navigation.c

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

Generated on Wed Sep 23 09:17:02 2009 for ATMEL by  doxygen 1.5.3