Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/inc/fx_directory.h
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/inc/fx_directory.h	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/inc/fx_directory.h	(revision 57)
@@ -0,0 +1,137 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_directory.h                                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the FileX Directory component constants, data     */
+/*    definitions, and external references.  It is assumed that fx_api.h  */
+/*    (and fx_port.h) have already been included.                         */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_DIRECTORY_H
+#define FX_DIRECTORY_H
+
+
+/* Define the external Directory component function prototypes.  */
+
+UINT _fx_directory_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr);
+UINT _fx_directory_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes);
+UINT _fx_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT _fx_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT _fx_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name);
+UINT _fx_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_entry_read_FAT(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry_ptr,
+                                  FX_DIR_ENTRY *destination_ptr);
+UINT _fx_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_first_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                         ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fx_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes, ULONG *size,
+                                   UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fx_directory_local_path_clear(FX_MEDIA *media_ptr);
+UINT _fx_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT _fx_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT _fx_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr);
+UINT _fx_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name);
+UINT _fx_directory_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name);
+UINT _fx_directory_long_name_get_extended(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name, UINT long_file_name_buffer_length);
+UINT _fx_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fx_directory_next_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                        ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fx_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name);
+UINT _fx_directory_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name);
+UINT _fx_directory_short_name_get_extended(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name, UINT short_file_name_length);
+
+UINT _fxe_directory_attributes_read(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes_ptr);
+UINT _fxe_directory_attributes_set(FX_MEDIA *media_ptr, CHAR *directory_name, UINT attributes);
+UINT _fxe_directory_create(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_default_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT _fxe_directory_default_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT _fxe_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name);
+UINT _fxe_directory_delete(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_first_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                          ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fxe_directory_information_get(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes, ULONG *size,
+                                    UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fxe_directory_local_path_clear(FX_MEDIA *media_ptr);
+UINT _fxe_directory_local_path_get(FX_MEDIA *media_ptr, CHAR **return_path_name);
+UINT _fxe_directory_local_path_get_copy(FX_MEDIA *media_ptr, CHAR *return_path_name_buffer, UINT return_path_name_buffer_size);
+UINT _fxe_directory_local_path_restore(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr);
+UINT _fxe_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name, UINT local_path_control_block_size);
+UINT _fxe_directory_long_name_get(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name);
+UINT _fxe_directory_long_name_get_extended(FX_MEDIA *media_ptr, CHAR *short_file_name, CHAR *long_file_name, UINT long_file_name_buffer_length);
+UINT _fxe_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name);
+UINT _fxe_directory_next_full_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name, UINT *attributes,
+                                         ULONG *size, UINT *year, UINT *month, UINT *day, UINT *hour, UINT *minute, UINT *second);
+UINT _fxe_directory_rename(FX_MEDIA *media_ptr, CHAR *old_directory_name, CHAR *new_directory_name);
+UINT _fxe_directory_short_name_get(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name);
+UINT _fxe_directory_short_name_get_extended(FX_MEDIA *media_ptr, CHAR *long_file_name, CHAR *short_file_name, UINT short_file_name_length);
+
+
+/* Define the internal Directory component function prototypes.  */
+#ifdef FX_ENABLE_EXFAT
+#define UPDATE_DELETE (0)
+#define UPDATE_FILE   (1)
+#define UPDATE_STREAM (2)
+#define UPDATE_NAME   (3)
+#define UPDATE_FULL   (4)
+
+UINT _fx_directory_entry_read_ex(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry, FX_DIR_ENTRY *destination_ptr, UINT hash);
+UINT _fx_directory_exFAT_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr, UINT hash, UINT skip, UCHAR *unicode_name, UINT *unicode_len);
+UINT _fx_directory_exFAT_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR update_level);
+UINT _fx_directory_exFAT_unicode_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR update_level, USHORT *unicode_name,
+                                             UINT unicode_len);
+UINT _fx_directory_exFAT_free_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, FX_DIR_ENTRY *entry_ptr);
+
+#endif /* FX_ENABLE_EXFAT */
+
+UINT  _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir, ULONG *entry, FX_DIR_ENTRY *destination_ptr);
+UINT  _fx_directory_entry_write(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr);
+UINT  _fx_directory_free_search(FX_MEDIA *media_ptr, FX_DIR_ENTRY *directory_ptr, FX_DIR_ENTRY *entry_ptr);
+CHAR *_fx_directory_name_extract(CHAR *source_ptr, CHAR *dest_ptr);
+UINT  _fx_directory_search(FX_MEDIA *media_ptr, CHAR *name_ptr, FX_DIR_ENTRY *entry_ptr, FX_DIR_ENTRY *last_dir_ptr, CHAR **last_name_ptr);
+
+#endif
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/inc/fx_media.h
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/inc/fx_media.h	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/inc/fx_media.h	(revision 57)
@@ -0,0 +1,114 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  COMPONENT DEFINITION                                   RELEASE        */
+/*                                                                        */
+/*    fx_media.h                                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This file defines the FileX Media component constants, data         */
+/*    definitions, and external references.  It is assumed that fx_api.h  */
+/*    (and fx_port.h) have already been included.                         */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef FX_MEDIA_H
+#define FX_MEDIA_H
+
+
+/* Define the external Media component function prototypes.  */
+
+UINT _fx_media_abort(FX_MEDIA *media_ptr);
+UINT _fx_media_cache_invalidate(FX_MEDIA *media_ptr);
+UINT _fx_media_check(FX_MEDIA *media_ptr, UCHAR *scratch_memory_ptr, ULONG scratch_memory_size, ULONG error_correction_option, ULONG *errors_detected);
+UINT _fx_media_close(FX_MEDIA *media_ptr);
+UINT _fx_media_flush(FX_MEDIA *media_ptr);
+UINT _fx_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                      CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
+                      ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
+                      UINT heads, UINT sectors_per_track);
+UINT _fx_media_exFAT_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                            CHAR *volume_name, UINT number_of_fats, ULONG64 hidden_sectors, ULONG64 total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster, UINT volume_serial_number, UINT boundary_unit);
+UINT _fx_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
+                    VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
+                    VOID *memory_ptr, ULONG memory_size);
+UINT _fx_media_read(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT _fx_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr);
+UINT _fx_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source);
+UINT _fx_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source);
+UINT _fx_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name);
+UINT _fx_media_write(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT _fx_media_open_notify_set(FX_MEDIA *media_ptr, VOID (*media_open_notify)(FX_MEDIA *));
+UINT _fx_media_close_notify_set(FX_MEDIA *media_ptr, VOID (*media_close_notify)(FX_MEDIA *));
+UINT _fx_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr);
+
+
+UINT _fxe_media_abort(FX_MEDIA *media_ptr);
+UINT _fxe_media_cache_invalidate(FX_MEDIA *media_ptr);
+UINT _fxe_media_check(FX_MEDIA *media_ptr, UCHAR *scratch_memory_ptr, ULONG scratch_memory_size, ULONG error_correction_option, ULONG *errors_detected);
+UINT _fxe_media_close(FX_MEDIA *media_ptr);
+UINT _fxe_media_flush(FX_MEDIA *media_ptr);
+UINT _fxe_media_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                       CHAR *volume_name, UINT number_of_fats, UINT directory_entries, UINT hidden_sectors,
+                       ULONG total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster,
+                       UINT heads, UINT sectors_per_track);
+UINT _fxe_media_exFAT_format(FX_MEDIA *media_ptr, VOID (*driver)(FX_MEDIA *media), VOID *driver_info_ptr, UCHAR *memory_ptr, UINT memory_size,
+                             CHAR *volume_name, UINT number_of_fats, ULONG64 hidden_sectors, ULONG64 total_sectors, UINT bytes_per_sector, UINT sectors_per_cluster, UINT volume_serial_number, UINT boundary_unit);
+UINT _fxe_media_open(FX_MEDIA *media_ptr, CHAR *media_name,
+                     VOID (*media_driver)(FX_MEDIA *), VOID *driver_info_ptr,
+                     VOID *memory_ptr, ULONG memory_size, UINT media_control_block_size);
+UINT _fxe_media_read(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT _fxe_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr);
+UINT _fxe_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source);
+UINT _fxe_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source);
+UINT _fxe_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name);
+UINT _fxe_media_write(FX_MEDIA *media_ptr, ULONG logical_sector, VOID *buffer_ptr);
+UINT _fxe_media_open_notify_set(FX_MEDIA *media_ptr, VOID (*media_open_notify)(FX_MEDIA *));
+UINT _fxe_media_close_notify_set(FX_MEDIA *media_ptr, VOID (*media_close_notify)(FX_MEDIA *));
+UINT _fxe_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr);
+
+
+/* Define the internal Media component function prototypes.  */
+
+ULONG _fx_media_check_FAT_chain_check(FX_MEDIA *media_ptr, ULONG starting_cluster, ULONG *last_valid_cluster, ULONG *total_valid_clusters, UCHAR *logical_fat);
+ULONG _fx_media_check_lost_cluster_check(FX_MEDIA *media_ptr, UCHAR *logical_fat, ULONG total_clusters, ULONG error_correction_option);
+ULONG _fx_media_check_exFAT_lost_cluster_check(FX_MEDIA *media_ptr, UCHAR *logical_fat, ULONG total_clusters, ULONG error_correction_option);
+UINT  _fx_media_boot_info_extract(FX_MEDIA *media_ptr);
+
+#endif
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_entry_read.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_entry_read.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_entry_read.c	(revision 57)
@@ -0,0 +1,786 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+
+
+
+#endif /* FX_ENABLE_EXFAT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_entry_read                            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the supplied directory entry from the supplied  */
+/*    source directory.  If the supplied directory entry is NULL, then    */
+/*    the root directory is assumed.                                      */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    source_dir                            Source directory entry        */
+/*    entry_ptr                             Directory entry number        */
+/*    destination_ptr                       Pointer to destination for    */
+/*                                            the directory entry         */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*    *entry_ptr should point to the 8:3 entry if it is a long name       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_exFAT_entry_read        Read exFAT entries            */
+/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
+/*    _fx_utility_logical_sector_read       Read directory sector         */
+/*    _fx_utility_16_unsigned_read          Read a UINT from memory       */
+/*    _fx_utility_32_unsigned_read          Read a ULONG from memory      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+#ifdef FX_ENABLE_EXFAT
+UINT  _fx_directory_entry_read_FAT(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                                   ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
+#else
+UINT  _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                               ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
+#endif /* FX_ENABLE_EXFAT */
+{
+
+UINT   i, j, card, dotflag, get_short_name;
+UINT   number_of_lfns;
+UINT   status;
+ULONG  cluster, next_cluster = 0;
+UINT   relative_cluster;
+UINT   relative_sector;
+ULONG  logical_sector;
+ULONG  byte_offset;
+ULONG  bytes_per_cluster;
+UCHAR *read_ptr;
+CHAR  *short_name_ptr;
+ULONG  entry = *entry_ptr;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of directory entry read requests.  */
+    media_ptr -> fx_media_directory_entry_reads++;
+#endif
+
+    /* Extended port-specific processing macro, which is by default defined to white space.  */
+    FX_DIRECTORY_ENTRY_READ_EXTENSION
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_ENTRY_READ, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Calculate the byte offset of this directory entry.  */
+    byte_offset =  entry * FX_DIR_ENTRY_SIZE;
+
+    /* Determine if a sub-directory or FAT32 root directory is specified.  */
+#ifdef FX_ENABLE_EXFAT
+    if ((source_dir) || (media_ptr -> fx_media_FAT_type == FX_FAT32))
+#else
+    if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
+#endif
+    {
+
+        /* Yes, a sub-directory is present.  */
+
+        /* Calculate the number of bytes per cluster.  */
+        bytes_per_cluster =  ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
+            ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
+
+        /* Check for invalid value.  */
+        if (bytes_per_cluster == 0)
+        {
+
+            /* Invalid media, return error.  */
+            return(FX_MEDIA_INVALID);
+        }
+
+        /* Now determine the relative cluster in the sub-directory file.  */
+        relative_cluster =   (UINT)(byte_offset / bytes_per_cluster);
+
+        /* Calculate the byte offset within the cluster.  */
+        byte_offset =  byte_offset % bytes_per_cluster;
+
+        /* Now figure out the relative sector within the cluster.  */
+        relative_sector =    (UINT)(byte_offset / ((ULONG)media_ptr -> fx_media_bytes_per_sector));
+
+        /* Read the directory sector into the internal memory buffer.  */
+
+        /* Determine if there is a sub-directory.  */
+        if (source_dir)
+        {
+
+            /* Determine if this source directory has valid information from the previous call.  */
+            if ((source_dir -> fx_dir_entry_last_search_cluster) &&
+                (source_dir -> fx_dir_entry_last_search_relative_cluster <= relative_cluster) &&
+                (source_dir -> fx_dir_entry_last_search_log_sector == source_dir -> fx_dir_entry_log_sector) &&
+                (source_dir -> fx_dir_entry_last_search_byte_offset == source_dir -> fx_dir_entry_byte_offset))
+            {
+
+                /* Use the previous information to start the search.  */
+                cluster =  source_dir -> fx_dir_entry_last_search_cluster;
+
+                /* Setup the relative cluster index to the saved relative cluster.  */
+                i =  source_dir -> fx_dir_entry_last_search_relative_cluster;
+
+                /* Clear the search cluster.  It will be updated prior to successful return.  */
+                source_dir -> fx_dir_entry_last_search_cluster =  0;
+            }
+            else
+            {
+
+                /* Nothing from the previous directory read, just setup the starting cluster to the
+                   beginning of the sub-directory.  */
+                cluster =  source_dir -> fx_dir_entry_cluster;
+
+                /* Setup the relative cluster index to zero.  */
+                i =  0;
+            }
+        }
+        else
+        {
+
+            /* No, setup the starting cluster to the FAT32 root cluster.  */
+            cluster =  media_ptr -> fx_media_root_cluster_32;
+
+            /* Setup the relative cluster index to zero.  */
+            i =  0;
+        }
+
+        /* Loop to position to the appropriate cluster.  */
+        while (i < relative_cluster)
+        {
+
+            /* Check the value of the new cluster - it must be a valid cluster number
+               or something is really wrong!  */
+            if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
+            {
+
+                /* Send error message back to caller.  */
+                return(FX_FILE_CORRUPT);
+            }
+
+            /* Read the next cluster.  */
+            status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+            /* There is a potential for loop, but hardly anything can be done */
+
+            /* Check for I/O error.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Return error code.  */
+                return(status);
+            }
+
+            /* Setup the actual cluster.  */
+            cluster = next_cluster;
+
+            /* Increment the relative cluster number.  */
+            i++;
+        }
+
+        /* At this point, the directory data sector needs to be read.  */
+        logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
+            (((ULONG)cluster - FX_FAT_ENTRY_START) *
+             ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
+            relative_sector;
+
+        /* Read the logical directory sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return error code.  */
+            return(status);
+        }
+
+        /* Calculate the byte offset within this sector.  */
+        byte_offset =  byte_offset % media_ptr -> fx_media_bytes_per_sector;
+    }
+    else
+    {
+
+        /* Read the entry from the root directory.  */
+
+        /* Determine which sector the requested root directory entry is in.  */
+        logical_sector =  (byte_offset / media_ptr -> fx_media_bytes_per_sector) +
+            (ULONG)media_ptr -> fx_media_root_sector_start;
+
+        /* Read the logical directory sector.  */
+        status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                  media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+        /* Determine if an error occurred.  */
+        if (status != FX_SUCCESS)
+        {
+
+            /* Return error code.  */
+            return(status);
+        }
+
+        /* Set the cluster and relative variables (not used in this case) to avoid any compiler
+           warnings.  */
+        relative_cluster =  relative_sector =  cluster =  0;
+
+        /* Now calculate the byte offset into this sector.  */
+        byte_offset =  byte_offset -
+            ((logical_sector - (ULONG)media_ptr -> fx_media_root_sector_start) *
+             media_ptr -> fx_media_bytes_per_sector);
+    }
+
+    /* Setup a pointer into the buffer.  */
+    read_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT)byte_offset;
+
+    /* Save the logical sector and byte offset in the returned directory entry.  */
+    destination_ptr -> fx_dir_entry_log_sector =       logical_sector;
+    destination_ptr -> fx_dir_entry_byte_offset =      byte_offset;
+
+    /* Clear the short file name information.  */
+    destination_ptr -> fx_dir_entry_long_name_shorted =  0;
+    destination_ptr -> fx_dir_entry_short_name[0]     =  0;
+
+    /* Setup short name pointer.  */
+    short_name_ptr =  destination_ptr -> fx_dir_entry_name;
+
+    /* Check if long file name exists.  */
+    get_short_name =  0;
+    if ((*(read_ptr + 11) == (UCHAR)FX_LONG_NAME) && (*read_ptr != (UCHAR)FX_DIR_ENTRY_FREE))
+    {
+
+        /* Collate the long name. */
+
+        /* Pickup the file name length.  */
+        i = (((UINT)(*read_ptr & (UCHAR)0x1f) - 1) * FX_LONG_NAME_ENTRY_LEN) & 0xFFFFFFFF;
+
+        /* Save the number of LFN entries.  */
+        number_of_lfns =  (UINT)(*read_ptr & (UCHAR)0x1f);
+
+        /* Check the file name size.  */
+        if (i >= (FX_MAX_LONG_NAME_LEN - 1))
+        {
+
+            /* Name is too big, shorten it.  */
+            get_short_name = 1;
+            destination_ptr -> fx_dir_entry_long_name_shorted =  (UINT)(*read_ptr & (UCHAR)0x1f);
+        }
+        else
+        {
+
+            /* Size of name is fine, save pointer to short file name.  */
+            short_name_ptr = destination_ptr -> fx_dir_entry_short_name;
+
+            /* Loop to make sure the long file name is NULL terminated.  */
+            j = i + FX_LONG_NAME_ENTRY_LEN + 1;
+            do
+            {
+                /* Place a NULL in the long name.  */
+                destination_ptr -> fx_dir_entry_name[i] =  0;
+
+                /* Position to the next entry.  */
+                i++;
+            } while ((i < j) && (i < FX_MAX_LONG_NAME_LEN));
+        }
+
+        /* Loop to pickup the rest of the name.  */
+        do
+        {
+
+            /* Get the lower 5 bit containing the cardinality.  */
+            card = (UINT)(*read_ptr & (UCHAR)0x1f) - 1;
+
+            /* For simplicity no checksum or cardinality checking is done */
+            if (get_short_name == 0)
+            {
+
+                /* Loop to pickup name.  */
+                for (i = 1, j = 0; i < FX_DIR_ENTRY_SIZE; i += 2)
+                {
+
+                    if ((i == 11) || (i == 26))
+                    {
+                        continue;
+                    }
+
+                    /* i = 12, 27 is not generated due to +=2 */
+                    if (i == 13)
+                    {
+                        i = 12;
+                        continue; /* this time next unicode is byte offset 14*/
+                    }
+
+                    /* Determine if there is an actual unicode character present.  */
+                    if (read_ptr[i + 1])
+                    {
+
+                        /* Extended byte is non-zero, make sure both bytes of the unicode entry are not
+                           all ones, since this is a normal case.  */
+                        if ((read_ptr[i + 1] != (UCHAR)0xFF) || (read_ptr[i] != (UCHAR)0xFF))
+                        {
+
+                            /* Name is an actual unicode name, shorten it.  */
+                            get_short_name = 1;
+
+                            /* Save the number of directory entries the LFN has.  This will be
+                               used later when updating the 8.3 portion of the LFN.  */
+                            destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
+
+                            /* Setup short name pointer.  */
+                            short_name_ptr =  destination_ptr -> fx_dir_entry_name;
+                        }
+                    }
+
+                    /* Determine if the character is NULL.  */
+                    if ((read_ptr[i] == FX_NULL) || (read_ptr[i] == (UCHAR)0xFF))
+                    {
+                        continue;
+                    }
+
+                    /* Determine if the name is too big.  */
+                    if ((card * 13 + j) >= (FX_MAX_LONG_NAME_LEN - 1))
+                    {
+
+                        /* Name is actually too big, shorten it.  */
+                        get_short_name =  1;
+
+                        /* Save the number of directory entries the LFN has.  This will be
+                           used later when updating the 8.3 portion of the LFN.  */
+                        destination_ptr -> fx_dir_entry_long_name_shorted =  number_of_lfns;
+
+                        /* Also reposition the short name pointer.  */
+                        short_name_ptr =  destination_ptr -> fx_dir_entry_name;
+
+                        break;
+                    }
+
+                    /* Each entry contains 13 unicode and first byte ASCII, second byte is extended. */
+                    destination_ptr -> fx_dir_entry_name[13 * card + j] = (CHAR)read_ptr[i];
+
+                    j++;
+                }
+            }
+
+            /* Determine if a new sector needs to be read.  */
+            if (byte_offset + FX_DIR_ENTRY_SIZE >= media_ptr -> fx_media_bytes_per_sector)
+            {
+
+                /* Determine if a sub-directory or FAT32 root directory is specified.  */
+                if ((source_dir) || (media_ptr -> fx_media_32_bit_FAT))
+                {
+
+                    /* Determine the next sector of the directory entry.  */
+                    if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
+                    {
+
+                        /* More sectors in this cluster.  */
+
+                        /* Simply increment the logical sector.  */
+                        logical_sector++;
+
+                        /* Increment the relative sector.  */
+                        relative_sector++;
+                    }
+                    else
+                    {
+
+                        /* We need to move to the next cluster.  */
+
+                        /* Pickup the next cluster.  */
+                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                        /* Check for I/O error.  */
+                        if (status != FX_SUCCESS)
+                        {
+
+                            /* Return error code.  */
+                            return(status);
+                        }
+
+                        /* Copy next cluster to the current cluster.  */
+                        cluster =  next_cluster;
+
+                        /* Check the value of the new cluster - it must be a valid cluster number
+                           or something is really wrong!  */
+                        if ((cluster < FX_FAT_ENTRY_START) || (cluster >= media_ptr -> fx_media_fat_reserved))
+                        {
+
+                            /* Send error message back to caller.  */
+                            return(FX_FILE_CORRUPT);
+                        }
+
+                        /* Now increment the relative cluster.  */
+                        relative_cluster++;
+
+                        /* Setup the relative sector (this is zero for subsequent cluster.  */
+                        relative_sector =  0;
+
+                        /* Calculate the next logical sector.  */
+                        logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
+                            (((ULONG)cluster - FX_FAT_ENTRY_START) *
+                             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
+                    }
+                }
+                else
+                {
+
+                    /* Non-FAT 32 root directory.  */
+
+                    /* Advance to the next sector.  */
+                    logical_sector++;
+
+                    /* Determine if the logical sector is valid.  */
+                    if (logical_sector >= (ULONG)(media_ptr -> fx_media_root_sector_start + media_ptr -> fx_media_root_sectors))
+                    {
+
+                        /* Trying to read past root directory - send error message back to caller.  */
+                        return(FX_FILE_CORRUPT);
+                    }
+                }
+
+                /* Read the new sector.  */
+                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
+                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+                /* Check I/O status.  */
+                if (status != FX_SUCCESS)
+                {
+                    return(status);
+                }
+
+                /* Set the byte offset to 0 for new sector.  */
+                byte_offset = 0;
+            }
+            else
+            {
+
+                /* Calculate the new byte offset.  */
+                byte_offset += FX_DIR_ENTRY_SIZE;
+            }
+
+            /* Calculate the next read pointer.  */
+            read_ptr =  (UCHAR *)media_ptr -> fx_media_memory_buffer + (UINT) byte_offset;
+
+            /* Move to the next entry.  */
+            entry++;
+        } while (card > 0);
+
+        /* Set flag indicating long file name is present.  */
+        destination_ptr -> fx_dir_entry_long_name_present = 1;
+    }
+    else
+    {
+        /* No long file name is present.  */
+        get_short_name = 1;
+    }
+
+    /* Determine if we need to clear the long name flag.  */
+    if (get_short_name == 1)
+    {
+
+        /* Clear the long name flag.  */
+        destination_ptr -> fx_dir_entry_long_name_present =  0;
+    }
+
+    /* Pickup the short file name.  */
+    short_name_ptr[0] =  0;
+    dotflag =  0;
+    for (i = 0, j = 0; i < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); i++)
+    {
+
+        /* Check for a NULL.  */
+        if ((CHAR)read_ptr[i] == 0)
+        {
+            break;
+        }
+
+        /* Check for a dot.  This happens for the first two directory entries, no
+           extra dot is needed.  */
+        if ((CHAR)read_ptr[i] == '.')
+        {
+            dotflag =  2;
+        }
+
+        /* Check for a space.  */
+        if ((CHAR)read_ptr[i] == ' ')
+        {
+            /* Put a dot if a character comes after space.  */
+            if (dotflag == 0)
+            {
+                dotflag =  1;
+            }
+            continue;
+        }
+
+        /* Check for the main short file name size.  */
+        if (i == FX_DIR_NAME_SIZE)
+        {
+            /* Check to see if we need to insert a dot.  */
+            if (dotflag == 0)
+            {
+                dotflag =  1;
+            }
+        }
+
+        /* Check to see if we need to add a dot.  */
+        if (dotflag == 1)
+        {
+            /* Add dot to short file name.  */
+            short_name_ptr[j++] =  '.';
+            dotflag =  2;    /* no more dot for spaces */
+        }
+
+        /* Copy a character.  */
+        short_name_ptr[j] =  (CHAR)read_ptr[i];
+
+        /* Increment size.  */
+        j++;
+    }
+
+    /* Determine if a long file name is present and its associated short file
+       name is actually free.  */
+    if ((destination_ptr -> fx_dir_entry_long_name_present) && (((UCHAR)short_name_ptr[0]) == (UCHAR)FX_DIR_ENTRY_FREE))
+    {
+
+        /* Yes, the short file name is really free even though long file name entries directly precede it.
+           In this case, simply place the free directory marker at the front of the long file name.  */
+        destination_ptr -> fx_dir_entry_name[0] =  (CHAR)FX_DIR_ENTRY_FREE;
+        short_name_ptr[0] =  (CHAR)0;
+    }
+
+    /* Determine if the short name pointer is NULL while the read pointer is
+       non-NULL.  */
+    if ((short_name_ptr[0] == 0) && (read_ptr[0] == ' '))
+    {
+
+        /* This condition can occur with an all blank volume name.  Simply
+           copy the volume name to the short name in this case.  */
+        for (j = 0; j < (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE); j++)
+        {
+
+            /* Copy a byte of the volume name.  */
+            short_name_ptr[j] =  (CHAR)read_ptr[j];
+        }
+    }
+
+    /* Set end of string to null.  */
+    short_name_ptr[j] = 0;
+
+    /* Load up the destination directory entry.  */
+    read_ptr += (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE);
+
+    /* Copy the attribute into the destination.  */
+    destination_ptr -> fx_dir_entry_attributes =  *read_ptr++;
+
+    /* Pickup the reserved byte.  */
+    destination_ptr -> fx_dir_entry_reserved =  *read_ptr++;
+
+    /* Check for an undocumented NT file name feature for optimizing the storage
+       of all lower case file names that otherwise are valid 8.3 file names. The
+       following reserved bit definitions are present:
+
+         BIT3 - set if 8.3 is all in lower case and no extended filename.
+         BIT4 - set for file, clear for directory entry if no extended filename.
+
+       This is true for all NT systems. Prior to NT follows MSDOS FAT documentation and
+       is set to 0x00, all bits cleared. Therefore if BIT3 is set force lowercase.  */
+    if ((get_short_name) && (destination_ptr -> fx_dir_entry_reserved & 0x08))
+    {
+
+        /* Microsoft undocumented NT file name feature... convert short name to lower
+           case.  */
+        for (j = 0; j <= (FX_DIR_NAME_SIZE + FX_DIR_EXT_SIZE) && (short_name_ptr[j] != 0x00); j++)
+        {
+
+            /* Determine if an upper case character is present.  */
+            if ((short_name_ptr[j] >= 'A') && (short_name_ptr[j] <= 'Z'))
+            {
+
+                /* Yes, an upper case character is present. Force it to lower case.  */
+                short_name_ptr[j] =  (CHAR)(short_name_ptr[j] + 32);
+            }
+        }
+    }
+
+    /* Pickup the created time in milliseconds.  */
+    destination_ptr -> fx_dir_entry_created_time_ms =  *read_ptr++;
+
+    /* Pickup the created time.  */
+    destination_ptr -> fx_dir_entry_created_time =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Pickup the created date.  */
+    destination_ptr -> fx_dir_entry_created_date =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Pickup the last accessed date.  */
+    destination_ptr -> fx_dir_entry_last_accessed_date =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* read the upper 2 bytes of starting cluster - required only for 32 bit FAT */
+    if (media_ptr -> fx_media_32_bit_FAT)
+    {
+
+        /* FAT32 only.  */
+        destination_ptr -> fx_dir_entry_cluster =  _fx_utility_16_unsigned_read(read_ptr);
+        destination_ptr -> fx_dir_entry_cluster <<= 16;
+    }
+    else
+    {
+        /* Not required for non FAT32.  */
+        destination_ptr -> fx_dir_entry_cluster =  0;
+    }
+
+    /* Advance the read pointer.  */
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the time into the destination.  */
+    destination_ptr -> fx_dir_entry_time =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the date into the destination.  */
+    destination_ptr -> fx_dir_entry_date =  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the starting cluster into the destination.  */
+    destination_ptr -> fx_dir_entry_cluster +=  _fx_utility_16_unsigned_read(read_ptr);
+    read_ptr =  read_ptr + 2;  /* Always 2 bytes */
+
+    /* Copy the file size into the destination.  */
+    destination_ptr -> fx_dir_entry_file_size =  _fx_utility_32_unsigned_read(read_ptr);
+
+    /* Clear the destination search specific fields.  */
+    destination_ptr -> fx_dir_entry_last_search_cluster =           0;
+    destination_ptr -> fx_dir_entry_last_search_relative_cluster =  0;
+    destination_ptr -> fx_dir_entry_last_search_log_sector =        0;
+    destination_ptr -> fx_dir_entry_last_search_byte_offset =       0;
+
+    /* Remember the entry number.  */
+    destination_ptr -> fx_dir_entry_number =  entry;
+
+    /* Return entry number.  */
+    *entry_ptr =  entry;
+
+    /* Determine if we should remember the last cluster and relative cluster.  */
+    if (source_dir)
+    {
+
+        /* Yes, remember the last cluster and relative cluster for a subsequent call
+           to read a directory entry.  */
+        source_dir -> fx_dir_entry_last_search_cluster =           cluster;
+        source_dir -> fx_dir_entry_last_search_relative_cluster =  relative_cluster;
+
+        /* Also remember several other items that are unique to the directory... just to verify that the
+           search information can be used.  */
+        source_dir -> fx_dir_entry_last_search_log_sector =        source_dir -> fx_dir_entry_log_sector;
+        source_dir -> fx_dir_entry_last_search_byte_offset =       source_dir -> fx_dir_entry_byte_offset;
+    }
+#ifdef FX_ENABLE_EXFAT
+    destination_ptr -> fx_dir_entry_dont_use_fat = 0;
+
+    /* If a file whose first byte of long name is read, fx_dir_entry_short_name will not be empty. */
+    /* If a free dir_entry is obtained, fx_dir_entry_short_name[0] will not be assigned as 0 around Line 623 in this file. */
+    /* If there is only a free dir_entry without front long name dir_entries, fx_dir_entry_name[0] will be assigned by the loop around Line 568. */
+    if (((UCHAR)destination_ptr -> fx_dir_entry_name[0] == FX_DIR_ENTRY_FREE) && ((UCHAR)destination_ptr -> fx_dir_entry_short_name[0] == 0))
+    {
+        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_FREE;
+    }
+    else if ((UCHAR)destination_ptr -> fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
+    {
+        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER;
+    }
+    else
+    {
+        destination_ptr -> fx_dir_entry_type = FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY;
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Return success to the caller.  */
+    return(FX_SUCCESS);
+}
+
+
+#ifdef FX_ENABLE_EXFAT
+UINT  _fx_directory_entry_read_ex(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                                  ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr, UINT hash)
+{
+UINT status = FX_SUCCESS;
+
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        status =
+            _fx_directory_exFAT_entry_read(
+                media_ptr, source_dir, entry_ptr, destination_ptr, hash, FX_FALSE, NULL, NULL);
+    }
+    else
+    {
+        status =
+            _fx_directory_entry_read_FAT(media_ptr, source_dir, entry_ptr, destination_ptr);
+    }
+
+    return(status);
+}
+
+
+UINT  _fx_directory_entry_read(FX_MEDIA *media_ptr, FX_DIR_ENTRY *source_dir,
+                               ULONG *entry_ptr, FX_DIR_ENTRY *destination_ptr)
+{
+
+    return(_fx_directory_entry_read_ex(media_ptr, source_dir, entry_ptr, destination_ptr, 0));
+}
+#endif /* FX_ENABLE_EXFAT */
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_first_entry_find.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_first_entry_find.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_first_entry_find.c	(revision 57)
@@ -0,0 +1,136 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_first_entry_find                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the first directory entry of the current      */
+/*    working directory.                                                  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_next_entry_find         Find next directory entry     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_first_entry_finds++;
+#endif
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_FIRST_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Determine if a local path is in effect at this point.  */
+#ifndef FX_NO_LOCAL_PATH
+    if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+    {
+
+        /* Yes, there is a local path.  Set the current entry to zero.  */
+        ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_current_entry =  0;
+    }
+    else
+    {
+
+        /* Use global default directory.  Set the current entry to 0 in
+           order to pickup the first entry.  */
+        media_ptr -> fx_media_default_path.fx_path_current_entry =  0;
+    }
+#else
+
+    /* Set the current entry to 0 in order to pickup the first entry.  */
+    media_ptr -> fx_media_default_path.fx_path_current_entry =  0;
+#endif
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Call the next directory entry to pickup the first entry.  */
+    status =  _fx_directory_next_entry_find(media_ptr, directory_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_extract.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_extract.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_extract.c	(revision 57)
@@ -0,0 +1,161 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_name_extract                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function extracts the file name from the supplied input        */
+/*    string.  If there is nothing left after the extracted name, a NULL  */
+/*    is returned to the caller.  Otherwise, if something is left, a      */
+/*    pointer to it is returned.                                          */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    source_ptr                           Source string pointer          */
+/*    dest_ptr                             Destination string pointer     */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    Pointer to Next Name                 (if multiple directories)      */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+CHAR  *_fx_directory_name_extract(CHAR *source_ptr, CHAR *dest_ptr)
+{
+
+UINT i;
+
+
+    /* Set the destination string to NULL.  */
+    dest_ptr[0] = 0;
+
+    /* Is a backslash present?  */
+    if ((*source_ptr == '\\') || (*source_ptr == '/'))
+    {
+
+        /* Advance the string pointer.  */
+        source_ptr++;
+    }
+
+    /* Loop to remove any leading spaces.  */
+    while (*source_ptr == ' ')
+    {
+
+        /* Position past leading space.  */
+        source_ptr++;
+    }
+
+    /* Loop to extract the name.  */
+    i = 0;
+    while (*source_ptr)
+    {
+
+        /* If another backslash is present, break the loop.  */
+        if ((*source_ptr == '\\') || (*source_ptr == '/'))
+        {
+            break;
+        }
+
+        /* Long name can be at most 255 characters, but are further limited by the
+           FX_MAX_LONG_NAME_LEN define.  */
+        if (i == FX_MAX_LONG_NAME_LEN - 1)
+        {
+            break;
+        }
+
+        /* Store the character.  */
+        dest_ptr[i] =  *source_ptr++;
+
+        /* Increment the character counter.  */
+        i++;
+    }
+
+    /* NULL-terminate the string.  */
+    dest_ptr[i] =  0;
+
+    /* Determine if we can backup to the previous character.  */
+    if (i)
+    {
+
+        /* Yes, we can move backwards.  */
+        i--;
+    }
+
+    /* Get rid of trailing blanks in the destination string.  */
+    while (dest_ptr[i] == ' ')
+    {
+
+        /* Set this entry to NULL.  */
+        dest_ptr[i] =  0;
+
+        /* Backup to the next character. Since leading spaces have been removed,
+           we know that the index is always greater than 1.  */
+        i--;
+    }
+
+    /* Determine if the source string is now at the end.  */
+    if (*source_ptr == 0)
+    {
+
+        /* Yes, return a NULL pointer.  */
+        source_ptr = FX_NULL;
+    }
+
+    /* Return the last pointer position in the source.  */
+    return(source_ptr);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_test.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_test.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_name_test.c	(revision 57)
@@ -0,0 +1,143 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_file.h"
+#include "fx_utility.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_name_test                             PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function first attempts to find the specified directory name.  */
+/*    If found, the attributes are checked to see if the entry is a       */
+/*    directory.  If not, the appropriate error code is returned to the   */
+/*    caller.                                                             */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_search                  Search for the file name in   */
+/*                                          the directory structure       */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT         status;
+FX_DIR_ENTRY dir_entry;
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_name_tests++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    dir_entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_NAME_TEST, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Search the system for the supplied directory name.  */
+    status =  _fx_directory_search(media_ptr, directory_name, &dir_entry, FX_NULL, FX_NULL);
+
+    /* Determine if the search was successful.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error code.  */
+        return(status);
+    }
+
+    /* Check to see if the entry is a directory.  */
+    if (!(dir_entry.fx_dir_entry_attributes & (UCHAR)FX_DIRECTORY))
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the not a directory error code.  */
+        return(FX_NOT_DIRECTORY);
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Directory name test is complete, return successful status.  */
+    return(FX_SUCCESS);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_next_entry_find.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_next_entry_find.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_next_entry_find.c	(revision 57)
@@ -0,0 +1,471 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_next_entry_find                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the name of the next entry in the current     */
+/*    working directory.  The function that returns the first name in the */
+/*    current directory must be called prior to this function.            */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_entry_read              Read entries from root dir    */
+/*    _fx_utility_FAT_entry_read            Read FAT entries to calculate */
+/*                                            the sub-directory size      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code and                                                */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+ULONG         i;
+UINT          status;
+UINT          temp_status;
+ULONG         cluster, next_cluster = 0;
+ULONG64       directory_size;
+FX_DIR_ENTRY  entry;
+FX_DIR_ENTRY *search_dir_ptr;
+FX_PATH      *path_ptr;
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+UINT          index;
+CHAR         *path_string_ptr =  FX_NULL;
+#endif
+
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of times this service has been called.  */
+    media_ptr -> fx_media_directory_next_entry_finds++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
+
+    /* Clear the short name string.  */
+    entry.fx_dir_entry_short_name[0] =  0;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_NEXT_ENTRY_FIND, media_ptr, directory_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* First check for a local path pointer stored in the thread control block.  This
+       is only available in ThreadX Version 4 and above.  */
+
+#ifndef FX_NO_LOCAL_PATH
+
+    if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+    {
+
+        /* Setup the default path pointer.  */
+        path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
+
+        /* Determine if we are at the root directory.  */
+        if (path_ptr -> fx_path_directory.fx_dir_entry_name[0])
+        {
+
+            /* No, we are not at the root directory.  */
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+            /* Setup pointer to the path.  */
+            path_string_ptr =  ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
+#endif
+
+            /* Set the internal pointer to the search directory as well.  */
+            search_dir_ptr =  &(path_ptr -> fx_path_directory);
+        }
+        else
+        {
+
+            /* The current default directory is the root so just set the
+               search directory pointer to NULL.  */
+            search_dir_ptr =  FX_NULL;
+        }
+    }
+    else
+#endif
+
+    /* Set the initial search directory to the current working
+       directory - if there is one.  */
+    if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
+    {
+
+        /* Setup the path pointer to the global media path.  */
+        path_ptr =  &media_ptr -> fx_media_default_path;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+        /* Setup pointer to the path.  */
+        path_string_ptr =  media_ptr -> fx_media_default_path.fx_path_string;
+#endif
+
+        /* Set the internal pointer to the search directory as well.  */
+        search_dir_ptr =  &(path_ptr -> fx_path_directory);
+    }
+    else
+    {
+
+        /* Setup the path pointer to the global media path.  */
+        path_ptr =  &media_ptr -> fx_media_default_path;
+
+        /* The current default directory is the root so just set the
+           search directory pointer to NULL.  */
+        search_dir_ptr =  FX_NULL;
+    }
+
+    /* Calculate the directory size.  */
+    if (search_dir_ptr)
+    {
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+            directory_size = search_dir_ptr -> fx_dir_entry_file_size / FX_DIR_ENTRY_SIZE;
+        }
+        else
+        {
+#endif /* FX_ENABLE_EXFAT */
+            /* Determine the directory size.  */
+            if (path_ptr -> fx_path_current_entry != 0)
+            {
+
+                /* Pickup the previously saved directory size.  */
+                directory_size =  search_dir_ptr -> fx_dir_entry_file_size;
+            }
+            else
+            {
+
+                /* This should only be done on the first time into next directory find.  */
+
+                /* Ensure that the search directory's last search cluster is cleared.  */
+                search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+
+                /* Calculate the directory size by counting the allocated
+                   clusters for it. */
+                i =        0;
+                cluster =  search_dir_ptr -> fx_dir_entry_cluster;
+                while (cluster < media_ptr -> fx_media_fat_reserved)
+                {
+
+                    /* Increment the cluster count.  */
+                    i++;
+
+                    /* Read the next FAT entry.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                    /* Check the return status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+
+                    if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
+                    {
+
+                        /* Release media protection.  */
+                        FX_UNPROTECT
+
+                        /* Return the bad status.  */
+                        return(FX_FAT_READ_ERROR);
+                    }
+
+                    cluster = next_cluster;
+                }
+
+                /* Now we can calculate the directory size.  */
+                directory_size =  (((ULONG64)media_ptr -> fx_media_bytes_per_sector) *
+                                   ((ULONG64)media_ptr -> fx_media_sectors_per_cluster) * i) /
+                    (ULONG64)FX_DIR_ENTRY_SIZE;
+
+                /* Save how many entries there are in the directory.  */
+                search_dir_ptr -> fx_dir_entry_file_size =  directory_size;
+            }
+#ifdef FX_ENABLE_EXFAT
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+    else
+    {
+
+        /* Directory size is the number of entries in the root directory.  */
+        directory_size =  (ULONG)media_ptr -> fx_media_root_directory_entries;
+    }
+
+    /* Preset status with an error return.  */
+    status =  FX_NO_MORE_ENTRIES;
+
+    /* Determine if the current entry is inside of the directory's range.  */
+    while (path_ptr -> fx_path_current_entry < directory_size)
+    {
+
+        /* Read an entry from the directory.  */
+        temp_status =  _fx_directory_entry_read(media_ptr, search_dir_ptr,
+                                                &(path_ptr -> fx_path_current_entry), &entry);
+
+        /* Check for error status.  */
+        if (temp_status != FX_SUCCESS)
+        {
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return error status.  */
+            return(temp_status);
+        }
+#ifdef FX_ENABLE_EXFAT
+        if (entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER)
+        {
+            /* Set the error code.  */
+            status =  FX_NO_MORE_ENTRIES;
+
+            /* Get out of the loop.  */
+            break;
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        /* Check to see if the entry has something in it.  */
+#ifdef FX_ENABLE_EXFAT
+        else if (entry.fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY)
+#else
+        if (((UCHAR)entry.fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry.fx_dir_entry_short_name[0] == 0))
+#endif /* FX_ENABLE_EXFAT */
+        {
+
+            /* Current entry is free, skip to next entry and continue the loop.  */
+            path_ptr -> fx_path_current_entry++;
+            continue;
+        }
+#ifdef FX_ENABLE_EXFAT
+        else /* FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY */
+#else
+        else if ((UCHAR)entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_DONE)
+#endif /* FX_ENABLE_EXFAT */
+        {
+
+            /* A valid directory entry is present.  */
+
+            /* Copy the name into the destination.  */
+            for (i = 0; entry.fx_dir_entry_name[i]; i++)
+            {
+
+                *directory_name = entry.fx_dir_entry_name[i];
+                directory_name++;
+            }
+
+            /* Place a NULL at the end of the directory name.  */
+            *directory_name =  (CHAR)0;
+
+            /* Increment the current entry for the media.  */
+            path_ptr -> fx_path_current_entry++;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+            {
+            UINT v, j;
+
+
+                /* If a subsequent search for the same name is done, it will find it immediately.  */
+
+                /* Set the index of the saved name string.  */
+                v =  0;
+
+                /* First, build the full path and name.  */
+                if (path_string_ptr)
+                {
+
+                    /* Copy the path into the destination.  */
+                    while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_string_ptr[v]))
+                    {
+
+                        /* Copy one character.   */
+                        media_ptr -> fx_media_last_found_name[v] =  path_string_ptr[v];
+
+                        /* Move to next character.  */
+                        v++;
+                    }
+                }
+
+                /* We know there is room at this point, place a directory separator character.  */
+                media_ptr -> fx_media_last_found_name[v++] =  '/';
+
+                /* Now append the name to the path.  */
+                j =  0;
+                while ((v < FX_MAX_LAST_NAME_LEN) && (entry.fx_dir_entry_name[j]))
+                {
+
+                    /* Copy one character.   */
+                    media_ptr -> fx_media_last_found_name[v] =  entry.fx_dir_entry_name[j];
+
+                    /* Move to next character.  */
+                    v++;
+                    j++;
+                }
+
+                /* Null terminate the last name string.   */
+                if (v < FX_MAX_LAST_NAME_LEN)
+                {
+
+                    /* Null terminate.  */
+                    media_ptr -> fx_media_last_found_name[v] =  FX_NULL;
+                }
+                else
+                {
+
+                    /* The string is too big, NULL the string so it won't be used in searching.  */
+                    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+                }
+
+                /* Determine if there is a search pointer.  */
+                if (search_dir_ptr)
+                {
+
+                    /* Yes, there is a search directory pointer so save it!   */
+                    media_ptr -> fx_media_last_found_directory =  *search_dir_ptr;
+
+                    /* Indicate the search directory is valid.  */
+                    media_ptr -> fx_media_last_found_directory_valid =  FX_TRUE;
+                }
+                else
+                {
+
+                    /* Indicate the search directory is not valid.  */
+                    media_ptr -> fx_media_last_found_directory_valid =  FX_FALSE;
+                }
+
+                /* Copy the directory entry.  */
+                media_ptr -> fx_media_last_found_entry =  entry;
+
+                /* Setup the last found directory entry to point at the last found internal file name.  */
+                media_ptr -> fx_media_last_found_entry.fx_dir_entry_name =  media_ptr -> fx_media_last_found_file_name;
+
+                /* Copy the actual directory name into the cached directory name.  */
+                for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
+                {
+
+                    /* Copy character into the cached directory name.  */
+                    media_ptr -> fx_media_last_found_file_name[index] =  entry.fx_dir_entry_name[index];
+
+                    /* See if we have copied the NULL termination character.  */
+                    if (entry.fx_dir_entry_name[index] == (CHAR)FX_NULL)
+                    {
+                    
+                        /* Check to see if we use the break to get out of the loop.  */
+                        if (v < (FX_MAX_LONG_NAME_LEN - 1))
+                        {
+                        
+                            /* Yes, not at the end of the string, break.  */
+                            break;
+                        }
+                    }
+                }
+            }
+#endif
+
+            /* Set return status to success.  */
+            status =  FX_SUCCESS;
+
+            /* Get out of the loop.  */
+            break;
+        }
+#ifndef FX_ENABLE_EXFAT
+        else
+        {
+
+            /* Set the error code.  */
+            status =  FX_NO_MORE_ENTRIES;
+
+            /* Get out of the loop.  */
+            break;
+        }
+#endif /* FX_ENABLE_EXFAT */
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_search.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_search.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_directory_search.c	(revision 57)
@@ -0,0 +1,984 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_NO_LOCAL_PATH
+FX_LOCAL_PATH_SETUP
+#endif
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_directory_search                                PORTABLE C      */
+/*                                                           6.1.10       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function searches the media for the supplied name.  The search */
+/*    routine will find files as well as directory names.                 */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    name_ptr                              Name pointer                  */
+/*    entry_ptr                             Pointer to directory entry    */
+/*                                            record                      */
+/*    last_dir_ptr                          Pointer to destination for    */
+/*                                            the last directory entry    */
+/*    last_name_ptr                         Pointer to the last name      */
+/*                                            token that was searched for */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_name_extract            Extract directory name from   */
+/*                                            input string                */
+/*    _fx_directory_entry_read              Read entries from root dir    */
+/*    _fx_utility_exFAT_name_hash_get       Get name hash                 */
+/*    _fx_utility_FAT_entry_read            Read FAT entries to calculate */
+/*                                            the sub-directory size      */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    FileX System Functions                                              */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s), and      */
+/*                                            added conditional to        */
+/*                                            disable media search cache, */
+/*                                            resulting in version 6.1    */
+/*  06-02-2021     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            added check for             */
+/*                                            volume label,               */
+/*                                            resulting in version 6.1.7  */
+/*  01-31-2022     William E. Lamie         Modified comment(s), and      */
+/*                                            fixed path compare,         */
+/*                                            resulting in version 6.1.10 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_directory_search(FX_MEDIA *media_ptr, CHAR *name_ptr, FX_DIR_ENTRY *entry_ptr,
+                           FX_DIR_ENTRY *last_dir_ptr, CHAR **last_name_ptr)
+{
+
+ULONG         i, n;
+UINT          found;
+UINT          status;
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+UINT          v, j;
+#endif /* FX_MEDIA_DISABLE_SEARCH_CACHE */
+ULONG         cluster, next_cluster = 0;
+ULONG64       directory_size;
+CHAR         *dir_name_ptr;
+CHAR         *work_ptr;
+CHAR         *source_name_ptr;
+CHAR         *destination_name_ptr;
+FX_DIR_ENTRY  search_dir;
+FX_DIR_ENTRY *search_dir_ptr;
+CHAR         *name, alpha, name_alpha;
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+UINT          index;
+CHAR         *path_ptr =  FX_NULL;
+CHAR         *original_name =  name_ptr;
+#endif
+#ifdef FX_ENABLE_EXFAT
+USHORT        hash = 0;
+#endif /* FX_ENABLE_EXFAT */
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of directory search requests.  */
+    media_ptr -> fx_media_directory_searches++;
+#endif
+
+    /* Setup pointer to media name buffer.  */
+    name =  media_ptr -> fx_media_name_buffer;
+
+    /* Setup the last directory, if required.  */
+    if (last_dir_ptr)
+    {
+
+        /* Set the first character of the directory entry to NULL to
+           indicate root or no directory.  */
+        last_dir_ptr -> fx_dir_entry_name[0] =  0;
+    }
+
+    /* Determine if the file name has a full directory path.  */
+    if ((*name_ptr == '\\') || (*name_ptr == '/'))
+    {
+
+        /* Directory name has full path, set the search pointer to NULL.  */
+        search_dir_ptr =  FX_NULL;
+    }
+    else
+    {
+
+        /* Set the initial search directory to the current working
+           directory - if there is one.  */
+
+        /* First check for a local path pointer stored in the thread control block.  This
+           is only available in ThreadX Version 4 and above.  */
+#ifndef FX_NO_LOCAL_PATH
+        if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
+        {
+
+            /* Determine if the local directory is not the root directory.  */
+            if (((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory.fx_dir_entry_name[0])
+            {
+
+                /* Start at the current working directory of the media.  */
+                search_dir =   ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_directory;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+                /* Setup pointer to the path.  */
+                path_ptr =  ((FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string;
+#endif
+
+                /* Set the internal pointer to the search directory as well.  */
+                search_dir_ptr =  &search_dir;
+            }
+            else
+            {
+
+                /* We are searching in the root directory.  */
+                search_dir_ptr =  FX_NULL;
+            }
+        }
+        else
+#endif
+        if (media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0])
+        {
+
+            /* Start at the current working directory of the media.  */
+            search_dir =  media_ptr -> fx_media_default_path.fx_path_directory;
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+            /* Setup pointer to the path.  */
+            path_ptr =  media_ptr -> fx_media_default_path.fx_path_string;
+#endif
+
+            /* Set the internal pointer to the search directory as well.  */
+            search_dir_ptr =  &search_dir;
+        }
+        else
+        {
+
+            /* The current default directory is the root so just set the
+               search directory pointer to NULL.  */
+            search_dir_ptr =  FX_NULL;
+        }
+    }
+
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+    /* Determine if there is a previously found directory entry.  */
+    if (media_ptr -> fx_media_last_found_name[0])
+    {
+
+    UINT  match;
+    CHAR *temp_ptr, beta;
+
+        /* Yes, there is a previously found directory in our cache.  */
+
+        /* Initialize the index.  */
+        v =  0;
+
+        /* Determine if there is a full path.  */
+        if ((*name_ptr == '\\') || (*name_ptr == '/'))
+        {
+
+            /* Yes, the full path is in the name buffer. Simply compare with what is in
+               the last search buffer.  */
+            while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[v]))
+            {
+
+                /* Pickup the respective name characters.  */
+                alpha =  name_ptr[v];
+                beta =   media_ptr -> fx_media_last_found_name[v];
+
+                /* Ensure directory markers are the same.  */
+                if (alpha == '\\')
+                {
+                    alpha =  '/';
+                }
+                if (beta == '\\')
+                {
+                    beta =  '/';
+                }
+
+                /* Is the name the same?  */
+                if (alpha != beta)
+                {
+
+                    /* Break out of loop!  */
+                    break;
+                }
+
+                /* Move to next character.  */
+                v++;
+            }
+
+            /* Determine if we have a match.  */
+            if (name_ptr[v] != media_ptr -> fx_media_last_found_name[v])
+            {
+                match =  FX_FALSE;
+            }
+            else
+            {
+                match =  FX_TRUE;
+            }
+        }
+        else
+        {
+
+            /* Default to found.  */
+            match =  FX_TRUE;
+
+            /* Determine if there is a default path to compare with.  */
+            if (path_ptr)
+            {
+
+                /* Yes, compare the current path with what is contained in the last
+                   found buffer. Note that the last found name must have at least one
+                   path separator as well as room for at least one character for a name. */
+                while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
+                {
+
+                    /* Pickup the respective name characters.  */
+                    alpha =  media_ptr -> fx_media_last_found_name[v];
+                    beta =   path_ptr[v];
+
+                    /* Ensure directory markers are the same.  */
+                    if (alpha == '\\')
+                    {
+                        alpha =  '/';
+                    }
+                    if (beta == '\\')
+                    {
+                        beta =  '/';
+                    }
+
+                    /* Is the name the same?  */
+                    if (alpha != beta)
+                    {
+
+                        /* Break out of loop!  */
+                        break;
+                    }
+
+                    /* Move to next character.  */
+                    v++;
+                }
+
+                /* Determine if we don't have a match...  The relative path must be exhausted. */
+                if (path_ptr[v])
+                {
+                    match =  FX_FALSE;
+                }
+            }
+
+            /* Determine if we still have a match.  */
+            if (match)
+            {
+
+                /* Now examine the rest of the last name and the newly supplied
+                   input name.  */
+
+                /* Determine if a valid directory separator is present.  */
+                if ((media_ptr -> fx_media_last_found_name[v] != '\\') &&
+                    (media_ptr -> fx_media_last_found_name[v] != '/'))
+                {
+
+                    /* Set match to false - invalid directory path separator.  */
+                    match =  FX_FALSE;
+                }
+                else
+                {
+                    /* Position past the next directory separator in the
+                       last name string.  */
+                    v++;
+                }
+
+                /* Yes, the full path is in the name buffer. Simply compare with what is in
+                   the last search buffer.  */
+                j =  0;
+                while ((v < (FX_MAX_LAST_NAME_LEN - 1)) && (name_ptr[j]) && (match))
+                {
+
+                    /* Pickup the respective name characters.  */
+                    alpha =  name_ptr[j];
+                    beta =   media_ptr -> fx_media_last_found_name[v];
+
+                    /* Ensure directory markers are the same.  */
+                    if (alpha == '\\')
+                    {
+                        alpha =  '/';
+                    }
+                    if (beta == '\\')
+                    {
+                        beta =  '/';
+                    }
+
+                    /* Is the name the same?  */
+                    if (alpha != beta)
+                    {
+
+                        /* Break out of loop!  */
+                        break;
+                    }
+
+                    /* Move to next character.  */
+                    v++;
+                    j++;
+                }
+
+                /* Avoid accessing fx_media_last_found_name out of bounds. */
+                if (v >= 256)
+                {
+                    match = FX_FALSE;
+                }
+                else if ((match) && (name_ptr[j] != media_ptr -> fx_media_last_found_name[v]))
+                {
+
+                    /* We don't have a match.  */
+                    match =  FX_FALSE;
+                }
+            }
+        }
+
+        /* Now determine if we actually found a match.  */
+        if (match)
+        {
+
+            /* Save the directory entry name pointer.  */
+            temp_ptr =  entry_ptr -> fx_dir_entry_name;
+
+            /* Copy the saved directory entry.  */
+            *entry_ptr =  media_ptr -> fx_media_last_found_entry;
+
+            /* Restore the directory entry name pointer.  */
+            entry_ptr -> fx_dir_entry_name =  temp_ptr;
+
+            /* Copy the directory name into the destination directory name.  */
+            for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
+            {
+
+                /* Copy character into the destination.  */
+                temp_ptr[index] =  media_ptr -> fx_media_last_found_file_name[index];
+
+                /* See if we have copied the NULL termination character.  */
+                if (temp_ptr[index] == (CHAR)FX_NULL)
+                {
+                
+                    /* Determine if we should break here or at the top of the loop.  */
+                    if (index < (FX_MAX_LONG_NAME_LEN - 1))
+                    {
+                    
+                        /* Yes, break out of the loop early.  */
+                        break;
+                    }
+                }
+            }
+
+            /* Determine if there is a search directory to copy.  */
+            if ((last_dir_ptr) && (media_ptr -> fx_media_last_found_directory_valid))
+            {
+
+                /* Yes, there was a search directory... and one is requested in this request as well.
+                   Simply copy it into the destination.  */
+
+                /* First, save the name pointer from the list directory pointer.  */
+                destination_name_ptr =  last_dir_ptr -> fx_dir_entry_name;
+
+                /* Copy the entire directory entry structure.  */
+                *last_dir_ptr =  media_ptr -> fx_media_last_found_directory;
+
+                /* Restore the original name buffer pointer.  */
+                last_dir_ptr -> fx_dir_entry_name =  destination_name_ptr;
+
+                /* Pickup pointer to name to copy.  */
+                source_name_ptr =  media_ptr -> fx_media_last_found_directory.fx_dir_entry_name;
+
+                /* Loop to copy the name into the last directory name buffer.  */
+                for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
+                {
+                
+                    /* Copy a character.  */
+                    destination_name_ptr[n] =  source_name_ptr[n];
+                
+                    /* See if we have copied the NULL termination character.  */
+                    if (source_name_ptr[n] == (CHAR)FX_NULL)
+                    {
+                
+                        /* Determine if we should break here or at the top of the loop.  */
+                        if (n < (FX_MAX_LONG_NAME_LEN - 1))
+                        {
+                    
+                            /* Yes, break out of the loop early.  */
+                            break;
+                        }
+                    }
+                }
+            }
+
+            /* Return the last name pointer, if required.  */
+            if (last_name_ptr)
+            {
+
+                /* Just set the last name to initial name string.  */
+                *last_name_ptr =  temp_ptr;
+            }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+            /* Increment the number of directory search cache hits.  */
+            media_ptr -> fx_media_directory_search_cache_hits++;
+#endif
+
+            /* Return success.  */
+            return(FX_SUCCESS);
+        }
+    }
+
+    /* Not a sequential search, invalidate the saved information.  */
+    media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, media_ptr -> fx_media_directory_searches - media_ptr -> fx_media_directory_search_cache_hits, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+#else
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_DIR_CACHE_MISS, media_ptr, 0, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+#endif
+#endif
+
+    /* Loop to traverse the directory paths to find the specified file.  */
+    do
+    {
+
+        /* Remember the last name pointer, if required.  */
+        if (last_name_ptr)
+        {
+
+            /* Just set the last name to initial name string.  */
+            *last_name_ptr =  name_ptr;
+        }
+
+        /* Extract file name.  */
+        name_ptr =  _fx_directory_name_extract(name_ptr, name);
+
+        /* Calculate the directory size.  */
+        if (search_dir_ptr)
+        {
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+                directory_size = search_dir_ptr -> fx_dir_entry_file_size / FX_DIR_ENTRY_SIZE;
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Ensure that the search directory's last search cluster is cleared.  */
+                search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+
+                /* Calculate the directory size by counting the allocated
+                clusters for it.  */
+                i =        0;
+                cluster =  search_dir_ptr -> fx_dir_entry_cluster;
+                while (cluster < media_ptr -> fx_media_fat_reserved)
+                {
+
+                    /* Increment the cluster count.  */
+                    i++;
+
+                    /* Read the next FAT entry.  */
+                    status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
+
+                    /* Check the return status.  */
+                    if (status != FX_SUCCESS)
+                    {
+
+                        /* Return the bad status.  */
+                        return(status);
+                    }
+
+                    /* Check for error situation.  */
+                    if ((cluster < FX_FAT_ENTRY_START) || (cluster == next_cluster) || (i > media_ptr -> fx_media_total_clusters))
+                    {
+
+                        /* Return the bad status.  */
+                        return(FX_FAT_READ_ERROR);
+                    }
+
+                    cluster = next_cluster;
+                }
+
+                /* Now we can calculate the directory size.  */
+                directory_size =  (((ULONG64) media_ptr -> fx_media_bytes_per_sector) *
+                                   ((ULONG64) media_ptr -> fx_media_sectors_per_cluster) * i)
+                                    / (ULONG64) FX_DIR_ENTRY_SIZE;
+
+                /* Also save this in the directory entry so we don't have to
+                   calculate it later.  */
+                search_dir_ptr -> fx_dir_entry_file_size =  directory_size;
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* If required, copy the last search directory entry into the
+               destination.  */
+            if (last_dir_ptr)
+            {
+
+                /* Copy the last search directory into the destination.  */
+
+                /* First, save the name pointer from the list directory pointer.  */
+                destination_name_ptr =  last_dir_ptr -> fx_dir_entry_name;
+
+                /* Copy the entire directory entry structure.  */
+                *last_dir_ptr =  *search_dir_ptr;
+
+                /* Restore the original name buffer pointer.  */
+                last_dir_ptr -> fx_dir_entry_name =  destination_name_ptr;
+
+                /* Pickup pointer to name to copy.  */
+                source_name_ptr =  search_dir_ptr -> fx_dir_entry_name;
+
+                /* Loop to copy the name into the last directory name buffer.  */
+                for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
+                {
+
+                    /* Copy a character.  */
+                    destination_name_ptr[n] =  source_name_ptr[n];
+
+                    /* See if we have copied the NULL termination character.  */
+                    if (source_name_ptr[n] == (CHAR) FX_NULL)
+                    {
+                
+                        /* Determine if we should break here or at the top of the loop.  */
+                        if (n < (FX_MAX_LONG_NAME_LEN - 1))
+                        {
+                    
+                            /* Yes, break out of the loop early.  */
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+
+            /* Directory size is the number of entries in the root directory.  */
+            directory_size =  (ULONG)media_ptr -> fx_media_root_directory_entries;
+        }
+
+        /* Loop through entries in the directory.  Yes, this is a
+           linear search!  */
+        i =      0;
+        found =  FX_FALSE;
+
+#ifdef FX_ENABLE_EXFAT
+        if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+        {
+
+            /* Get name hash.  */
+            hash =  _fx_utility_exFAT_name_hash_get(name);
+        }
+#endif /* FX_ENABLE_EXFAT */
+
+        do
+        {
+
+            /* Read an entry from the directory.  */
+#ifdef FX_ENABLE_EXFAT
+            status =  _fx_directory_entry_read_ex(media_ptr, search_dir_ptr, &i, entry_ptr, hash);
+#else
+            status =  _fx_directory_entry_read(media_ptr, search_dir_ptr, &i, entry_ptr);
+#endif /* FX_ENABLE_EXFAT */
+
+            i++;
+
+            /* Check for error status.  */
+            if (status != FX_SUCCESS)
+            {
+                return(status);
+            }
+
+            /* Determine if this is the last directory entry.  */
+#ifdef FX_ENABLE_EXFAT
+            if (entry_ptr -> fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_END_MARKER)
+#else
+            if ((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_DONE)
+#endif /* FX_ENABLE_EXFAT */
+            {
+                break;
+            }
+
+            /* Determine if the entry is a volume label entry */
+            if ((entry_ptr -> fx_dir_entry_attributes & FX_VOLUME))
+            {
+                continue;
+            }
+
+            /* Determine if this is an empty entry.  */
+#ifdef FX_ENABLE_EXFAT
+            if (entry_ptr -> fx_dir_entry_type != FX_EXFAT_DIR_ENTRY_TYPE_FILE_DIRECTORY)
+#else
+            if (((UCHAR)entry_ptr -> fx_dir_entry_name[0] == (UCHAR)FX_DIR_ENTRY_FREE) && (entry_ptr -> fx_dir_entry_short_name[0] == 0))
+#endif /* FX_ENABLE_EXFAT */
+            {
+                continue;
+            }
+
+            /* Compare the input name and extension with the directory
+               entry.  */
+            work_ptr =      &name[0];
+            dir_name_ptr =  &(entry_ptr -> fx_dir_entry_name[0]);
+
+            /* Loop to compare names.  */
+            do
+            {
+
+                /* Pickup character of directory name.  */
+                alpha =  *dir_name_ptr;
+
+                /* Pickup character of name.  */
+                name_alpha =  *work_ptr;
+
+                /* Determine if its case needs to be changed.  */
+                if ((alpha >= 'a') && (alpha <= 'z'))
+                {
+
+                    /* Yes, make upper case.  */
+                    alpha =  (CHAR)((INT)alpha - 0x20);
+                }
+
+                /* Determine if its case needs to be changed.  */
+                if ((name_alpha >= 'a') && (name_alpha <= 'z'))
+                {
+
+                    /* Yes, make upper case.  */
+                    name_alpha =  (CHAR)((INT)name_alpha - 0x20);
+                }
+
+                /* Compare name with directory name.  */
+                if (alpha != name_alpha)
+                {
+
+                    /* The names don't match, get out of the loop. */
+                    break;
+                }
+
+                /* Otherwise, increment the name pointers.  */
+                work_ptr++;
+                dir_name_ptr++;
+            } while (*dir_name_ptr);
+
+            /* Determine if the requested name has been found.  If so,
+               return success to the caller.  */
+            if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
+            {
+
+                /* Yes, the name was located.  All pertinent directory
+                   information is in the directory entry field.  */
+                found =  FX_TRUE;
+            }
+            /* Determine if there is a short name to check.  */
+#ifdef FX_ENABLE_EXFAT
+            else if ((media_ptr -> fx_media_FAT_type != FX_exFAT) &&
+                     (entry_ptr -> fx_dir_entry_short_name[0] != 0))
+#else
+            else if (entry_ptr -> fx_dir_entry_short_name[0] != 0)
+#endif /* FX_ENABLE_EXFAT */
+            {
+
+                /* Yes, check for the short part of the name.  */
+
+                /* Compare the input name and extension with the directory entry.  */
+                work_ptr =      &name[0];
+                dir_name_ptr =  &(entry_ptr -> fx_dir_entry_short_name[0]);
+
+                /* Loop to compare names.  */
+                do
+                {
+
+                    /* Pickup character of directory name.  */
+                    alpha =  *dir_name_ptr;
+
+                    /* Pickup character of name.  */
+                    name_alpha =  *work_ptr;
+
+                    /* Determine if its case needs to be changed.  */
+                    if ((name_alpha >= 'a') && (name_alpha <= 'z'))
+                    {
+
+                        /* Yes, make upper case.  */
+                        name_alpha =  (CHAR)((INT)name_alpha - 0x20);
+                    }
+
+                    /* Compare name with directory name.  */
+                    if (alpha != name_alpha)
+                    {
+
+                        /* The names don't match, get out of the loop. */
+                        break;
+                    }
+
+                    /* Otherwise, move the name pointers and increment the
+                       count.  */
+                    work_ptr++;
+                    dir_name_ptr++;
+                } while (*dir_name_ptr);
+
+                /* Determine if the names match.  */
+                if ((*dir_name_ptr == 0) && (*work_ptr == *dir_name_ptr))
+                {
+
+                    /* Yes, the name was located.  All pertinent directory
+                        information is in the directory entry field.  */
+                    found =  FX_TRUE;
+                }
+            }
+        } while ((i < directory_size) && (!found));
+
+        /* Now determine if we have a match.  */
+        if (!found)
+        {
+
+            /* Return a "not found" status to the caller.  */
+            return(FX_NOT_FOUND);
+        }
+
+        /* Determine if the found entry is indeed a sub-directory.  */
+        if (entry_ptr -> fx_dir_entry_attributes & FX_DIRECTORY)
+        {
+
+            /* Move the directory search pointer to this entry.  */
+            search_dir =      *entry_ptr;
+            search_dir_ptr =  &search_dir;
+
+            /* Ensure that the search directory's last search cluster is cleared.  */
+            search_dir_ptr -> fx_dir_entry_last_search_cluster =  0;
+
+            /* Now determine if the new search directory is the root
+               directory.  */
+#ifdef FX_ENABLE_EXFAT
+            if ((!search_dir_ptr -> fx_dir_entry_cluster)
+                && (media_ptr -> fx_media_FAT_type != FX_exFAT))
+#else
+            if (!search_dir_ptr -> fx_dir_entry_cluster)
+#endif /* FX_ENABLE_EXFAT */
+            {
+
+                /* This is a backward link to the root directory.  Make
+                   sure this is indicated in the search directory
+                   information.  */
+                search_dir_ptr -> fx_dir_entry_name[0] =  0;
+
+                /* Determine if we need to remember this in the last
+                   directory searched return area.  */
+                if (last_dir_ptr)
+                {
+
+                    /* Yes, return this value to the caller.  */
+
+                    /* First, save the name pointer from the list directory pointer.  */
+                    destination_name_ptr =  last_dir_ptr -> fx_dir_entry_name;
+
+                    /* Copy the entire directory entry structure.  */
+                    *last_dir_ptr =  *search_dir_ptr;
+
+                    /* Restore the original name buffer pointer.  */
+                    last_dir_ptr -> fx_dir_entry_name =  destination_name_ptr;
+
+                    /* Pickup pointer to name to copy.  */
+                    source_name_ptr =  search_dir_ptr -> fx_dir_entry_name;
+
+                    /* Loop to copy the name into the last directory name buffer.  */
+                    for (n = 0; n < FX_MAX_LONG_NAME_LEN; n++)
+                    {
+
+                        /* Copy a character.  */
+                        destination_name_ptr[n] =  source_name_ptr[n];
+                    }
+                }
+
+                /* Set the search directory pointer to NULL to indicate
+                   we are at the root directory.  */
+                search_dir_ptr =  FX_NULL;
+            }
+        }
+        else
+        {
+
+            /* This is not a directory, we better return not found
+               since we can't continue the search.  */
+            if (name_ptr)
+            {
+
+                /* Return not-found status to caller.  */
+                return(FX_NOT_FOUND);
+            }
+        }
+    } while (name_ptr);
+
+    /* If you reach this point, the directory is found absolutely, since !found will return directly in the loop above.   */
+#ifndef FX_MEDIA_DISABLE_SEARCH_CACHE
+
+
+    /* At this point, cache the found information.  If a subsequent search for the same name is done,
+       it will return immediately.  */
+
+    /* Set the index of the saved name string.  */
+    v=  0;
+
+    /* First, build the full path and name.  */
+    if ((*original_name != '\\') && (*original_name != '/') && (path_ptr))
+    {
+
+        /* Copy the path into the destination.  */
+        while ((v< (FX_MAX_LAST_NAME_LEN - 1)) && (path_ptr[v]))
+        {
+
+            /* Copy one character.   */
+            media_ptr -> fx_media_last_found_name[v] =  path_ptr[v];
+
+            /* Move to next character.  */
+            v++;
+        }
+    }
+
+    /* Now see if there is no directory path symbol in the name itself.  */
+    if ((*original_name != '\\') && (*original_name != '/'))
+    {
+
+        /* If there is room, place a directory separator character.  */
+        if (v < (FX_MAX_LAST_NAME_LEN - 1))
+        {
+            media_ptr -> fx_media_last_found_name[v++] =  '/';
+        }
+    }
+
+    /* Now append the name to the path.  */
+    j =  0;
+    while ((v < FX_MAX_LAST_NAME_LEN) && (original_name[j]))
+    {
+
+        /* Copy one character.   */
+        media_ptr -> fx_media_last_found_name[v] =  original_name[j];
+
+        /* Move to next character.  */
+        v++;
+        j++;
+    }
+
+    /* Null terminate the last name string.   */
+    if (v< FX_MAX_LAST_NAME_LEN)
+    {
+
+        /* Null terminate.  */
+        media_ptr -> fx_media_last_found_name[v] =  FX_NULL;
+    }
+    else
+    {
+
+        /* The string is too big, NULL the string so it won't be used in searching.  */
+        media_ptr -> fx_media_last_found_name[0] =  FX_NULL;
+    }
+
+    /* Determine if there is a search pointer.  */
+    if (search_dir_ptr)
+    {
+
+        /* Yes, there is a search directory pointer so save it!   */
+        media_ptr -> fx_media_last_found_directory =  *search_dir_ptr;
+
+        /* Indicate the search directory is valid.  */
+        media_ptr -> fx_media_last_found_directory_valid =  FX_TRUE;
+    }
+    else
+    {
+
+        /* Indicate the search directory is not valid.  */
+        media_ptr -> fx_media_last_found_directory_valid =  FX_FALSE;
+    }
+
+    /* Copy the directory entry.  */
+    media_ptr -> fx_media_last_found_entry =  *entry_ptr;
+
+    /* Setup the directory entry for the last found internal file name.  */
+    media_ptr -> fx_media_last_found_entry.fx_dir_entry_name =  media_ptr -> fx_media_last_found_file_name;
+
+    /* Copy the actual directory name into the cached directory name.  */
+    for (index = 0; index < FX_MAX_LONG_NAME_LEN; index++)
+    {
+
+        /* Copy character into the cached directory name.  */
+        media_ptr -> fx_media_last_found_file_name[index] =  entry_ptr ->  fx_dir_entry_name[index];
+
+        /* See if we have copied the NULL termination character.  */
+        if (entry_ptr -> fx_dir_entry_name[index] == (CHAR)FX_NULL)
+        {
+                
+            /* Check to see if we use the break to get out of the loop.  */
+            if (index < (FX_MAX_LONG_NAME_LEN - 1))
+            {
+                    
+                /* Yes, not at the end of the string, break.  */
+                break;
+            }
+        }
+    }
+#endif
+
+    return(FX_SUCCESS);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_extended_space_available.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_extended_space_available.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_extended_space_available.c	(revision 57)
@@ -0,0 +1,115 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_extended_space_available                  PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the number of bytes available in the          */
+/*    specified media.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    available_bytes_ptr                   Pointer to available bytes    */
+/*                                            destination                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr)
+{
+
+ULONG64 available_bytes;
+ULONG   bytes_per_cluster;
+ULONG   available_clusters;
+
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_SPACE_AVAILABLE, media_ptr, available_bytes_ptr, media_ptr -> fx_media_available_clusters, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+    /* Pickup the number of free clusters.  */
+    available_clusters =  media_ptr -> fx_media_available_clusters;
+
+    /* Derive the bytes per cluster.  */
+    bytes_per_cluster =  media_ptr -> fx_media_bytes_per_sector * media_ptr -> fx_media_sectors_per_cluster;
+
+    /* Calculate the free space.  */
+    available_bytes =  ((ULONG64)available_clusters) * ((ULONG64)bytes_per_cluster);
+
+    /* Return the value.  */
+    *available_bytes_ptr =  available_bytes;
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return a successful status to the caller.  */
+    return(FX_SUCCESS);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_space_available.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_space_available.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_space_available.c	(revision 57)
@@ -0,0 +1,107 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_media.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_space_available                           PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function returns the number of bytes available in the          */
+/*    specified media.                                                    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    available_bytes_ptr                   Pointer to available bytes    */
+/*                                            destination                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    None                                                                */
+/*                                                                        */
+/*    _fx_media_extended_space_available    Actual space available service*/
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr)
+{
+
+UINT    status;
+ULONG64 available_bytes;
+
+    /* Call actual media space available service.  */
+    status = _fx_media_extended_space_available(media_ptr, &available_bytes);
+
+    /* Check status.  */
+    if (status == FX_SUCCESS)
+    {
+
+        /* Determine if more than 4GB available.  */
+        if (available_bytes > 0x00000000FFFFFFFF)
+        {
+
+            /* Yes, we must have more than 4GB available... report the maximum we can fit
+               in 32bits, which is 4GB.  */
+            *available_bytes_ptr = 0xFFFFFFFF;
+        }
+        else
+        {
+            *available_bytes_ptr = (ULONG)(available_bytes);
+        }
+    }
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get.c	(revision 57)
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_volume_get                                PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the volume name stored in the media's boot      */
+/*    record or root directory.                                           */
+/*                                                                        */
+/*    Note, this API is deprecated as fx_media_volume_get_extended should */
+/*    be used. The maximum written size to volume_name could be 12.       */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    volume_name                           Pointer to destination for    */
+/*                                            the volume name (maximum    */
+/*                                            11 characters + NULL)       */
+/*    volume_source                         Source of volume              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_volume_get_extended         Actual media volume get       */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source)
+{
+
+    /* Call the extended version with 12 bytes volume name length.  */
+    return(_fx_media_volume_get_extended(media_ptr, volume_name, 12, volume_source));
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get_extended.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get_extended.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fx_media_volume_get_extended.c	(revision 57)
@@ -0,0 +1,380 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_system.h"
+#include "fx_directory.h"
+#include "fx_media.h"
+#include "fx_utility.h"
+#ifdef FX_ENABLE_EXFAT
+#include "fx_directory_exFAT.h"
+#endif /* FX_ENABLE_EXFAT */
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fx_media_volume_get_extended                       PORTABLE C      */
+/*                                                           6.1.11       */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function reads the volume name stored in the media's boot      */
+/*    record or root directory.                                           */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    volume_name                           Pointer to destination for    */
+/*                                            the volume name (maximum    */
+/*                                            11 characters + NULL)       */
+/*    volume_name_buffer_length             Buffer length for volume_name */
+/*    volume_source                         Source of volume              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_utility_logical_sector_read       Read directory sector         */
+/*    _fx_directory_entry_read              Directory entry read          */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*  04-25-2022     Bhupendra Naphade        Modified comment(s), and      */
+/*                                            updated check for           */
+/*                                            volume name,                */
+/*                                            resulting in version 6.1.11 */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fx_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source)
+{
+
+UINT         status, offset;
+ULONG        i;
+INT          j;
+
+#ifdef FX_ENABLE_EXFAT
+ULONG        character_count;
+#endif /* FX_ENABLE_EXFAT */
+FX_DIR_ENTRY dir_entry;
+
+
+    /* Clear the volume name.  */
+    volume_name[0] =  FX_NULL;
+
+    /* Check the media to make sure it is open.  */
+    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
+    {
+
+        /* Return the media not opened error.  */
+        return(FX_MEDIA_NOT_OPEN);
+    }
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_VOLUME_GET, media_ptr, volume_name, volume_source, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
+
+    /* Protect against other threads accessing the media.  */
+    FX_PROTECT
+
+#ifdef FX_ENABLE_EXFAT
+    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+    {
+        volume_source = FX_DIRECTORY_SECTOR;
+    }
+#endif /* FX_ENABLE_EXFAT */
+
+    /* Ensure the volume name is NULL initially.  */
+    volume_name[0] =  FX_NULL;
+
+    if (volume_source == FX_DIRECTORY_SECTOR)
+    {
+
+        /* Setup pointer to media name buffer.  */
+        dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer;
+
+        /* Clear the short name string.  */
+        dir_entry.fx_dir_entry_short_name[0] =  0;
+
+        /* Attempt to find the volume name in the root directory.  */
+        i =  0;
+        do
+        {
+
+            /* Read an entry from the root directory.  */
+            status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry);
+
+            /* Check for error status.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return to caller.  */
+                return(status);
+            }
+
+            /* Check for a volume name.  */
+#ifdef FX_ENABLE_EXFAT
+            if (((media_ptr -> fx_media_FAT_type == FX_exFAT) && ((dir_entry.fx_dir_entry_attributes & FX_VOLUME) || (dir_entry.fx_dir_entry_type == FX_EXFAT_DIR_ENTRY_TYPE_VOLUME_LABEL))) 
+                    || ((media_ptr -> fx_media_FAT_type != FX_exFAT) && (dir_entry.fx_dir_entry_attributes & FX_VOLUME) && ((UCHAR)dir_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE)))
+#else
+            if ((dir_entry.fx_dir_entry_attributes & FX_VOLUME) && ((UCHAR)dir_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE))
+#endif /* FX_ENABLE_EXFAT */
+            {
+
+                /* Yes, we have found a previously set volume name.  */
+                break;
+            }
+
+            /* Move to next directory entry.  */
+            i++;
+        } while (i < media_ptr -> fx_media_root_directory_entries);
+
+        /* Determine if a volume entry has been found.  */
+        if (i < media_ptr -> fx_media_root_directory_entries)
+        {
+
+            /* Read the logical directory sector.  */
+            status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
+                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
+
+            /* Determine if an error occurred.  */
+            if (status != FX_SUCCESS)
+            {
+
+                /* Release media protection.  */
+                FX_UNPROTECT
+
+                /* Return error code.  */
+                return(status);
+            }
+
+            /* Offset to volume label entry.  */
+            offset = dir_entry.fx_dir_entry_byte_offset;
+
+#ifdef FX_ENABLE_EXFAT
+            if (media_ptr -> fx_media_FAT_type == FX_exFAT)
+            {
+
+                /* Read character count of volume label.  */
+                character_count = media_ptr -> fx_media_memory_buffer[offset + FX_EXFAT_CHAR_COUNT];
+
+                /* Check if the buffer is too short for the name.  */
+                if (character_count >= volume_name_buffer_length)
+                {
+
+                    /* Buffer too short, return error.  */
+                    status =  FX_BUFFER_ERROR;
+
+                    /* Set character count to fit for the buffer.  */
+                    character_count = volume_name_buffer_length - 1;
+                }
+
+                /* Move to volume label field.  */
+                offset += FX_EXFAT_VOLUME_LABEL;
+
+                for (i = 0; i < character_count; i++)
+                {
+
+                    /* Read one character of volume label.  */
+                    volume_name[i] = (CHAR)_fx_utility_16_unsigned_read(&media_ptr -> fx_media_memory_buffer[offset]);
+
+                    /* Move to next character.  */
+                    offset += 2;
+                }
+
+                /* NULL terminate the volume name.  */
+                volume_name[i] =  FX_NULL;
+            }
+            else
+            {
+#endif /* FX_ENABLE_EXFAT */
+
+                /* Skip trailing space characters of volume name. */
+                for (j = 10; j >= 0; j--)
+                {
+
+                    /* Check for space character.  */
+                    if (media_ptr -> fx_media_memory_buffer[offset + (UINT)j] != (UCHAR)' ')
+                    {
+
+                        /* Last character found. */
+                        break;
+                    }
+                }
+
+                /* Check if the buffer is too short for the name.  */
+                if (j >= (INT)volume_name_buffer_length - 1)
+                {
+
+                    /* Buffer too short, return error.  */
+                    status =  FX_BUFFER_ERROR;
+
+                    /* Set character count to fit for the buffer.  */
+                    j = (INT)volume_name_buffer_length - 2;
+                }
+
+                /* NULL terminate the volume name.  */
+                volume_name[j + 1] =  FX_NULL;
+
+                /* Pickup the remaining characters of the volume name from the boot sector.  */
+                for (; j >= 0; j--)
+                {
+
+                    /* Pickup byte of volume name.  */
+                    volume_name[j] =  (CHAR)media_ptr -> fx_media_memory_buffer[offset + (UINT)j];
+                }
+#ifdef FX_ENABLE_EXFAT
+            }
+#endif /* FX_ENABLE_EXFAT */
+
+            /* Release media protection.  */
+            FX_UNPROTECT
+
+            /* Return the completion status.  */
+            return(status);
+        }
+    }
+
+    /* Read volume name from boot record.  */
+    /* Read the logical directory sector 0 - we just do this to get a memory_buffer pointer */
+    status =  _fx_utility_logical_sector_read(media_ptr, ((ULONG64) 0),
+                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
+
+    /* Check the return status.  */
+    if (status != FX_SUCCESS)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* Return the error status.  */
+        return(status);
+    }
+
+#ifndef FX_MEDIA_STATISTICS_DISABLE
+
+    /* Increment the number of driver read boot sector requests.  */
+    media_ptr -> fx_media_driver_boot_read_requests++;
+#endif
+
+    /* Build the driver request to read the boot record.  */
+    media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_READ;
+    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
+    media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
+    media_ptr -> fx_media_driver_sectors =      1;
+    media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, media_ptr -> fx_media_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
+
+    /* Invoke the driver to read the boot sector.  */
+    (media_ptr -> fx_media_driver_entry) (media_ptr);
+
+    /* Determine if the request is successful.  */
+    if (media_ptr -> fx_media_driver_status)
+    {
+
+        /* Release media protection.  */
+        FX_UNPROTECT
+
+        /* An error occurred in the driver.  */
+        return(media_ptr -> fx_media_driver_status);
+    }
+
+    /* Calculate the offset to the volume name based on the type of FAT.  */
+    if (media_ptr -> fx_media_32_bit_FAT)
+    {
+
+        /* FAT32 offset to volume name.  */
+        offset =  FX_VOLUME_LABEL_32;
+    }
+    else
+    {
+
+        /* FAT12/16 offset to volume name.  */
+        offset =  FX_VOLUME_LABEL;
+    }
+
+    /* Skip trailing space characters of volume name. */
+    for (j = 10; j >= 0; j--)
+    {
+
+        /* Check for space character.  */
+        if (media_ptr -> fx_media_memory_buffer[offset + (UINT)j] != (UCHAR)' ')
+        {
+
+            /* Last character found. */
+            break;
+        }
+    }
+    
+    /* Check if the buffer is too short for the name.  */
+    if (j >= (INT)volume_name_buffer_length - 1)
+    {
+
+        /* Buffer too short, return error.  */
+        status =  FX_BUFFER_ERROR;
+
+        /* Set character count to fit for the buffer.  */
+        j = (INT)volume_name_buffer_length - 2;
+    }
+
+    /* NULL terminate the volume name.  */
+    volume_name[j + 1] =  FX_NULL;
+
+    /* Pickup the remaining characters of the volume name from the boot sector.  */
+    for (; j >= 0; j--)
+    {
+
+        /* Pickup byte of volume name.  */
+        volume_name[j] =  (CHAR)media_ptr -> fx_media_memory_buffer[offset + (UINT)j];
+    }
+
+    /* Release media protection.  */
+    FX_UNPROTECT
+
+    /* Return the completion status.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_first_entry_find.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_first_entry_find.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_first_entry_find.c	(revision 57)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_first_entry_find                     PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory find first call.   */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_first_entry_find        Actual first find service     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_first_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual directory find first service.  */
+    status =  _fx_directory_first_entry_find(media_ptr, directory_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_name_test.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_name_test.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_name_test.c	(revision 57)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_name_test                            PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the directory name test call.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Directory name pointer        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_name_test               Actual directory name test    */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_name_test(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual directory name test service.  */
+    status =  _fx_directory_name_test(media_ptr, directory_name);
+
+    /* Directory name test is complete, return status.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_next_entry_find.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_next_entry_find.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_directory_next_entry_find.c	(revision 57)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Directory                                                           */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_directory.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_directory_next_entry_find                      PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks the next directory entry find call for errors. */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    directory_name                        Destination for directory     */
+/*                                            name                        */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_directory_next_entry_find         Actual entry find service     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_directory_next_entry_find(FX_MEDIA *media_ptr, CHAR *directory_name)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer.  */
+    if (media_ptr == FX_NULL)
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual next directory entry find service.  */
+    status =  _fx_directory_next_entry_find(media_ptr, directory_name);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_media_extended_space_available.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_media_extended_space_available.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_media_extended_space_available.c	(revision 57)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_extended_space_available                 PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media space available call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    available_bytes_ptr                   Pointer to available bytes    */
+/*                                            destination                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_extended_space_available    Actual space available service*/
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_extended_space_available(FX_MEDIA *media_ptr, ULONG64 *available_bytes_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or destination pointer.  */
+    if ((media_ptr == FX_NULL) || (available_bytes_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media space available service.  */
+    status =  _fx_media_extended_space_available(media_ptr, available_bytes_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_media_space_available.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_media_space_available.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_media_space_available.c	(revision 57)
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_space_available                          PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media space available call.  */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    available_bytes_ptr                   Pointer to available bytes    */
+/*                                            destination                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_space_available             Actual space available service*/
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_space_available(FX_MEDIA *media_ptr, ULONG *available_bytes_ptr)
+{
+
+UINT status;
+
+
+    /* Check for a null media pointer or destination pointer.  */
+    if ((media_ptr == FX_NULL) || (available_bytes_ptr == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media space available service.  */
+    status =  _fx_media_space_available(media_ptr, available_bytes_ptr);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_get.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_get.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/filex/common/src/fxe_media_volume_get.c	(revision 57)
@@ -0,0 +1,100 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** FileX Component                                                       */
+/**                                                                       */
+/**   Media                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define FX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "fx_api.h"
+#include "fx_media.h"
+
+
+FX_CALLER_CHECKING_EXTERNS
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _fxe_media_volume_get                               PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function checks for errors in the media volume get service.    */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    media_ptr                             Media control block pointer   */
+/*    volume_name                           Pointer to destination for    */
+/*                                            the volume name (maximum    */
+/*                                            11 characters + NULL)       */
+/*    volume_source                         Source of volume              */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    return status                                                       */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _fx_media_volume_get                  Actual media volume get       */
+/*                                            service                     */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     William E. Lamie         Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _fxe_media_volume_get(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_source)
+{
+
+UINT status;
+
+
+    /* Check for a NULL media or volume name pointer.  */
+    if ((media_ptr == FX_NULL) || (volume_name == FX_NULL))
+    {
+        return(FX_PTR_ERROR);
+    }
+
+    /* Check for a valid caller.  */
+    FX_CALLER_CHECKING_CODE
+
+    /* Call actual media volume get service.  */
+    status =  _fx_media_volume_get(media_ptr, volume_name, volume_source);
+
+    /* Return status to the caller.  */
+    return(status);
+}
+
Index: ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_mutex_get.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_mutex_get.c	(revision 57)
+++ ctrl/firmware/Main/CubeMX/Middlewares/ST/threadx/common/src/tx_mutex_get.c	(revision 57)
@@ -0,0 +1,411 @@
+/**************************************************************************/
+/*                                                                        */
+/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
+/*                                                                        */
+/*       This software is licensed under the Microsoft Software License   */
+/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
+/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
+/*       and in the root directory of this software.                      */
+/*                                                                        */
+/**************************************************************************/
+
+
+/**************************************************************************/
+/**************************************************************************/
+/**                                                                       */
+/** ThreadX Component                                                     */
+/**                                                                       */
+/**   Mutex                                                               */
+/**                                                                       */
+/**************************************************************************/
+/**************************************************************************/
+
+#define TX_SOURCE_CODE
+
+
+/* Include necessary system files.  */
+
+#include "tx_api.h"
+#include "tx_trace.h"
+#include "tx_thread.h"
+#include "tx_mutex.h"
+
+
+/**************************************************************************/
+/*                                                                        */
+/*  FUNCTION                                               RELEASE        */
+/*                                                                        */
+/*    _tx_mutex_get                                       PORTABLE C      */
+/*                                                           6.1          */
+/*  AUTHOR                                                                */
+/*                                                                        */
+/*    William E. Lamie, Microsoft Corporation                             */
+/*                                                                        */
+/*  DESCRIPTION                                                           */
+/*                                                                        */
+/*    This function gets the specified mutex.  If the calling thread      */
+/*    already owns the mutex, an ownership count is simply increased.     */
+/*                                                                        */
+/*  INPUT                                                                 */
+/*                                                                        */
+/*    mutex_ptr                         Pointer to mutex control block    */
+/*    wait_option                       Suspension option                 */
+/*                                                                        */
+/*  OUTPUT                                                                */
+/*                                                                        */
+/*    status                            Completion status                 */
+/*                                                                        */
+/*  CALLS                                                                 */
+/*                                                                        */
+/*    _tx_thread_system_suspend         Suspend thread service            */
+/*    _tx_thread_system_ni_suspend      Non-interruptable suspend thread  */
+/*    _tx_mutex_priority_change         Inherit thread priority           */
+/*                                                                        */
+/*  CALLED BY                                                             */
+/*                                                                        */
+/*    Application Code                                                    */
+/*                                                                        */
+/*  RELEASE HISTORY                                                       */
+/*                                                                        */
+/*    DATE              NAME                      DESCRIPTION             */
+/*                                                                        */
+/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
+/*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
+/*                                            resulting in version 6.1    */
+/*                                                                        */
+/**************************************************************************/
+UINT  _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TX_THREAD       *thread_ptr;
+TX_MUTEX        *next_mutex;
+TX_MUTEX        *previous_mutex;
+TX_THREAD       *mutex_owner;
+TX_THREAD       *next_thread;
+TX_THREAD       *previous_thread;
+UINT            status;
+
+
+    /* Disable interrupts to get an instance from the mutex.  */
+    TX_DISABLE
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+    /* Increment the total mutex get counter.  */
+    _tx_mutex_performance_get_count++;
+
+    /* Increment the number of attempts to get this mutex.  */
+    mutex_ptr -> tx_mutex_performance_get_count++;
+#endif
+
+    /* If trace is enabled, insert this event into the trace buffer.  */
+    TX_TRACE_IN_LINE_INSERT(TX_TRACE_MUTEX_GET, mutex_ptr, wait_option, TX_POINTER_TO_ULONG_CONVERT(mutex_ptr -> tx_mutex_owner), mutex_ptr -> tx_mutex_ownership_count, TX_TRACE_MUTEX_EVENTS)
+
+    /* Log this kernel call.  */
+    TX_EL_MUTEX_GET_INSERT
+
+    /* Pickup thread pointer.  */
+    TX_THREAD_GET_CURRENT(thread_ptr)
+
+    /* Determine if this mutex is available.  */
+    if (mutex_ptr -> tx_mutex_ownership_count == ((UINT) 0))
+    {
+
+        /* Set the ownership count to 1.  */
+        mutex_ptr -> tx_mutex_ownership_count =  ((UINT) 1);
+
+        /* Remember that the calling thread owns the mutex.  */
+        mutex_ptr -> tx_mutex_owner =  thread_ptr;
+
+        /* Determine if the thread pointer is valid.  */
+        if (thread_ptr != TX_NULL)
+        {
+
+            /* Determine if priority inheritance is required.  */
+            if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+            {
+
+                /* Remember the current priority of thread.  */
+                mutex_ptr -> tx_mutex_original_priority =   thread_ptr -> tx_thread_priority;
+
+                /* Setup the highest priority waiting thread.  */
+                mutex_ptr -> tx_mutex_highest_priority_waiting =  ((UINT) TX_MAX_PRIORITIES);
+            }
+
+            /* Pickup next mutex pointer, which is the head of the list.  */
+            next_mutex =  thread_ptr -> tx_thread_owned_mutex_list;
+
+            /* Determine if this thread owns any other mutexes that have priority inheritance.  */
+            if (next_mutex != TX_NULL)
+            {
+
+                /* Non-empty list. Link up the mutex.  */
+
+                /* Pickup the next and previous mutex pointer.  */
+                previous_mutex =  next_mutex -> tx_mutex_owned_previous;
+
+                /* Place the owned mutex in the list.  */
+                next_mutex -> tx_mutex_owned_previous =  mutex_ptr;
+                previous_mutex -> tx_mutex_owned_next =  mutex_ptr;
+
+                /* Setup this mutex's next and previous created links.  */
+                mutex_ptr -> tx_mutex_owned_previous =  previous_mutex;
+                mutex_ptr -> tx_mutex_owned_next =      next_mutex;
+            }
+            else
+            {
+
+                /* The owned mutex list is empty.  Add mutex to empty list.  */
+                thread_ptr -> tx_thread_owned_mutex_list =     mutex_ptr;
+                mutex_ptr -> tx_mutex_owned_next =             mutex_ptr;
+                mutex_ptr -> tx_mutex_owned_previous =         mutex_ptr;
+            }
+
+            /* Increment the number of mutexes owned counter.  */
+            thread_ptr -> tx_thread_owned_mutex_count++;
+        }
+
+        /* Restore interrupts.  */
+        TX_RESTORE
+
+        /* Return success.  */
+        status =  TX_SUCCESS;
+    }
+
+    /* Otherwise, see if the owning thread is trying to obtain the same mutex.  */
+    else if (mutex_ptr -> tx_mutex_owner == thread_ptr)
+    {
+
+        /* The owning thread is requesting the mutex again, just
+           increment the ownership count.  */
+        mutex_ptr -> tx_mutex_ownership_count++;
+
+        /* Restore interrupts.  */
+        TX_RESTORE
+
+        /* Return success.  */
+        status =  TX_SUCCESS;
+    }
+    else
+    {
+
+        /* Determine if the request specifies suspension.  */
+        if (wait_option != TX_NO_WAIT)
+        {
+
+            /* Determine if the preempt disable flag is non-zero.  */
+            if (_tx_thread_preempt_disable != ((UINT) 0))
+            {
+
+                /* Restore interrupts.  */
+                TX_RESTORE
+
+                /* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion.  */
+                status =  TX_NOT_AVAILABLE;
+            }
+            else
+            {
+
+                /* Prepare for suspension of this thread.  */
+
+                /* Pickup the mutex owner.  */
+                mutex_owner =  mutex_ptr -> tx_mutex_owner;
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+                /* Increment the total mutex suspension counter.  */
+                _tx_mutex_performance_suspension_count++;
+
+                /* Increment the number of suspensions on this mutex.  */
+                mutex_ptr -> tx_mutex_performance_suspension_count++;
+
+                /* Determine if a priority inversion is present.  */
+                if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_priority)
+                {
+
+                    /* Yes, priority inversion is present!  */
+
+                    /* Increment the total mutex priority inversions counter.  */
+                    _tx_mutex_performance_priority_inversion_count++;
+
+                    /* Increment the number of priority inversions on this mutex.  */
+                    mutex_ptr -> tx_mutex_performance_priority_inversion_count++;
+
+#ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
+
+                    /* Increment the number of total thread priority inversions.  */
+                    _tx_thread_performance_priority_inversion_count++;
+
+                    /* Increment the number of priority inversions for this thread.  */
+                    thread_ptr -> tx_thread_performance_priority_inversion_count++;
+#endif
+                }
+#endif
+
+                /* Setup cleanup routine pointer.  */
+                thread_ptr -> tx_thread_suspend_cleanup =  &(_tx_mutex_cleanup);
+
+                /* Setup cleanup information, i.e. this mutex control
+                   block.  */
+                thread_ptr -> tx_thread_suspend_control_block =  (VOID *) mutex_ptr;
+
+#ifndef TX_NOT_INTERRUPTABLE
+
+                /* Increment the suspension sequence number, which is used to identify
+                   this suspension event.  */
+                thread_ptr -> tx_thread_suspension_sequence++;
+#endif
+
+                /* Setup suspension list.  */
+                if (mutex_ptr -> tx_mutex_suspended_count == TX_NO_SUSPENSIONS)
+                {
+
+                    /* No other threads are suspended.  Setup the head pointer and
+                       just setup this threads pointers to itself.  */
+                    mutex_ptr -> tx_mutex_suspension_list =         thread_ptr;
+                    thread_ptr -> tx_thread_suspended_next =        thread_ptr;
+                    thread_ptr -> tx_thread_suspended_previous =    thread_ptr;
+                }
+                else
+                {
+
+                    /* This list is not NULL, add current thread to the end. */
+                    next_thread =                                   mutex_ptr -> tx_mutex_suspension_list;
+                    thread_ptr -> tx_thread_suspended_next =        next_thread;
+                    previous_thread =                               next_thread -> tx_thread_suspended_previous;
+                    thread_ptr -> tx_thread_suspended_previous =    previous_thread;
+                    previous_thread -> tx_thread_suspended_next =   thread_ptr;
+                    next_thread -> tx_thread_suspended_previous =   thread_ptr;
+                }
+
+                /* Increment the suspension count.  */
+                mutex_ptr -> tx_mutex_suspended_count++;
+
+                /* Set the state to suspended.  */
+                thread_ptr -> tx_thread_state =    TX_MUTEX_SUSP;
+
+#ifdef TX_NOT_INTERRUPTABLE
+
+                /* Determine if we need to raise the priority of the thread
+                   owning the mutex.  */
+                if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+                {
+
+                    /* Determine if this is the highest priority to raise for this mutex.  */
+                    if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority)
+                    {
+
+                        /* Remember this priority.  */
+                        mutex_ptr -> tx_mutex_highest_priority_waiting =  thread_ptr -> tx_thread_priority;
+                    }
+
+                    /* Determine if we have to update inherit priority level of the mutex owner.  */
+                    if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority)
+                    {
+
+                        /* Remember the new priority inheritance priority.  */
+                        mutex_owner -> tx_thread_inherit_priority =  thread_ptr -> tx_thread_priority;
+                    }
+
+                    /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority.  */
+                    if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority)
+                    {
+
+                        /* Yes, raise the suspended, owning thread's priority to that
+                           of the current thread.  */
+                        _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority);
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+                        /* Increment the total mutex priority inheritance counter.  */
+                        _tx_mutex_performance__priority_inheritance_count++;
+
+                        /* Increment the number of priority inheritance situations on this mutex.  */
+                        mutex_ptr -> tx_mutex_performance__priority_inheritance_count++;
+#endif
+                    }
+                }
+
+                /* Call actual non-interruptable thread suspension routine.  */
+                _tx_thread_system_ni_suspend(thread_ptr, wait_option);
+
+                /* Restore interrupts.  */
+                TX_RESTORE
+#else
+
+                /* Set the suspending flag.  */
+                thread_ptr -> tx_thread_suspending =  TX_TRUE;
+
+                /* Setup the timeout period.  */
+                thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks =  wait_option;
+
+                /* Temporarily disable preemption.  */
+                _tx_thread_preempt_disable++;
+
+                /* Restore interrupts.  */
+                TX_RESTORE
+
+                /* Determine if we need to raise the priority of the thread
+                   owning the mutex.  */
+                if (mutex_ptr -> tx_mutex_inherit == TX_TRUE)
+                {
+
+                    /* Determine if this is the highest priority to raise for this mutex.  */
+                    if (mutex_ptr -> tx_mutex_highest_priority_waiting > thread_ptr -> tx_thread_priority)
+                    {
+
+                        /* Remember this priority.  */
+                        mutex_ptr -> tx_mutex_highest_priority_waiting =  thread_ptr -> tx_thread_priority;
+                    }
+
+                    /* Determine if we have to update inherit priority level of the mutex owner.  */
+                    if (thread_ptr -> tx_thread_priority < mutex_owner -> tx_thread_inherit_priority)
+                    {
+
+                        /* Remember the new priority inheritance priority.  */
+                        mutex_owner -> tx_thread_inherit_priority =  thread_ptr -> tx_thread_priority;
+                    }
+
+                    /* Priority inheritance is requested, check to see if the thread that owns the mutex is lower priority.  */
+                    if (mutex_owner -> tx_thread_priority > thread_ptr -> tx_thread_priority)
+                    {
+
+                        /* Yes, raise the suspended, owning thread's priority to that
+                           of the current thread.  */
+                        _tx_mutex_priority_change(mutex_owner, thread_ptr -> tx_thread_priority);
+
+#ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
+
+                        /* Increment the total mutex priority inheritance counter.  */
+                        _tx_mutex_performance__priority_inheritance_count++;
+
+                        /* Increment the number of priority inheritance situations on this mutex.  */
+                        mutex_ptr -> tx_mutex_performance__priority_inheritance_count++;
+#endif
+                    }
+                }
+
+                /* Call actual thread suspension routine.  */
+                _tx_thread_system_suspend(thread_ptr);
+#endif
+                /* Return the completion status.  */
+                status =  thread_ptr -> tx_thread_suspend_status;
+            }
+        }
+        else
+        {
+
+            /* Restore interrupts.  */
+            TX_RESTORE
+
+            /* Immediate return, return error completion.  */
+            status =  TX_NOT_AVAILABLE;
+        }
+    }
+
+    /* Return completion status.  */
+    return(status);
+}
+
