navigation.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00013 /* Copyright (C) 2006-2008, Atmel Corporation All rights reserved.
00014  *
00015  * Redistribution and use in source and binary forms, with or without
00016  * modification, are permitted provided that the following conditions are met:
00017  *
00018  * 1. Redistributions of source code must retain the above copyright notice,
00019  * this list of conditions and the following disclaimer.
00020  *
00021  * 2. Redistributions in binary form must reproduce the above copyright notice,
00022  * this list of conditions and the following disclaimer in the documentation
00023  * and/or other materials provided with the distribution.
00024  *
00025  * 3. The name of ATMEL may not be used to endorse or promote products derived
00026  * from this software without specific prior written permission.
00027  *
00028  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00029  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00030  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
00031  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00032  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00033  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00034  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00035  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00036  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00037  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00038  */
00039 
00040 //_____  I N C L U D E S ___________________________________________________
00041 #include <ctype.h> // Use of toupper
00042 
00043 #include "conf_explorer.h"
00044 #include "navigation.h"
00045 #include "file.h"
00046 #include LIB_CTRLACCESS
00047 
00048 
00049 //_____ M A C R O S ________________________________________________________
00050 
00051 
00052 //_____ D E F I N I T I O N S ______________________________________________
00053 
00054 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
00056    _MEM_TYPE_SLOW_ U8 g_id_trans_memtomem = ID_STREAM_ERR;
00057 #endif
00058 
00059 #if (FS_NB_NAVIGATOR > 1)
00061    _MEM_TYPE_SLOW_ U8 fs_g_u8_nav_selected;
00062 #endif
00063 
00064 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
00065    _MEM_TYPE_SLOW_ Fs_file_segment g_segment_src;
00066    _MEM_TYPE_SLOW_ Fs_file_segment g_segment_dest;
00067 #endif
00068 
00069 #define SIZE_OF_SPLIT_COPY    ((1*1024*1024L)/512L)    // 1MB - Unit sector (max = 0xFFFF)
00070 
00071 
00072 //_____ D E C L A R A T I O N S ____________________________________________
00073 
00074 //**********************************************************************
00075 //************************ String format select ************************
00076 #if( (FS_ASCII == ENABLED) && (FS_UNICODE == ENABLED))
00084 void  nav_string_unicode( void )
00085 {
00086    g_b_unicode = TRUE;
00087 }
00095 void  nav_string_ascii( void )
00096 {
00097    g_b_unicode = FALSE;
00098 }
00099 #endif
00100 
00108 void  nav_string_length_enable( void )
00109 {
00110    g_b_string_length = TRUE;
00111 }
00119 void  nav_string_length_disable( void )
00120 {
00121    g_b_string_length = FALSE;
00122 }
00123 
00124 //**********************************************************************
00125 //********************** To optimize speed access **********************
00126 
00134 void  nav_checkdisk_disable( void )
00135 {
00136    g_b_no_check_disk = TRUE;
00137 }
00138 
00146 void  nav_checkdisk_enable( void )
00147 {
00148    g_b_no_check_disk = FALSE;
00149 }
00150 
00151 
00152 //**********************************************************************
00153 //************** Initialise or Stop navigation module ******************
00154 
00155 
00162 void  nav_reset( void )
00163 {
00164 #if ( (FS_ASCII   == ENABLED) && (FS_UNICODE == ENABLED))
00165    g_b_unicode = TRUE;
00166 #endif
00167    g_b_string_length = FALSE;
00168    g_b_no_check_disk = FALSE;
00169 
00170    fat_cache_reset();
00171    fat_cache_clusterlist_reset();
00172 
00173 #if (FS_NB_NAVIGATOR > 1)
00174    {
00175    U8 i;
00176    // Reset variables of each navigators
00177    for( i=0 ; i!=FS_NB_NAVIGATOR ; i++ )
00178    {
00179       nav_select(i);
00180       fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_UNM; // By default the fat isn't mounted
00181       fs_g_nav.u8_lun = 0xFF;                      // By default don't select a drive
00182 #if (FS_MULTI_PARTITION  ==  ENABLED)
00183       fs_g_nav.u8_partition=0;                     // By default select the first partition
00184 #endif
00185       Fat_file_close();                            // By default no file is opened
00186       fs_g_nav.b_mode_nav_single = FALSE;          // By default display files and directories
00187    }
00188    // By default select the navigator 0
00189    fs_g_u8_nav_selected = 0;
00190    }
00191 #else
00192    fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_UNM;    // By default the fat isn't mounted
00193    fs_g_nav.u8_lun = 0xFF;                         // By default don't select a drive
00194 #  if (FS_MULTI_PARTITION  ==  ENABLED)
00195    fs_g_nav.u8_partition=0;                        // By default select the first partition
00196 #  endif
00197    Fat_file_close();                               // By default no file is opened
00198 #endif // (FS_NB_NAVIGATOR > 1)
00199 }
00200 
00201 
00208 void  nav_exit( void )
00209 {
00210    // If you have opened files then close them
00211 #if (FS_NB_NAVIGATOR > 1)
00212    U8 u8_i;
00213    for( u8_i=0; u8_i<FS_NB_NAVIGATOR; u8_i++)
00214    {
00215       nav_select(u8_i);
00216       file_close();
00217    }
00218 #else
00219    nav_select(0);
00220    file_close();
00221 #endif
00222    // Flush data eventually present in FAT cache
00223    fat_cache_flush();
00224 }
00225 
00226 
00234 Bool  nav_select( U8 u8_idnav )
00235 {
00236    if( FS_NB_NAVIGATOR <= u8_idnav )
00237    {
00238       fs_g_status = FS_ERR_BAD_NAV;             // The navigator doesn't exist
00239       return FALSE;
00240    }
00241 #if (FS_NB_NAVIGATOR > 1)
00242    if( fs_g_u8_nav_selected != u8_idnav )
00243    {
00244       fat_invert_nav( fs_g_u8_nav_selected );   // Deselect previous navigator = Select default navigator
00245       fat_invert_nav( u8_idnav );               // Select new navigator
00246       fs_g_u8_nav_selected = u8_idnav;
00247    }
00248 #endif
00249    return TRUE;
00250 }
00251 
00252 
00257 U8    nav_get( void )
00258 {
00259 #if (FS_NB_NAVIGATOR > 1)
00260    return fs_g_u8_nav_selected;
00261 #else
00262    return 0;
00263 #endif
00264 }
00265 
00266 
00278 Bool  nav_copy( U8 u8_idnav )
00279 {
00280 #if (FS_NB_NAVIGATOR > 1)
00281    if( fs_g_u8_nav_selected == u8_idnav )
00282       return FALSE;                    // It is the source and destination is the same navigator
00283    if( 0 == u8_idnav )
00284       u8_idnav = fs_g_u8_nav_selected; // the default navigator is invert with the current navigator
00285    if( 0 == u8_idnav)
00286       return FALSE;                    // It is the source and destination is the same navigator
00287    fat_copy_nav( u8_idnav );
00288    return TRUE;
00289 #else
00290    u8_idnav++;
00291    return FALSE;                       // Copy impossible because only one navigator is available
00292 #endif
00293 }
00294 
00295 
00296 //**********************************************************************
00297 //********************* Drive navigation functions *********************
00298 
00299 
00308 U8    nav_drive_nb( void )
00309 {
00310    return get_nb_lun(); // Number of devices = Number of lun
00311 }
00312 
00313 
00321 Bool  nav_drive_set( U8 u8_number )
00322 {
00323    if ( !fat_check_noopen() )
00324       return FALSE;
00325 
00326    if (u8_number >= get_nb_lun() )
00327    {
00328       fs_g_status = FS_ERR_END_OF_DRIVE;   // The drive number is bad
00329       return FALSE;
00330    }
00331 
00332    if ( fs_g_nav.u8_lun == u8_number)
00333       return TRUE;   // It is the same drive number
00334 
00335    // Go to the device
00336    fs_g_nav.u8_lun = u8_number;
00337    fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_UNM;
00338 #if (FS_MULTI_PARTITION  ==  ENABLED)
00339    fs_g_nav.u8_partition=0;   // by default select the first partition
00340 #endif
00341    return TRUE;
00342 }
00343 
00344 
00350 U8    nav_drive_get( void )
00351 {
00352 #if (FS_MULTI_PARTITION  ==  ENABLED)
00353    if(0xFF == fs_g_nav.u8_lun)
00354       return 0xFF;
00355    return ((fs_g_nav.u8_lun*4) + fs_g_nav.u8_partition); // Maximum 4 partitions per device
00356 #else
00357    return (fs_g_nav.u8_lun);
00358 #endif
00359 }
00360 
00361 
00367 U8    nav_drive_getname( void )
00368 {
00369    if(0xFF == fs_g_nav.u8_lun)
00370       return 'X';
00371 #if (FS_MULTI_PARTITION  ==  ENABLED)
00372    return ('A' + (fs_g_nav.u8_lun*4) + fs_g_nav.u8_partition); // Maximum 4 partitions per device
00373 #else
00374    return ('A' + fs_g_nav.u8_lun);
00375 #endif
00376 }
00377 
00378 
00379 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
00396 Bool  nav_drive_format( U8 u8_fat_type )
00397 {
00398    if ( !fat_check_noopen() )
00399       return FALSE;
00400    if ( !fat_check_nav_access_disk() )
00401       return FALSE;
00402    if ( !fat_format( u8_fat_type ) )
00403       return FALSE;
00404    return fat_mount();
00405 }
00406 #endif  // FS_LEVEL_FEATURES
00407 
00408 
00409 //**********************************************************************
00410 //******************* Partition navigation functions *******************
00411 
00412 
00413 #if (FS_MULTI_PARTITION  ==  ENABLED)
00418 U8    nav_partition_nb( void )
00419 {
00420    return fat_get_nbpartition();
00421 }
00422 
00423 
00431 Bool  nav_partition_set( U8 partition_number )
00432 {
00433    if ( fs_g_nav.u8_partition == partition_number)
00434       return TRUE;   // It is the same
00435 
00436    if ( !fat_check_noopen() )
00437       return FALSE;
00438 
00439    // Go to partition
00440    fs_g_nav.u8_partition = partition_number;
00441    fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_UNM;
00442    return TRUE;
00443 }
00444 #endif
00445 
00446 
00458 Bool  nav_partition_mount( void )
00459 {
00460    if ( !fat_check_noopen() )
00461       return FALSE;
00462 
00463    if( FS_TYPE_FAT_UNM != fs_g_nav_fast.u8_type_fat)
00464    {
00465       // Already mounted
00466       // Go to root directory
00467       fs_g_nav.u32_cluster_sel_dir   = 0;
00468       // No file is selected by default
00469       fat_clear_entry_info_and_ptr();
00470       return TRUE;
00471    }
00472 
00473    return fat_mount();
00474 }
00475 
00476 
00482 U8    nav_partition_type( void )
00483 {
00484    fat_check_device();
00485    if( FS_TYPE_FAT_UNM == fs_g_nav_fast.u8_type_fat)
00486    {
00487       nav_partition_mount();
00488    }
00489    return fs_g_nav_fast.u8_type_fat;
00490 }
00491 
00492 
00505 Bool  nav_partition_serialnumber( Bool b_action , U8 _MEM_TYPE_SLOW_ *a_u8_sn )
00506 {
00507    if( !fat_check_mount())
00508       return FALSE;
00509 
00510    return fat_serialnumber( b_action , a_u8_sn );
00511 }
00512 
00513 
00526 Bool  nav_partition_label( Bool b_action , FS_STRING sz_label )
00527 {
00528    _MEM_TYPE_SLOW_   Fs_index index;
00529    Bool status = TRUE;
00530 
00531    index = nav_getindex();    // Save current position
00532 
00533    // Go to root dir
00534    if( nav_dir_root())
00535    {
00536       // Find field label
00537       fs_g_nav_fast.u16_entry_pos_sel_file = 0; // Go to first entry
00538       while( 1 )
00539       {
00540          if ( !fat_read_dir())
00541          {
00542             status = FALSE;
00543             break;               // error
00544          }
00545          if( fat_entry_label( FS_LABEL_READ , NULL ) )
00546             break;
00547          if( FS_ERR_ENTRY_EMPTY == fs_g_status )
00548             break;
00549          fs_g_nav_fast.u16_entry_pos_sel_file++;
00550       }
00551       if( TRUE == status )
00552       {
00553          // Find OK
00554          if( FS_LABEL_READ == b_action )
00555          {
00556             // Read field label
00557             if( !fat_entry_label( FS_LABEL_READ , sz_label ) )
00558                sz_label[0]=0;    // empty name
00559          }else{
00560             // Change field label
00561             status = fat_entry_label( FS_LABEL_WRITE , sz_label );
00562          }
00563       }
00564    }
00565    nav_gotoindex( &index );   // Restore the position
00566    return status;
00567 }
00568 
00569 
00579 U32   nav_partition_space( void )
00580 {
00581    fat_check_device();
00582    if (FS_TYPE_FAT_UNM == fs_g_nav_fast.u8_type_fat)
00583       return 0;
00584    return (fs_g_nav.u32_CountofCluster * fs_g_nav.u8_BPB_SecPerClus);
00585 }
00586 
00587 
00592 U8    nav_partition_cluster_size( void )
00593 {
00594    return fs_g_nav.u8_BPB_SecPerClus;
00595 }
00596 
00606 U32   nav_partition_freespace( void )
00607 {
00608    fat_check_device();
00609    if (FS_TYPE_FAT_UNM == fs_g_nav_fast.u8_type_fat)
00610       return 0;
00611    return fat_getfreespace();
00612 }
00613 
00614 
00624 U8    nav_partition_freespace_percent( void )
00625 {
00626    fat_check_device();
00627    if (FS_TYPE_FAT_UNM == fs_g_nav_fast.u8_type_fat)
00628       return 0;
00629    return fat_getfreespace_percent();
00630 }
00631 
00632 
00633 //**********************************************************************
00634 //****************** File list navigation functions ********************
00635 
00636 
00645 Bool  nav_filelist_single_enable( Bool b_type )
00646 {
00647    if ( !nav_filelist_reset())
00648       return FALSE;
00649 
00650    fs_g_nav.b_mode_nav_single = TRUE;
00651    fs_g_nav.b_mode_nav        = b_type;
00652    return TRUE;
00653 }
00654 
00655 
00661 Bool  nav_filelist_single_disable( void )
00662 {
00663    fs_g_nav.b_mode_nav_single = FALSE;
00664    return nav_filelist_reset();
00665 }
00666 
00667 
00673 Bool  nav_filelist_reset( void )
00674 {
00675    if ( !fat_check_mount_noopen())
00676       return FALSE;
00677 
00678    // No file selected and reset navigation
00679    fat_clear_entry_info_and_ptr();
00680    return TRUE;
00681 }
00682 
00683 
00689 Bool  nav_filelist_validpos( void )
00690 {
00691    return fat_check_mount_select_noopen();
00692 }
00693 
00694 
00700 Bool  nav_filelist_fileisnotopen( void )
00701 {
00702    return fat_check_noopen();
00703 }
00704 
00705 
00723 Bool  nav_filelist_set( U16 u16_nb , Bool b_direction )
00724 {
00725    U16   u16_ptr_save_entry;
00726    U16   u16_save_pos_sel_file;
00727    Bool  b_save_entry_type;
00728    Bool  b_find_last_entry = FALSE;
00729 
00730    if ( !fat_check_mount_noopen())
00731       return FALSE;
00732 
00733    // Save the current selection
00734    u16_ptr_save_entry      = fs_g_nav_fast.u16_entry_pos_sel_file;
00735    u16_save_pos_sel_file   = fs_g_nav.u16_pos_sel_file;
00736    b_save_entry_type       = fs_g_nav.b_mode_nav;
00737 
00738    // Loop in directory
00739    while( 1 )
00740    {
00741       if(( FS_FIND_NEXT == b_direction )
00742       || ( b_find_last_entry ) )
00743       {
00744          if ( FS_END_FIND == fs_g_nav_fast.u16_entry_pos_sel_file )
00745          {
00746             // Too many files in directory (case impossible)
00747             fs_g_status = FS_ERR_FS;
00748             break;
00749          }
00750          fs_g_nav_fast.u16_entry_pos_sel_file++;      // Update entry position
00751       }
00752       else
00753       {
00754          if ( FS_NO_SEL == fs_g_nav_fast.u16_entry_pos_sel_file )
00755          {
00756             // No selected file then previous action impossible
00757             fs_g_status = FS_ERR_NO_FIND;
00758             break;
00759          }
00760          if ( 0 == fs_g_nav_fast.u16_entry_pos_sel_file )
00761          {
00762             // beginning of directory
00763             if ( (FS_DIR == fs_g_nav.b_mode_nav ) || fs_g_nav.b_mode_nav_single )
00764             {
00765                // End of directory scan, then no previous action possible
00766                fs_g_status = FS_ERR_NO_FIND;
00767                break;
00768             }
00769             // End of file scan, then find last directory
00770             b_find_last_entry = TRUE;
00771          }else{
00772             fs_g_nav_fast.u16_entry_pos_sel_file--;   // Update entry position
00773          }
00774       }
00775 
00776       if( !fat_read_dir())
00777       {
00778          if( FS_ERR_OUT_LIST != fs_g_status )
00779             break; // Error
00780       }else{
00781          if ( fat_entry_check( fs_g_nav.b_mode_nav ) )
00782          {
00783            // HERE, the file entry match with the type seached
00784 
00785            if( b_find_last_entry )
00786              continue;  // The search of last directory is on going then continue the search
00787 
00788            // Update position in directory
00789            if ( FS_FIND_NEXT == b_direction )
00790               fs_g_nav.u16_pos_sel_file++;
00791            else
00792               fs_g_nav.u16_pos_sel_file--;
00793 
00794            if (0 == u16_nb)
00795            {
00796               // It is the end of move then update file information
00797               fat_get_entry_info();
00798               return TRUE;         // NB FILE FIND
00799            }
00800            u16_nb--;
00801            continue;
00802          }
00803       }
00804 
00805       // Here error, check type of error
00806       if(( FS_ERR_ENTRY_EMPTY == fs_g_status )
00807       || ( FS_ERR_OUT_LIST    == fs_g_status ) )
00808       {
00809          // Here, end of the directory
00810          if( b_find_last_entry )
00811          {
00812             // Re enable the previous command at the end of directory to find the last directory entry
00813             b_find_last_entry = FALSE;
00814             fs_g_nav.b_mode_nav = FS_DIR;
00815             continue;
00816          }
00817          // Here, a next action is on going
00818          if ( (FS_FILE == fs_g_nav.b_mode_nav) || fs_g_nav.b_mode_nav_single )
00819          {
00820             // End of next file action then end of next action
00821             fs_g_status = FS_ERR_NO_FIND; // No file found
00822             break;                        // end of search
00823          }else{
00824             // End of next dir action then starts the next file action at the beginning of directory
00825             fs_g_nav_fast.u16_entry_pos_sel_file = 0xFFFF;
00826             fs_g_nav.b_mode_nav = FS_FILE;
00827          }
00828       }
00829    }  // end of loop while(1)
00830 
00831    fs_g_nav.b_mode_nav                    = b_save_entry_type;
00832    fs_g_nav_fast.u16_entry_pos_sel_file   = u16_ptr_save_entry;
00833    fs_g_nav.u16_pos_sel_file              = u16_save_pos_sel_file;
00834    return FALSE;
00835 }
00836 
00837 
00843 U16   nav_filelist_get( void )
00844 {
00845    return fs_g_nav.u16_pos_sel_file;
00846 }
00847 
00848 
00856 Bool  nav_filelist_goto( U16 u16_newpos )
00857 {
00858    U16 u16_current_pos;
00859 
00860    if( FS_NO_SEL == u16_newpos )
00861       return nav_filelist_reset();
00862 
00863    u16_current_pos = nav_filelist_get();
00864    if( u16_newpos < (u16_current_pos/2) )
00865    {
00866       // Restart at the beginning of list to accelerate the search
00867       if( !nav_filelist_reset() )
00868          return FALSE;
00869       u16_current_pos = FS_NO_SEL;
00870    }
00871    if (FS_NO_SEL == u16_current_pos)
00872    {
00873       return nav_filelist_set( u16_newpos, FS_FIND_NEXT );
00874    }
00875    else
00876    {
00877       if (u16_newpos < u16_current_pos)
00878       {
00879          return nav_filelist_set( u16_current_pos -u16_newpos -1 , FS_FIND_PREV );
00880       }
00881       if (u16_newpos > u16_current_pos)
00882       {
00883          return nav_filelist_set( u16_newpos -u16_current_pos - 1 , FS_FIND_NEXT );
00884       }
00885    }
00886    return TRUE;
00887 }
00888 
00889 
00903 Bool  nav_filelist_findname( const FS_STRING sz_name , Bool b_match_case )
00904 {
00905    while( 1 )
00906    {
00907       if ( !nav_filelist_set( 0, FS_FIND_NEXT ))
00908          return FALSE;
00909       if ( nav_file_name( sz_name , 0 , FS_NAME_CHECK , b_match_case ))
00910          return TRUE;
00911    }
00912 }
00913 
00914 
00920 Bool  nav_filelist_eol( void )
00921 {
00922    if( FALSE == nav_filelist_set( 0 , FS_FIND_NEXT ) )
00923       return TRUE;   // End of list or error (remark: the position haven't changed)
00924 
00925    if( 0 != fs_g_nav.u16_pos_sel_file )
00926    {
00927       // Go to previous position
00928       nav_filelist_set( 0 , FS_FIND_PREV );
00929    }else{
00930       // No select file before, then reset position
00931       fs_g_nav_fast.u16_entry_pos_sel_file= FS_NO_SEL;
00932       fs_g_nav.u16_pos_sel_file           = FS_NO_SEL;
00933       fs_g_nav.b_mode_nav                 = FS_DIR;
00934    }
00935    return FALSE;
00936 }
00937 
00938 
00944 Bool  nav_filelist_bol( void )
00945 {
00946    if( FALSE == nav_filelist_set( 0 , FS_FIND_PREV ) )
00947       return TRUE;   // End of list or error (remark: the position haven't changed)
00948    // Go to previous position
00949    nav_filelist_set( 0 , FS_FIND_NEXT );
00950    return FALSE;
00951 }
00952 
00953 
00962 Bool  nav_filelist_exist( Bool b_type )
00963 {
00964    Bool status;
00965    U16   u16_save_position;
00966 
00967    // Save current position
00968    u16_save_position = fs_g_nav.u16_pos_sel_file;
00969    // Go to first file or directory
00970    status = nav_filelist_first( b_type );
00971    // Restore previous position
00972    nav_filelist_reset();
00973    if ( u16_save_position != FS_NO_SEL )
00974    {
00975       nav_filelist_set( u16_save_position , FS_FIND_NEXT );
00976    }
00977    return status;
00978 }
00979 
00980 
00988 U16   nav_filelist_nb( Bool b_type )
00989 {
00990    U16   u16_save_position;
00991    U16   u16_save_number_dir;
00992    U16   u16_save_number_file;
00993 
00994    // Save current position
00995    u16_save_position = fs_g_nav.u16_pos_sel_file;
00996    // Reset position
00997    if ( !nav_filelist_reset())
00998       return 0;
00999    // Scan all directory
01000    u16_save_number_dir  = 0;
01001    u16_save_number_file = 0;
01002    while( nav_filelist_set( 0 , FS_FIND_NEXT ) )
01003    {
01004       if( FS_FILE == fs_g_nav.b_mode_nav )
01005          u16_save_number_file++;    // It is a file
01006       else
01007          u16_save_number_dir++;     // It is a directory
01008    }
01009    // Restore previous position
01010    nav_filelist_reset();
01011    if ( u16_save_position != FS_NO_SEL )
01012    {
01013       nav_filelist_set( u16_save_position , FS_FIND_NEXT );
01014    }
01015    // Return the value asked
01016    if( FS_FILE == b_type )
01017       return u16_save_number_file;
01018    else
01019       return u16_save_number_dir;
01020 }
01021 
01022 
01031 Bool  nav_filelist_first( Bool b_type )
01032 {
01033    // Reset position
01034    if ( !nav_filelist_reset())
01035       return FALSE;
01036    // Find the first file or directory
01037    while( nav_filelist_set( 0 , FS_FIND_NEXT ) )
01038    {
01039       if( b_type == fs_g_nav.b_mode_nav )
01040          return TRUE;   // First file or directory found
01041    }
01042    fs_g_status = FS_ERR_NO_FIND;
01043    return FALSE;
01044 }
01045 
01046 
01055 Bool  nav_filelist_last( Bool b_type )
01056 {
01057    U16 u16_nb;
01058 
01059    // Get number of file or directory
01060    u16_nb = nav_filelist_nb( b_type  );
01061    if( 0 == u16_nb )
01062    {
01063       fs_g_status = FS_ERR_NO_FIND;
01064       return FALSE;  // NO FILE FOUND
01065    }
01066    // Go to the first file or directory
01067    if ( !nav_filelist_first( b_type ))
01068       return FALSE;
01069    // If there are more one file or directory, then go to at the last of list
01070    if( 1 == u16_nb )
01071       return TRUE;
01072    u16_nb -= 2;
01073    return nav_filelist_set( u16_nb , FS_FIND_NEXT );
01074 }
01075 
01076 
01077 //**********************************************************************
01078 //************************ Index functions *****************************
01079 
01080 
01090 Fs_index nav_getindex( void )
01091 {
01092    Fs_index index;
01093 
01094    // Fill index structure
01095    index.u8_lun                  = fs_g_nav.u8_lun;
01096 #if (FS_MULTI_PARTITION  ==  ENABLED)
01097    index.u8_partition            = fs_g_nav.u8_partition;
01098 #endif
01099    index.u32_cluster_sel_dir     = fs_g_nav.u32_cluster_sel_dir;
01100    index.u16_entry_pos_sel_file  = fs_g_nav_fast.u16_entry_pos_sel_file;
01101    return index;
01102 }
01103 
01104 
01117 Bool  nav_gotoindex( const Fs_index _MEM_TYPE_SLOW_ *index )
01118 {
01119    // Select the drive and partition corresponding at file index
01120    if( !nav_drive_set( index->u8_lun ))
01121       return FALSE;
01122 #if (FS_MULTI_PARTITION  ==  ENABLED)
01123    if( !nav_partition_set(index->u8_partition))
01124       return FALSE;
01125 #endif
01126    if( !nav_partition_mount())
01127       return FALSE;
01128 
01129    // Select the directory corresponding at file index
01130    fs_g_nav.u32_cluster_sel_dir   = index->u32_cluster_sel_dir;
01131 
01132    // Search the file position corresponding at file index
01133    if ( !nav_filelist_reset())
01134       return FALSE;
01135    while( fs_g_nav_fast.u16_entry_pos_sel_file != index->u16_entry_pos_sel_file )
01136    {
01137       if( !nav_filelist_set( 0 , FS_FIND_NEXT ) )
01138       {
01139          nav_filelist_reset();
01140          return FALSE;
01141       }
01142    }
01143    return TRUE;
01144 }
01145 
01146 
01147 //**********************************************************************
01148 //************************ Directory functions *************************
01149 
01150 
01156 Bool  nav_dir_root( void )
01157 {
01158    return nav_partition_mount();
01159 }
01160 
01161 
01167 Bool  nav_dir_is_root( void )
01168 {
01169    if (!fat_check_mount_noopen())
01170       return FALSE;
01171 
01172    return (0 == fs_g_nav.u32_cluster_sel_dir);
01173 }
01174 
01175 
01186 Bool  nav_dir_cd( void )
01187 {
01188    if ( !fat_check_mount_select_noopen())
01189       return FALSE;
01190 
01191    // The current selection, is it a directory ?
01192    if ( !fat_entry_is_dir())
01193       return FALSE;
01194 
01195    // Select the current directory
01196    fs_g_nav.u16_entry_pos_sel_dir = fs_g_nav_fast.u16_entry_pos_sel_file;
01197    fs_g_nav.u32_cluster_sel_dir = fs_g_nav_entry.u32_cluster;
01198 
01199    // Reset file list
01200    if( FALSE == nav_filelist_reset())
01201       return FALSE;
01202    return TRUE;
01203 }
01204 
01205 
01216 Bool  nav_dir_gotoparent( void )
01217 {
01218    U32 u32_cluster_old_dir;
01219 
01220    if (!fat_check_mount_noopen())
01221       return FALSE;
01222 
01223    if (0 == fs_g_nav.u32_cluster_sel_dir)
01224    {
01225       fs_g_status = FS_ERR_IS_ROOT;        // There aren't parent
01226       return FALSE;
01227    }
01228 
01229    // Select and read information about directory ".."
01230    fs_g_nav_fast.u16_entry_pos_sel_file = 1;
01231    if ( !fat_read_dir())
01232       return FALSE;
01233    fat_get_entry_info();
01234    // Save the children directory cluster
01235    u32_cluster_old_dir = fs_g_nav.u32_cluster_sel_dir;
01236 
01237    // Select the parent directory via information present in the current directory ".."
01238    fs_g_nav.u32_cluster_sel_dir = fs_g_nav_entry.u32_cluster;
01239 
01240    // Select the children directory in new directory (=parent directory)
01241    if( FALSE == nav_filelist_reset())
01242       return FALSE;
01243    if( fs_g_nav.b_mode_nav_single && (FS_DIR != fs_g_nav.b_mode_nav) )
01244       return TRUE;
01245    
01246    while( nav_filelist_set( 0 , FS_FIND_NEXT ) )
01247    {
01248       if (fs_g_nav_entry.u32_cluster == u32_cluster_old_dir)
01249          return TRUE;         // It is the children directory
01250    }
01251    fs_g_status = FS_ERR_FS;
01252    return FALSE;
01253 }
01254 
01255 
01264 Bool  nav_dir_name( FS_STRING sz_path  , U8 u8_size_max  )
01265 {
01266    U8 u8_i, u8_character;
01267    Bool status = FALSE;
01268    U16 save_u16_entry_pos_sel_file;
01269    U32 save_u32_cluster_sel_dir;
01270    U8  save_u8_attr          ;
01271    U32 save_u32_cluster      ;
01272    U32 save_u32_size         ;
01273    Bool b_mode_nav_single_save;
01274    Bool b_mode_nav_mode_save;
01275 
01276    if ( !fat_check_mount_noopen())
01277       return FALSE;
01278 
01279    if (0 != fs_g_nav.u32_cluster_sel_dir)
01280    {
01281       // Save context
01282       save_u16_entry_pos_sel_file= fs_g_nav_fast.u16_entry_pos_sel_file;
01283       save_u32_cluster_sel_dir   = fs_g_nav.u32_cluster_sel_dir        ;
01284       save_u8_attr               = fs_g_nav_entry.u8_attr              ;
01285       save_u32_cluster           = fs_g_nav_entry.u32_cluster          ;
01286       save_u32_size              = fs_g_nav_entry.u32_size             ;
01287       b_mode_nav_single_save = fs_g_nav.b_mode_nav_single;
01288       b_mode_nav_mode_save   = fs_g_nav.b_mode_nav;
01289       fs_g_nav.b_mode_nav_single = TRUE;
01290       fs_g_nav.b_mode_nav = FS_FILE;
01291       // Go to parent directory and select the children directory
01292       if( !nav_dir_gotoparent() )
01293       {
01294          fs_g_nav.b_mode_nav_single = b_mode_nav_single_save;
01295          fs_g_nav.b_mode_nav = b_mode_nav_mode_save;
01296          return FALSE;
01297       }
01298       fs_g_nav.b_mode_nav_single = b_mode_nav_single_save ;
01299       fs_g_nav.b_mode_nav = b_mode_nav_mode_save;
01300       // Go to directory name position
01301       fs_g_nav_fast.u16_entry_pos_sel_file = fs_g_nav.u16_entry_pos_sel_dir;
01302       status = nav_file_name( sz_path  , u8_size_max , FS_NAME_GET , FALSE  );
01303       // Restore previous context
01304       fs_g_nav_fast.u16_entry_pos_sel_file= save_u16_entry_pos_sel_file;
01305       fs_g_nav.u32_cluster_sel_dir        = save_u32_cluster_sel_dir   ;
01306       fs_g_nav_entry.u8_attr              = save_u8_attr               ;
01307       fs_g_nav_entry.u32_cluster          = save_u32_cluster           ;
01308       fs_g_nav_entry.u32_size             = save_u32_size              ;
01309    }
01310    else
01311    {
01312       // No parent directory, then it is the root directory
01313       if( g_b_string_length )
01314       {
01315          ((FS_STR_UNICODE)sz_path )[0] = 3;  // 3 chars for path "x:"
01316          status = TRUE;
01317       }else
01318 
01319       // Create a device name
01320       for( u8_i = 0 ; u8_i<3 ; u8_i++ )
01321       {
01322          switch( u8_i )
01323          {
01324             case 0:
01325             u8_character = nav_drive_getname();    // Letter
01326             break;
01327             case 1:
01328             u8_character = ':';                     // ":"
01329             break;
01330             case 2:
01331             default:
01332             u8_character = 0;                       // end of string
01333             break;
01334          }
01335          if( Is_unicode )
01336          {
01337             ((FS_STR_UNICODE)sz_path )[0] = u8_character;
01338          }else{
01339             sz_path [0] = u8_character;
01340          }
01341          sz_path  += (Is_unicode? 2 : 1 );
01342       }
01343       status = TRUE;
01344 
01345    }
01346    return status;
01347 }
01348 
01349 
01350 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
01358 Bool  nav_dir_make( const FS_STRING sz_name  )
01359 {
01360    if ( !fat_check_mount_noopen())
01361       return FALSE;
01362 
01363    // Create an entry file
01364    if ( !nav_file_create( sz_name ))
01365       return FALSE;
01366 
01367    // Allocate one cluster for the new directory
01368    MSB0(fs_g_seg.u32_addr)=0xFF;    // It is a new cluster list
01369    fs_g_seg.u32_size_or_pos = 1;    // Only one sector (= one cluster)
01370    if ( !fat_allocfreespace())
01371    {
01372       fat_delete_file( FALSE );
01373       fat_cache_flush();
01374       return FALSE;
01375    }
01376    
01377    // Save information about the new directory
01378    fs_g_nav_entry.u32_cluster = fs_g_seg.u32_addr; // First cluster of the directory returned by alloc_free_space
01379    fs_g_nav_entry.u32_size    = 0;                 // The directory size is null
01380    fs_g_nav_entry.u8_attr     = FS_ATTR_DIRECTORY; // Directory attribut
01381 
01382    // Initialize the values in the new directory
01383    if ( !fat_initialize_dir())
01384       return FALSE;
01385 
01386    // Write directory information in her entry file
01387    if ( !fat_read_dir())
01388       return FALSE;
01389    fat_write_entry_file();
01390    if( !fat_cache_flush())
01391       return FALSE;
01392 
01393    // Go to position of new directory (it is the last directory)
01394    return nav_filelist_last( FS_DIR );
01395 }
01396 #endif  // FS_LEVEL_FEATURES
01397 
01398 
01408 Bool  nav_getcwd( FS_STRING sz_path  , U8 u8_size_path , Bool b_view_file_select  )
01409 {
01410    _MEM_TYPE_SLOW_   Fs_index index;
01411    _MEM_TYPE_SLOW_   U16 u16_lgt=0;    // Only used if LENGTH string mode enabled
01412    U8 u8_save_size_path=0, u8_i;
01413    Bool status = FALSE;                // Error by default
01414 
01415    if ( !fat_check_mount_noopen())
01416       return FALSE;
01417 
01418    index = nav_getindex();             // Save current position
01419 
01420    if( g_b_string_length )
01421    {
01422       u16_lgt = 1;   // 1 for NULL terminate
01423    }
01424    else
01425    {
01426       u8_save_size_path = u8_size_path;
01427       // Set NULL terminator at the end of path
01428       u8_size_path--;
01429       if( Is_unicode )
01430       {
01431          ((FS_STR_UNICODE)sz_path )[u8_size_path] = 0;
01432       }else{
01433          sz_path [u8_size_path]   = 0;
01434       }
01435    }
01436 
01437    // For each directory of path
01438    while( 1 )
01439    {
01440       if( b_view_file_select )
01441       {
01442          // Write the selected file or directory in path
01443          b_view_file_select = FALSE;
01444          if( !fat_check_select() )
01445             continue;   // No selected file or directory, then restart loop to go at the first directory of path
01446       }
01447       else
01448       {
01449          // Go to parent directory and selects the children directory
01450          if( !nav_dir_gotoparent() )
01451             break;
01452       }
01453 
01454       // Read name of selected file or directory
01455       if( !nav_file_name( sz_path  , u8_size_path , FS_NAME_GET, FALSE  ))
01456          break;
01457 
01458       if( g_b_string_length )
01459       {
01460          // Update total length
01461          u16_lgt += ((FS_STR_UNICODE)sz_path )[0]; // 0 = -1 to remove NULL terminated and +1 for '\\'
01462          continue;
01463       }
01464 
01465       // Compute the size of name
01466       u8_i = 0;
01467       while( 1 )
01468       {
01469          if( Is_unicode )
01470          {
01471             if( 0 == ((FS_STR_UNICODE)sz_path )[u8_i])
01472                break;
01473          }else{
01474             if( 0 == sz_path [u8_i])
01475                break;
01476          }
01477          u8_i++;
01478       }
01479 
01480       // Check the string size
01481       if( (u8_i+1) == u8_size_path )
01482       {
01483          fs_g_status = FS_ERR_BUFFER_FULL;   // The path string is full
01484          break;
01485       }
01486 
01487       // Move the name at the end of path
01488       while( 0 != u8_i )
01489       {
01490          u8_i--;
01491          u8_size_path--;
01492          if( Is_unicode )
01493          {
01494             ((FS_STR_UNICODE)sz_path )[u8_size_path] = ((FS_STR_UNICODE)sz_path )[u8_i];
01495          }else{
01496             sz_path [u8_size_path]   = sz_path [u8_i];
01497          }
01498       }
01499       // Set '\' char before the name
01500       u8_size_path--;
01501       if( Is_unicode )
01502       {
01503          ((FS_STR_UNICODE)sz_path )[u8_size_path] = '\\';
01504       }else{
01505          sz_path [u8_size_path]   = '\\';
01506       }
01507    }
01508 
01509    if ( FS_ERR_IS_ROOT == fs_g_status )
01510    {
01511       if( g_b_string_length )
01512       {
01513          // Update and write total length
01514          ((FS_STR_UNICODE)sz_path )[0] = u16_lgt +2 ; //+2 for "x:"
01515          status = TRUE;
01516       }
01517       else
01518       {
01519          // End of path then add device name
01520          if( 2 > u8_size_path )
01521          {
01522             fs_g_status = FS_ERR_BUFFER_FULL;   // The path string is full
01523          }
01524          else
01525          {
01526             // Create a device name
01527             if( Is_unicode )
01528             {
01529                ((FS_STR_UNICODE)sz_path )[0] = nav_drive_getname();    // Letter
01530                ((FS_STR_UNICODE)sz_path )[1] = ':';                   // ":"
01531             }else{
01532                sz_path [0] = nav_drive_getname();    // Letter
01533                sz_path [1] = ':';                      // ":"
01534             }
01535 
01536             // The path is stored at the end, then move the path at the beginning
01537             u8_i = 2;
01538             while( u8_save_size_path != u8_size_path )
01539             {
01540                if( Is_unicode )
01541                {
01542                   ((FS_STR_UNICODE)sz_path )[u8_i] = ((FS_STR_UNICODE)sz_path )[u8_size_path];
01543                }else{
01544                   sz_path [u8_i] = sz_path [u8_size_path];
01545                }
01546                u8_i++;
01547                u8_size_path++;
01548             }
01549             status = TRUE;
01550          }
01551       }
01552    } // else Error system
01553 
01554    nav_gotoindex( &index );   // Restore the position
01555    return status;
01556 }
01557 
01558 
01575 Bool  nav_setcwd( FS_STRING sz_path , Bool b_match_case , Bool b_create )
01576 {
01577    _MEM_TYPE_SLOW_   Fs_index index;
01578 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE)) ||              \
01579     (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
01580    FS_STRING sz_save_path = 0;
01581 #endif
01582    Bool b_create_name = FALSE;
01583 
01584    if ( !fat_check_noopen())
01585       return FALSE;
01586 
01587    index = nav_getindex();             // Save current position
01588 
01589    // Check syntact "\path..."
01590    if( (( Is_unicode) && (('\\'  == ((FS_STR_UNICODE)sz_path )[0]) || ('/'  == ((FS_STR_UNICODE)sz_path )[0])) )
01591    ||  ((!Is_unicode) && (('\\'  == sz_path [0]) || ('/'  == sz_path [0])) ) )
01592    {
01593       // Go to the root of current drive
01594       if( !nav_dir_root())
01595          goto nav_setcwd_fail;
01596       sz_path  += (Is_unicode? 2 : 1 );
01597    }else
01598 
01599    // Check syntact "x:\path..."
01600    if( (( Is_unicode) && (( ':'  == ((FS_STR_UNICODE)sz_path )[1] ) && (('\\'  == ((FS_STR_UNICODE)sz_path )[2] ) || ('/'  == ((FS_STR_UNICODE)sz_path )[2]))) )
01601    ||  ((!Is_unicode) && (( ':'  == sz_path [1] ) && (('\\'  == sz_path [2] ) || ('/'  == sz_path [2]))) ) )
01602    {
01603       // Go to the drive
01604       if( Is_unicode )
01605       {
01606          if( !nav_drive_set( toupper(((FS_STR_UNICODE)sz_path )[0])-'A' ) )
01607             goto nav_setcwd_fail;
01608       }else{
01609          if( !nav_drive_set( toupper(sz_path [0])-'A' ) )
01610             goto nav_setcwd_fail;
01611       }
01612       if( !nav_partition_mount())
01613          goto nav_setcwd_fail;
01614       sz_path  += 3*(Is_unicode? 2 : 1 );
01615    }else
01616 
01617    // Check syntact ".\path..."
01618    if( (( Is_unicode) && (( '.'  == ((FS_STR_UNICODE)sz_path )[0] ) && (('\\'  == ((FS_STR_UNICODE)sz_path )[1] ) || ('/'  == ((FS_STR_UNICODE)sz_path )[1] ))) )
01619    ||  ((!Is_unicode) && (( '.'  == sz_path [0] ) && (('\\'  == sz_path [1] ) || ('/'  == sz_path [1] ))) ) )
01620    {
01621       // Search in current directory
01622       sz_path  += 2*(Is_unicode? 2 : 1 );
01623    }else
01624 
01625    {
01626       // Check syntact "..\..\path..."
01627       if( Is_unicode )
01628       {
01629          while(( '.'  == ((FS_STR_UNICODE)sz_path )[0] )
01630          &&    ( '.'  == ((FS_STR_UNICODE)sz_path )[1] )
01631          &&    (('\\'  == ((FS_STR_UNICODE)sz_path )[2]) || ('/'  == ((FS_STR_UNICODE)sz_path )[2]) || (0  == ((FS_STR_UNICODE)sz_path )[2])) )
01632          {
01633             // Go to parent directory
01634             if( !nav_dir_gotoparent() )
01635                goto nav_setcwd_fail;
01636             sz_path  += (2*2); // jump ".."
01637             if( 0 != ((FS_STR_UNICODE)sz_path )[0])
01638                sz_path  += (2*1); // jump "/"
01639          }
01640       }else{
01641          while(( '.'  == sz_path [0] )
01642          &&    ( '.'  == sz_path [1] )
01643          &&    (('\\'  == sz_path [2]) || ('/'  == sz_path [2]) || (0  == sz_path [2])) )
01644          {
01645          // Go to parent directory
01646          if( !nav_dir_gotoparent() )
01647             goto nav_setcwd_fail;
01648             sz_path  += 2; // jump ".."
01649             if( 0 != sz_path [0])
01650                sz_path  +=1; // jump "/"
01651          }
01652       }
01653    }
01654 
01655    // Reset list to start the search at the beginning
01656    if( !nav_filelist_reset())
01657       goto nav_setcwd_fail;
01658 
01659    while( 1 )
01660    {
01661       if( (( Is_unicode) && ( 0 == ((FS_STR_UNICODE)sz_path )[0] ) )
01662       ||  ((!Is_unicode) && ( 0 == sz_path [0] ) ) )
01663       {
01664          return TRUE;   // path (without file) is found or create
01665       }
01666       if( !nav_filelist_findname( sz_path  , b_match_case  ))
01667       {
01668          // The file or directory is not found
01669          if( !b_create )
01670             goto nav_setcwd_fail;   // don't creat the directory then exit
01671          // Set flag to create the directory
01672          b_create_name = TRUE;
01673 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE)) ||              \
01674     (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
01675          sz_save_path = sz_path;
01676 #endif
01677       }
01678 
01679       while( 1 )
01680       {
01681          sz_path  += (Is_unicode? 2 : 1 );
01682          if( (( Is_unicode) && ( 0 == ((FS_STR_UNICODE)sz_path )[0] ) )
01683          ||  ((!Is_unicode) && ( 0 == sz_path [0] ) ) )
01684          {
01685             // Is it the last name of path and it is a file
01686             if( b_create_name )
01687             {
01688 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
01689                // The file must be created
01690                if( !nav_file_create( sz_save_path ) )
01691                   goto nav_setcwd_fail;
01692 #else
01693                goto nav_setcwd_fail;
01694 #endif
01695             }
01696             break;   // The file include in path is found or created, then end of set_cwd
01697          }
01698 
01699          if( (( Is_unicode) && (('\\' == ((FS_STR_UNICODE)sz_path )[0] ) || ('/' == ((FS_STR_UNICODE)sz_path )[0] )) )
01700          ||  ((!Is_unicode) && (('\\' == sz_path [0] ) || ('/' == sz_path [0] )) ) )
01701          {
01702             // Is it a folder name
01703             if( b_create_name )
01704             {
01705 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
01706                // The folder doesn't exist and it must be created
01707                if( !nav_dir_make( sz_save_path ))
01708                   goto nav_setcwd_fail;
01709 #else
01710                goto nav_setcwd_fail;
01711 #endif
01712             }
01713             if( !fat_entry_is_dir() )
01714                goto nav_setcwd_fail;
01715             // jump '\'
01716             sz_path  += (Is_unicode? 2 : 1 );
01717             if( !nav_dir_cd())
01718                goto nav_setcwd_fail;
01719             break;
01720          }
01721       }
01722 
01723    }
01724 
01725 nav_setcwd_fail:
01726    nav_gotoindex( &index );   // Restore the position
01727    return FALSE;
01728 }
01729 
01730 
01731 
01732 
01733 //**********************************************************************
01734 //*********************** File control functions ***********************
01735 
01736 
01745 Bool nav_file_getname( FS_STRING sz_name, U8 u8_size_max )
01746 {
01747    return nav_file_name( sz_name, u8_size_max, FS_NAME_GET, FALSE );
01748 }
01749 
01750 
01766 Bool  nav_file_name( FS_STRING sz_name , U8 u8_size_max , Bool b_mode , Bool b_match_case  )
01767 {
01768    _MEM_TYPE_SLOW_   U16 u16_lgt;   // Only used if LENGTH string mode enabled
01769    U16  u16_ptr_save_entry;
01770    Bool  b_readshortname = FALSE;
01771 
01772    if ( !fat_check_mount_select())
01773       return FALSE;
01774 
01775    // Check if the string size is not 0
01776    if( (FS_NAME_GET == b_mode)
01777    &&  (0 == u8_size_max) )
01778    {
01779       return TRUE;
01780    }
01781 
01782    // Save the current entry position
01783    u16_ptr_save_entry = fs_g_nav_fast.u16_entry_pos_sel_file;
01784    // if it is the beginning of the directory
01785    if ( 0 == fs_g_nav_fast.u16_entry_pos_sel_file )
01786    {
01787       b_readshortname = TRUE;                   // It isn't possibled to have a long name
01788    }
01789    else
01790    {
01791       fs_g_nav_fast.u16_entry_pos_sel_file--;   // Initialize entry position to search the first long name entry
01792    }
01793 
01794    // Loop in directory entry
01795    u16_lgt = 0;
01796    while( 1 )
01797    {
01798       if ( !fat_read_dir())
01799          break; // error
01800 
01801       if ( b_readshortname )
01802       {
01803          // No long name present then read short name
01804          return fat_entry_shortname( sz_name , u8_size_max , b_mode  );
01805       }
01806 
01807       // Check or read the part of long file name in this entry
01808       if ( fat_entry_longname( sz_name , u8_size_max , b_mode , b_match_case  ))
01809       {
01810          if( g_b_string_length )
01811          {
01812             ((FS_STR_UNICODE)sz_name )[0] += u16_lgt;
01813          }
01814          fs_g_nav_fast.u16_entry_pos_sel_file = u16_ptr_save_entry;
01815          return TRUE;
01816       }
01817 
01818       if ( FS_NO_LAST_LFN_ENTRY != fs_g_status )
01819       {
01820          // Go to the main entry file (=short name entry)
01821          fs_g_nav_fast.u16_entry_pos_sel_file = u16_ptr_save_entry;
01822 
01823          if ( FS_ERR_ENTRY_BAD == fs_g_status )
01824          {
01825             // It isn't a long name entry then there aren't long file name
01826             b_readshortname = TRUE;   // It is mandatory to use the short name
01827             continue;                 // restart the loop
01828          }
01829          // here, it is a error system or the string don't match with the file name
01830          break;
01831       }
01832       if( g_b_string_length )
01833       {
01834          u16_lgt += FS_SIZE_LFN_ENTRY;
01835       }
01836       else
01837       {
01838          // Increment the string to store the next part of file name
01839          sz_name += FS_SIZE_LFN_ENTRY * (Is_unicode? 2 : 1 );
01840          u8_size_max -= FS_SIZE_LFN_ENTRY;
01841       }
01842       fs_g_nav_fast.u16_entry_pos_sel_file--;   // Go to the next part of long file name
01843 
01844    }  // end of loop while(1)
01845    return FALSE;
01846 }
01847 
01848 
01853 U32   nav_file_lgt( void )
01854 {
01855    return fs_g_nav_entry.u32_size;
01856 }
01857 
01858 
01863 U16   nav_file_lgtsector( void )
01864 {
01865    return (fs_g_nav_entry.u32_size >> FS_512B_SHIFT_BIT);
01866 }
01867 
01868 
01874 Bool  nav_file_isreadonly( void )
01875 {
01876    if( !fat_check_mount_select() )
01877       return TRUE;   // No file selected
01878    if( mem_wr_protect( fs_g_nav.u8_lun ) )
01879       return TRUE;   // Disk protected
01880    return (0!=(FS_ATTR_READ_ONLY & fs_g_nav_entry.u8_attr));   // Check attribut "read only"
01881 }
01882 
01883 
01889 Bool  nav_file_isdir( void )
01890 {
01891    return fat_entry_is_dir();
01892 }
01893 
01894 
01902 Bool  nav_file_checkext( const FS_STRING sz_filterext )
01903 {
01904    if ( fat_check_mount_select() )
01905    {
01906       // Read selected entry (=short name entry) in directory
01907       if ( fat_read_dir())
01908       {
01909          // Check the extension with filter
01910          if ( fat_entry_checkext( (FS_STRING) sz_filterext ) )
01911             return TRUE;
01912       }
01913    }
01914    return FALSE;
01915 }
01916 
01917 
01928 Bool  nav_file_dateget( FS_STRING sz_date , Bool type_date )
01929 {
01930    if ( !fat_check_mount_select())
01931       return FALSE;
01932 
01933    // Read selected entry in directory
01934    if ( !fat_read_dir())
01935       return FALSE;
01936    fat_get_date( sz_date , type_date );
01937    return TRUE;
01938 }
01939 
01940 
01945 U8    nav_file_attributget( void )
01946 {
01947    return fs_g_nav_entry.u8_attr;
01948 }
01949 
01950 
01951 
01952 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
01963 Bool  nav_file_dateset( const FS_STRING sz_date , Bool type_date )
01964 {
01965    if ( !fat_check_mount_select())
01966       return FALSE;
01967 
01968    // Read selected entry in directory
01969    if ( !fat_read_dir())
01970       return FALSE;
01971    fat_set_date( sz_date , type_date );
01972    return fat_cache_flush();  // To write all data and check write access before exit function
01973 }
01974 #endif  // FS_LEVEL_FEATURES
01975 
01976 
01977 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
01985 Bool  nav_file_attributset( U8 u8_attribut )
01986 {
01987    if ( !fat_check_mount_select())
01988       return FALSE;
01989 
01990    // Read selected entry in directory
01991    if ( !fat_read_dir())
01992       return FALSE;
01993 
01994    // Write the new attribut
01995    fs_g_nav_entry.u8_attr &= (~(FS_ATTR_READ_ONLY|FS_ATTR_HIDDEN|FS_ATTR_SYSTEM|FS_ATTR_ARCHIVE));
01996    fs_g_nav_entry.u8_attr |= u8_attribut & (FS_ATTR_READ_ONLY|FS_ATTR_HIDDEN|FS_ATTR_SYSTEM|FS_ATTR_ARCHIVE);
01997    fat_write_entry_file();
01998    return fat_cache_flush();  // To write all data and check write access before exit function
01999 }
02000 #endif  // FS_LEVEL_FEATURES
02001 
02002 
02003 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
02013 Bool  nav_file_del( Bool b_only_empty )
02014 {
02015    U8 u8_folder_level = 0xFF;
02016 
02017    if ( !fat_check_mount_select_noopen())
02018       return FALSE;
02019 
02020    if( 0xFF == u8_folder_level )  // to remove a eventually compile warning
02021      goto nav_file_del_test_dir_or_file;
02022 
02023    // loop to scan and delete ALL folders and ALL files
02024    while(1)
02025    {
02026       while(1)
02027       {
02028          if( nav_filelist_set( 0 , FS_FIND_NEXT ) )
02029          {
02030             // Directory no empty
02031             if( b_only_empty )
02032             {
02033                fs_g_status = FS_ERR_DIR_NOT_EMPTY;      // Erase only the empty directory
02034                return FALSE;
02035             }
02036             break; // Exit loop to delete files or directories present
02037          }
02038          // HERE, directory empty
02039 
02040          // Go to parent directory and this one select the children directory
02041          if( !nav_dir_gotoparent() )
02042             return FALSE;
02043 
02044          // Delete children directory name and her cluster list
02045          if ( !fat_delete_file( TRUE ))
02046             return FALSE;
02047 
02048          if( 0 == u8_folder_level )
02049          {
02050             // All directory tree is deleted
02051             return TRUE; //********* END OF DEL TREE **************
02052          }
02053          u8_folder_level--;
02054 
02055       } // end of second while (1)
02056 
02057 nav_file_del_test_dir_or_file:
02058       if( nav_file_isdir())
02059       {
02060          // here, a directory is found and is selected
02061          if( !nav_dir_cd())
02062             return FALSE;
02063          u8_folder_level++;
02064       }
02065       else
02066       {
02067          // here, a file is found and is selected
02068          if( !fat_check_nav_access_file( TRUE ) )
02069             return FALSE;
02070          // delete file entry name and cluster list
02071          if ( !fat_delete_file( TRUE ))
02072             return FALSE;
02073          if( 0xFF == u8_folder_level )
02074             break;   // only one file to delete
02075       } // if dir OR file
02076    } // end of first while(1)
02077 
02078    // Reset selection
02079    nav_filelist_reset();
02080    return fat_cache_flush();  // To write all data and check write access before exit function
02081 }
02082 #endif  // FS_LEVEL_FEATURES
02083 
02084 
02085 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
02093 Bool  nav_file_rename( const FS_STRING sz_name  )
02094 {
02095    U16 u16_save_entry_pos;
02096    Bool b_save_entry_type;
02097    U8 u8_attr;
02098    U32 u32_cluster;
02099    U32 u32_size;
02100 
02101    if ( !fat_check_mount_select_noopen())
02102       return FALSE;
02103 
02104    if( !fat_check_nav_access_file( TRUE ) )
02105       return FALSE;
02106 
02107    // Note: in case of error, create the new name before delete the current name
02108 
02109    // Save information about current name poisition
02110    u16_save_entry_pos = fs_g_nav_fast.u16_entry_pos_sel_file;
02111    b_save_entry_type  = fs_g_nav.b_mode_nav;
02112    // Save information about file
02113    u8_attr           = fs_g_nav_entry.u8_attr;
02114    u32_cluster       = fs_g_nav_entry.u32_cluster;
02115    u32_size          = fs_g_nav_entry.u32_size;
02116 
02117    // Create a name
02118    if ( !nav_file_create( sz_name  ))
02119       return FALSE; // error
02120    // Restore information about file or directory on the new name entry
02121    if ( !fat_read_dir())
02122       return FALSE;
02123    fs_g_nav_entry.u8_attr = u8_attr;
02124    fs_g_nav_entry.u32_cluster = u32_cluster;
02125    fs_g_nav_entry.u32_size = u32_size;
02126    fat_write_entry_file();
02127 
02128    // Delete old entry name
02129    fs_g_nav_fast.u16_entry_pos_sel_file = u16_save_entry_pos; // go to old entry name
02130    if ( !fat_delete_file(FALSE) )
02131       return FALSE;
02132    if ( !fat_cache_flush() )
02133       return FALSE;
02134 
02135    // Go to at the position of the new name entry (it is the last file or directory )
02136    return nav_filelist_last( b_save_entry_type );
02137 }
02138 #endif  // FS_LEVEL_FEATURES
02139 
02140 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
02141 
02153 Bool  nav_file_create( const FS_STRING sz_name  )
02154 {
02155    // Check if the name already exists
02156    if (!nav_filelist_reset())
02157       return FALSE;
02158    if (nav_filelist_findname(sz_name , FALSE))
02159    {
02160       fs_g_status = FS_ERR_FILE_EXIST;
02161       return FALSE;  // File exist -> it is not possible to create this name
02162    }
02163    // FYC: here, the selection is at the end of the list
02164    // Create name entrys
02165    if ( !fat_create_entry_file_name( sz_name ))
02166       return FALSE; // error
02167    // By default the information about the new file is NULL
02168    fs_g_nav_entry.u32_cluster = 0;     // No first cluster
02169    fs_g_nav_entry.u32_size    = 0;     // The size is null
02170    fs_g_nav_entry.u8_attr     = 0;     // Attribut is a file
02171 
02172    // It is the last FILE of the list
02173    fs_g_nav.u16_pos_sel_file++;
02174    fs_g_nav.b_mode_nav = FS_FILE;
02175    return fat_cache_flush();
02176 }
02177 
02178 
02188 Bool  nav_file_copy( void )
02189 {
02190    if( nav_file_isdir() )
02191    {
02192       fs_g_status = FS_ERR_COPY_DIR; // Impossible to copy a directory
02193       return FALSE;
02194    }
02195    // In "copy file" navigator select the file
02196    nav_copy( FS_NAV_ID_COPYFILE );
02197    return TRUE;
02198 }
02199 
02200 
02212 Bool  nav_file_paste_start( const FS_STRING sz_name  )
02213 {
02214    U8 nav_id_save;
02215    Bool status;
02216 
02217    if( ID_STREAM_ERR != g_id_trans_memtomem )
02218    {
02219 
02220       fs_g_status = FS_ERR_COPY_RUNNING;  // A copy action is always running
02221       return FALSE;
02222    }
02223 
02224    // Create the file to paste
02225    if( !nav_file_create( sz_name  ) )
02226       return FALSE;
02227    // Open the file in write mode with size 0
02228    if( !file_open( FOPEN_MODE_W_PLUS ))
02229       return FALSE;
02230 
02231    // Open the file to copy
02232    nav_id_save = nav_get();
02233    nav_select( FS_NAV_ID_COPYFILE );
02234    status = file_open(FOPEN_MODE_R);
02235    nav_select( nav_id_save );
02236 
02237    // If error then close "paste file"
02238    if( !status )
02239    {
02240       file_close();
02241       return FALSE;
02242    }else{
02243       // Signal start copy
02244       g_id_trans_memtomem = ID_STREAM_ERR-1;
02245       g_segment_src.u16_size = 0;
02246       return TRUE;
02247    }
02248 }
02249 
02250 
02260 U8    nav_file_paste_state( Bool b_stop )
02261 {
02262    Ctrl_status status_stream;
02263    U8 status_copy;
02264    U8 nav_id_save;
02265    _MEM_TYPE_SLOW_ U16 u16_nb_sector_trans;
02266 
02267    nav_id_save = nav_get();
02268 
02269    // Check, if the copy is running
02270    if( ID_STREAM_ERR == g_id_trans_memtomem )
02271       return COPY_FAIL;
02272 
02273    if( b_stop )
02274    {
02275       status_copy = COPY_FAIL;
02276    }
02277    else
02278    {
02279       if( (ID_STREAM_ERR-1) != g_id_trans_memtomem )
02280       {
02281          // It isn't the beginning of copy action, then check current stream
02282          status_stream = stream_state( g_id_trans_memtomem );
02283          switch( status_stream )
02284          {
02285          case CTRL_BUSY:
02286             status_copy = COPY_BUSY;
02287             break;
02288          case CTRL_GOOD:
02289             status_copy = COPY_FINISH;
02290             break;
02291          case CTRL_FAIL:
02292          default:
02293             status_copy = COPY_FAIL;
02294             break;
02295          }
02296       }else{
02297          status_copy = COPY_FINISH;
02298       }
02299 
02300       // Compute the new segment to copy
02301       if( COPY_FINISH == status_copy )
02302       {
02303          stream_stop( g_id_trans_memtomem );
02304 
02305          if( 0 != g_segment_src.u16_size )
02306          {
02307             status_copy = COPY_BUSY;            // start the next continue stream
02308          }
02309          else
02310          {
02311             // check eof source file
02312             nav_select( FS_NAV_ID_COPYFILE );
02313             if( 0 == file_eof() )
02314             {
02315                status_copy = COPY_BUSY;
02316                g_segment_src.u16_size = 0xFFFF; // Get the maximum segment supported by navigation (U16)
02317                if( !file_read( &g_segment_src ))
02318                {
02319                   status_copy = COPY_FAIL;
02320                }
02321             }
02322             nav_select( nav_id_save );
02323            
02324             // Check destination file
02325             if( COPY_BUSY == status_copy )
02326             {
02327                 g_segment_dest.u16_size = g_segment_src.u16_size; // Ask the segment no more larger than source segment
02328                 if( !file_write( &g_segment_dest ))
02329                {
02330                   status_copy = COPY_FAIL;
02331                }
02332             }
02333            
02334             // Start new segment copy
02335             if( COPY_BUSY == status_copy )
02336             {
02337                // Compute a minimal segment
02338                 if( g_segment_src.u16_size > g_segment_dest.u16_size )
02339                {
02340                   // Reposition source file
02341                   nav_select( FS_NAV_ID_COPYFILE );
02342                    if( !file_seek( (U32)(g_segment_src.u16_size - g_segment_dest.u16_size)*FS_512B , FS_SEEK_CUR_RE ))
02343                   {
02344                      status_copy = COPY_FAIL;
02345                   }
02346                   nav_select( nav_id_save );
02347                    g_segment_src.u16_size = g_segment_dest.u16_size; // Update source to start a correct transfer
02348                }
02349             }
02350          }
02351          if( COPY_BUSY == status_copy )
02352          {
02353             // Split transfer by step of SIZE_OF_SPLIT_COPY
02354             if( g_segment_src.u16_size < SIZE_OF_SPLIT_COPY )
02355                u16_nb_sector_trans = g_segment_src.u16_size;
02356             else
02357                u16_nb_sector_trans = SIZE_OF_SPLIT_COPY;
02358 
02359             g_id_trans_memtomem = stream_mem_to_mem( g_segment_src.u8_lun , g_segment_src.u32_addr , g_segment_dest.u8_lun , g_segment_dest.u32_addr , u16_nb_sector_trans );
02360             if( ID_STREAM_ERR == g_id_trans_memtomem )
02361                   status_copy = COPY_FAIL;
02362             g_segment_src.u32_addr +=u16_nb_sector_trans;
02363             g_segment_dest.u32_addr+=u16_nb_sector_trans;
02364             g_segment_src.u16_size -=u16_nb_sector_trans;
02365          }
02366       }
02367    }
02368 
02369    // Check end of copy
02370    if( COPY_BUSY != status_copy )
02371    {
02372       U32 u32_size_exact;
02373 
02374       // Stop copy
02375       stream_stop( g_id_trans_memtomem );
02376       g_id_trans_memtomem = ID_STREAM_ERR;
02377 
02378       // Get exact size and close the source file
02379       nav_select( FS_NAV_ID_COPYFILE );
02380       u32_size_exact = nav_file_lgt();
02381       file_close();
02382       nav_select( nav_id_save );
02383 
02384       // If no error then set the exact size on the destination file
02385       if( COPY_FINISH == status_copy )
02386       {
02387          if( !file_seek( u32_size_exact , FS_SEEK_SET ))
02388          {
02389             status_copy = COPY_FAIL;
02390          }else{
02391             if( !file_set_eof() )
02392             {
02393                status_copy = COPY_FAIL;
02394             }
02395          }
02396       }
02397       file_close();
02398       // If error then delete the destination file
02399       if( COPY_FAIL == status_copy )
02400       {
02401          nav_file_del( TRUE );
02402       }
02403    }
02404    return status_copy;
02405 }
02406 #endif  // FS_LEVEL_FEATURES

Generated on Fri May 15 15:41:36 2009 for ATMEL by  doxygen 1.5.3