//! @brief This function mount a drive //! void ushell_cmd_mount( void ) { uint8_t u8_drive_lun; Fs_index sav_index; if( g_s_arg[0][0] == 0 ) return; // Compute the logical unit number of drive u8_drive_lun=g_s_arg[0][0]-'a'; // Check lun number if( u8_drive_lun >= nav_drive_nb() ) { fputs(MSG_ER_DRIVE, stdout); return; } // Mount drive sav_index = nav_getindex(); // Save previous position if( nav_drive_set(u8_drive_lun)) { if( nav_partition_mount() ) return; // Here, drive mounted } fputs(MSG_ER_MOUNT, stdout); nav_gotoindex(&sav_index); // Restore previous position }
//! @brief This function delete a file or directory //! void ushell_cmd_rm( void ) { uint8_t u8_i = 0; Fs_index sav_index; if( g_s_arg[0][0] == 0 ) return; // Save the position sav_index = nav_getindex(); while( 1 ) { // Restore the position nav_gotoindex(&sav_index); // Select file or directory if( !nav_setcwd( (FS_STRING)g_s_arg[0], true, false ) ) break; // Delete file or directory if( !nav_file_del( false ) ) { fputs(MSG_KO, stdout); break; } u8_i++; } printf( "%u file(s) deleted\n\r", u8_i ); }
//! @brief This function displays the free space of each drive present //! void ushell_cmd_free_space( void ) { uint8_t u8_tmp; Fs_index sav_index = nav_getindex(); // Save current position for( u8_tmp=0; u8_tmp<nav_drive_nb(); u8_tmp++ ) { nav_drive_set( u8_tmp ); // Select drive if( !nav_partition_mount() ) // Mount drive continue; // Display drive letter name (a, b...) printf("%c: %s\r\n", 'a'+u8_tmp, mem_name(u8_tmp) ); if( g_s_arg[0][0]=='l' ) // Choose command option { // Long and exact function printf("Free space: %llu Bytes / %llu Bytes\n\r", (uint64_t)(nav_partition_freespace() << FS_SHIFT_B_TO_SECTOR), (uint64_t)(nav_partition_space() << FS_SHIFT_B_TO_SECTOR)); } else { // Otherwise use fast command printf("Free space: %u %%\n\r", nav_partition_freespace_percent() ); } } nav_gotoindex(&sav_index); // Restore position }
bool pl_main_save( void ) { _MEM_TYPE_SLOW_ Fs_index index; uint8_t nav_id_save; uint16_t u16_pos; // Check if the play list file is opened and modified if( !pl_main_isopen() ) return false; if( !pl_g_list_is_modify ) return true; pl_g_list_is_modify = false; // Check if a undo file exists if( !pl_g_list_undo ) return true; // Remove original copy of play list file nav_id_save = nav_get(); nav_select( FS_NAV_ID_PLAYLIST ); u16_pos = pl_g_u16_list_sel; // Save position in play list file_close(); // Close list index = nav_getindex(); // Save the pointer on play list file pl_g_list_is_open = false; if( nav_gotoindex( ©file_index ) ) // Go to the copy of file nav_file_del( true ); // Remove the copy nav_gotoindex( &index ); // Re select play list file pl_main_open( true ); // Re open play list file pl_nav_setpos(u16_pos); // Restore position in play list nav_select( nav_id_save ); return true; }
//! This function closes the play list and selects this one in current navigator //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! bool pl_main_close( void ) { _MEM_TYPE_SLOW_ Fs_index index; uint8_t nav_id_save; if( !pl_main_isopen() ) return false; // Close play list nav_id_save = nav_get(); nav_select( FS_NAV_ID_PLAYLIST ); file_close(); #if( PL_READONLY == false ) if( pl_g_list_is_modify ) { if( pl_g_list_undo ) { uint16_t size_name; FS_STRING sz_name; //** Play list modified but not saved, then restore previous list // Get name of play list nav_string_length_enable(); nav_file_name( (FS_STRING)&size_name, 1, FS_NAME_GET, false ); nav_string_length_disable(); sz_name = PLAYLIST_BUF_ALLOC( size_name* (Is_unicode? 2 : 1 ) ); if( NULL != sz_name ) { if( nav_file_name( sz_name, size_name, FS_NAME_GET, false ) ) { // Delete current play list if( nav_file_del( true ) ) // Remove copy file { nav_gotoindex( ©file_index ); // Select copy play list nav_file_rename( sz_name ); // rename copy play list } } PLAYLIST_BUF_FREE( sz_name ); } } } #endif // Select the play list file in current navigator index = nav_getindex(); // Save a pointer on play list file nav_select( nav_id_save ); nav_gotoindex( &index ); pl_g_list_is_open = false; return true; }
//! This function goes to the parent directory //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! //! @verbatim //! After the selected file is the first entry of the new file list FLAT //! @endverbatim //! bool nav_flat_gotoparent( void ) { _MEM_TYPE_SLOW_ Fs_index index; index = nav_getindex(); while( 0 != fs_g_nav.u8_flat_dir_level ) { fs_g_nav.u8_flat_dir_level--; nav_dir_gotoparent(); } if( !nav_dir_gotoparent() ) { nav_gotoindex( &index ); return false; } // Go to at the beginning of FLAT list fs_g_nav.u8_flat_dir_level = 0; fs_g_nav.u16_flat_pos_offset = 0; nav_filelist_reset(); nav_flat_next(); return true; }
//! //! @brief Synchronize the contents of two drives (limited to files). //! //! @param sync_direction uint8_t: DEVICE_TO_HOST, HOST_TO_DEVICE or FULL_SYNC //! //! @return bool: true on success //! //! @todo Do recursive directory copy... //! bool host_mass_storage_task_sync_drives(uint8_t sync_direction) { Fs_index local_index; Fs_index sav_local_index; Fs_index usb_index; Fs_index sav_usb_index; // First, check the host controller is in full operating mode with the // B-device attached and enumerated if (!Is_host_ready()) return false; nav_reset(); // Try to mount local drive nav_drive_set(LUN_ID_AT45DBX_MEM); if (!nav_partition_mount()) return false; local_index = nav_getindex(); sav_local_index = nav_getindex(); // Try to mount first USB device drive nav_drive_set(LUN_ID_MEM_USB); if (!nav_partition_mount()) return false; usb_index = nav_getindex(); sav_usb_index = nav_getindex(); // First synchronization: USB/OUT -> Local/IN if (sync_direction & DEVICE_TO_HOST) { if (!host_mass_storage_task_sync_dir(&local_index, DIR_LOCAL_IN_NAME, &usb_index, DIR_USB_OUT_NAME)) return false; } // Restore positions nav_gotoindex(&sav_local_index); local_index = nav_getindex(); nav_gotoindex(&sav_usb_index); usb_index = nav_getindex(); nav_gotoindex(&local_index); // Second synchronization: Local/OUT -> USB/IN if (sync_direction & HOST_TO_DEVICE) { if (!host_mass_storage_task_sync_dir(&usb_index, DIR_USB_IN_NAME, &local_index, DIR_LOCAL_OUT_NAME)) return false; } return true; }
//! @brief This function initializes the hardware/software resources required for ushell task. //! void ushell_task_init(uint32_t pba_hz) { uint8_t u8_i; //** Initialize the USART used by uShell with the configured parameters static const gpio_map_t SHL_USART_GPIO_MAP = { {SHL_USART_RX_PIN, SHL_USART_RX_FUNCTION}, {SHL_USART_TX_PIN, SHL_USART_TX_FUNCTION} }; #if (defined __GNUC__) set_usart_base((void *)SHL_USART); gpio_enable_module(SHL_USART_GPIO_MAP, sizeof(SHL_USART_GPIO_MAP) / sizeof(SHL_USART_GPIO_MAP[0])); usart_init(SHL_USART_BAUDRATE); #elif (defined __ICCAVR32__) static const usart_options_t SHL_USART_OPTIONS = { .baudrate = SHL_USART_BAUDRATE, .charlength = 8, .paritytype = USART_NO_PARITY, .stopbits = USART_1_STOPBIT, .channelmode = USART_NORMAL_CHMODE }; extern volatile avr32_usart_t *volatile stdio_usart_base; stdio_usart_base = SHL_USART; gpio_enable_module(SHL_USART_GPIO_MAP, sizeof(SHL_USART_GPIO_MAP) / sizeof(SHL_USART_GPIO_MAP[0])); usart_init_rs232(SHL_USART, &SHL_USART_OPTIONS, pba_hz); #endif //** Configure standard I/O streams as unbuffered. #if (defined __GNUC__) setbuf(stdin, NULL); #endif setbuf(stdout, NULL); // Set default state of ushell g_b_ushell_task_run = false; for( u8_i=0; u8_i<USHELL_HISTORY; u8_i++ ) { g_s_cmd_his[u8_i][0] = 0; // Set end of line for all cmd line history } fputs(MSG_EXIT, stdout ); g_u32_ushell_pba_hz = pba_hz; // Save value to manage a time counter during perform command #ifdef FREERTOS_USED xTaskCreate(ushell_task, configTSK_USHELL_NAME, configTSK_USHELL_STACK_SIZE, NULL, configTSK_USHELL_PRIORITY, NULL); #endif // FREERTOS_USED } #ifdef FREERTOS_USED /*! \brief Entry point of the explorer task management. * * This function performs uShell decoding to access file-system functions. * * \param pvParameters Unused. */ void ushell_task(void *pvParameters) #else /*! \brief Entry point of the explorer task management. * * This function performs uShell decoding to access file-system functions. */ void ushell_task(void) #endif { #ifdef FREERTOS_USED //** Inifinite loop for RTOS because it is a RTOS task portTickType xLastWakeTime; xLastWakeTime = xTaskGetTickCount(); while (true) { vTaskDelayUntil(&xLastWakeTime, configTSK_USHELL_PERIOD); #else //** No loop with the basic scheduler { #endif // FREERTOS_USED //** Check the USB mode and authorize/unauthorize ushell if(!g_b_ushell_task_run) { if( Is_usb_id_device() ) #ifdef FREERTOS_USED continue; // Continue in the RTOS task #else return; // Exit of the task scheduled #endif g_b_ushell_task_run = true; // Display shell startup fputs(MSG_WELCOME, stdout); ushell_cmd_nb_drive(); fputs(MSG_PROMPT, stdout); // Reset the embedded FS on ushell navigator and on first drive nav_reset(); nav_select( FS_NAV_ID_USHELL_CMD ); nav_drive_set( 0 ); }else{ if( Is_usb_id_device() ) { g_b_ushell_task_run = false; fputs(MSG_EXIT, stdout ); nav_exit(); #ifdef FREERTOS_USED continue; // Continue in the RTOS task #else return; // Exit of the task scheduled #endif } } //** Scan shell command if( !ushell_cmd_scan() ) #ifdef FREERTOS_USED continue; // Continue in the RTOS task #else return; // Exit of the task scheduled #endif //** Command ready then decode and execute this one switch( ushell_cmd_decode() ) { // Displays number of drives case CMD_NB_DRIVE: ushell_cmd_nb_drive(); break; // Displays free space information for all connected drives case CMD_DF: ushell_cmd_free_space(); break; // Formats disk case CMD_FORMAT: ushell_cmd_format(); break; // Mounts a drive (e.g. "b:") case CMD_MOUNT: ushell_cmd_mount(); break; // Displays the space information for current drive case CMD_SPACE: ushell_cmd_space(); break; // Lists the files present in current directory (e.g. "ls") case CMD_LS: ushell_cmd_ls(false); break; case CMD_LS_MORE: ushell_cmd_ls(true); break; // Enters in a directory (e.g. "cd folder_toto") case CMD_CD: ushell_cmd_cd(); break; // Enters in parent directory ("cd..") case CMD_UP: ushell_cmd_gotoparent(); break; // Displays a text file case CMD_CAT: ushell_cmd_cat(false); break; case CMD_CAT_MORE: ushell_cmd_cat(true); break; // Displays the help case CMD_HELP: ushell_cmd_help(); break; // Creates directory case CMD_MKDIR: ushell_cmd_mkdir(); break; // Creates file case CMD_TOUCH: ushell_cmd_touch(); break; // Deletes files or directories case CMD_RM: ushell_cmd_rm(); break; // Appends char to selected file case CMD_APPEND: ushell_cmd_append_file(); break; // Index routines (= specific shortcut from ATMEL FileSystem) case CMD_SET_ID: g_mark_index = nav_getindex(); break; case CMD_GOTO_ID: nav_gotoindex( &g_mark_index ); break; // Copies file to other location case CMD_CP: ushell_cmd_copy(); break; // Renames file case CMD_MV: ushell_cmd_rename(); break; // Synchronize folders case CMD_SYNC: ushell_cmd_sync(); break; case CMD_PERFORM: ushell_cmd_perform(); break; // USB commands #if USB_HOST_FEATURE == true case CMD_LS_USB: ushell_cmdusb_ls(); break; case CMD_USB_SUSPEND: ushell_cmdusb_suspend(); break; case CMD_USB_RESUME: ushell_cmdusb_resume(); break; #endif case CMD_NONE: break; // Unknown command default: fputs(MSG_ER_CMD_NOT_FOUND, stdout); break; } fputs(MSG_PROMPT, stdout); } } //! @brief Get the full command line to be interpreted. //! //! @return true, if a command is ready //! bool ushell_cmd_scan(void) { int c_key; // Something new of the UART ? if (usart_read_char(SHL_USART, &c_key) != USART_SUCCESS) { usart_reset_status(SHL_USART); return false; } if( 0 != g_u8_escape_sequence ) { //** Decode escape sequence if( 1 == g_u8_escape_sequence ) { if( 0x5B != c_key ) { g_u8_escape_sequence=0; return false; // Escape sequence cancel } g_u8_escape_sequence=2; } else { // Decode value of the sequence switch (c_key) { /* Note: OVERRUN error on USART with an RTOS and USART without interrupt management If you want support "Escape sequence", then you have to implement USART interrupt management case 0x41: // UP command ushell_clean_cmd_line(); ushell_history_up(); ushell_history_display(); break; case 0x42: // DOWN command ushell_clean_cmd_line(); ushell_history_down(); ushell_history_display(); break; */ default: // Ignore other command break; } g_u8_escape_sequence=0; // End of Escape sequence } return false; } //** Normal sequence switch (c_key) { //** Command validation case ASCII_CR: putchar(ASCII_CR); // Echo putchar(ASCII_LF); // Add new line flag g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size]=0; // Add NULL terminator at the end of command line return true; //** Enter in escape sequence case ASCII_ESCAPE: g_u8_escape_sequence=1; break; //** backspace case ASCII_BKSPACE: if(g_u8_cmd_size>0) // Beginning of line ? { // Remove the last character on terminal putchar(ASCII_BKSPACE); // Send a backspace to go in previous character putchar(' '); // Send a space to erase previous character putchar(ASCII_BKSPACE); // Send a backspace to go in new end position (=previous character position) // Remove the last character on cmd line buffer g_u8_cmd_size--; } break; // History management case '!': ushell_clean_cmd_line(); ushell_history_up(); ushell_history_display(); break; case '$': ushell_clean_cmd_line(); ushell_history_down(); ushell_history_display(); break; //** Other char default: if( (0x1F<c_key) && (c_key<0x7F) && (USHELL_SIZE_CMD_LINE!=g_u8_cmd_size) ) { // Accept char putchar(c_key); // Echo g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size++] = c_key; // append to cmd line } break; } return false; }
//! @brief Perform transfer between two devices //! void ushell_cmd_perform( void ) { Fs_index sav_index; Fs_file_segment seg1, seg2; if( g_s_arg[0][0] == 0 ) return; sav_index = nav_getindex(); // Save the position // Alloc a file on each devices printf("Alloc a file on each devices\n\r"); seg1 = ushell_cmd_perform_alloc( (g_s_arg[0][0]-'a') , FILE_ALLOC_SIZE ); if( seg1.u16_size == 0 ) { printf("!!!Error allocation on device 1\n\r"); // Restore the position nav_gotoindex(&sav_index); return; } if( g_s_arg[1][0] != 0 ) { nav_select( FS_NAV_ID_COPYFILE ); seg2 = ushell_cmd_perform_alloc( (g_s_arg[1][0]-'a') , FILE_ALLOC_SIZE ); if( seg2.u16_size == 0 ) { nav_select( FS_NAV_ID_USHELL_CMD ); file_close(); nav_file_del(false); printf("!!!Error allocation on device 2\n\r"); // Restore the position nav_gotoindex(&sav_index); return; } // Transfer data from device 1 to device 2 printf("Transfer data from device 1 to device 2\r\n"); ushell_cmd_perform_transfer(seg1,seg2); printf("Transfer data from device 2 to device 1\r\n"); ushell_cmd_perform_transfer(seg2,seg1); // Delete files allocated nav_select( FS_NAV_ID_COPYFILE ); file_close(); nav_file_del(false); nav_select( FS_NAV_ID_USHELL_CMD ); } else { ushell_cmd_perform_access( false, seg1 ); ushell_cmd_perform_access( true, seg1 ); if( LUN_ID_USB <= nav_drive_get() ) { printf("Transfer large buffer on USB\r\n"); ushell_cmd_perform_extaccess( false, seg1 ); ushell_cmd_perform_extaccess( true, seg1 ); } } file_close(); nav_file_del(false); // Restore the position nav_gotoindex(&sav_index); printf("End of test\n\r"); return; }
//! @brief Synchronize a path with an other path //! //! @return true if success //! bool ushell_cmd_sync( void ) { Fs_index sav_index; uint8_t u8_folder_level = 0; if( g_s_arg[0][0] == 0 ) return false; if( g_s_arg[1][0] == 0 ) return false; // Add '\' at the end of path, else the nav_setcwd select the directory but don't enter into. ushell_path_valid_syntac( g_s_arg[0] ); ushell_path_valid_syntac( g_s_arg[1] ); printf("Synchronize folders:\n\r"); sav_index = nav_getindex(); // Save the position // Select source directory in COPYFILE navigator handle nav_select( FS_NAV_ID_COPYFILE ); printf("Select source directory\n\r"); if( !nav_setcwd( (FS_STRING)g_s_arg[0], true, false ) ) goto ushell_cmd_sync_error; nav_filelist_reset(); // Select destination directory in USHELL navigator handle nav_select( FS_NAV_ID_USHELL_CMD ); printf("Select destination directory\n\r"); if( !nav_setcwd( (FS_STRING)g_s_arg[1], true, true ) ) goto ushell_cmd_sync_error; nav_filelist_reset(); // loop to scan and create ALL folders and files while(1) { while(1) { // Loop to Search files or directories // Reselect Source nav_select( FS_NAV_ID_COPYFILE ); if( nav_filelist_set( 0 , FS_FIND_NEXT ) ) break; // a next file and directory is found // No other dir or file in current dir then go to parent dir on Source and Destination disk if( 0 == u8_folder_level ) { // end of update folder //********* END OF COPY ************** goto ushell_cmd_sync_finish; } printf("Go to parent\n\r"); // Remark, nav_dir_gotoparent() routine go to in parent dir and select the children dir in list u8_folder_level--; if( !nav_dir_gotoparent() ) goto ushell_cmd_sync_error; // Select Destination navigator and go to the same dir of Source nav_select( FS_NAV_ID_USHELL_CMD ); if( !nav_dir_gotoparent() ) goto ushell_cmd_sync_error; } // end of while (1) if( nav_file_isdir()) { printf("Dir found - create dir: "); //** here, a new directory is found and is selected // Get name of current selection (= dir name on Source) if( !nav_file_name( (FS_STRING)g_s_arg[0], USHELL_SIZE_CMD_LINE, FS_NAME_GET, false )) goto ushell_cmd_sync_error; // Enter in dir (on Source) if( !nav_dir_cd()) goto ushell_cmd_sync_error; u8_folder_level++; // Select Destination disk nav_select( FS_NAV_ID_USHELL_CMD ); // Create folder in Destination disk printf((char*)g_s_arg[0]); printf("\n\r"); if( !nav_dir_make( (FS_STRING )g_s_arg[0] )) { if( FS_ERR_FILE_EXIST != fs_g_status ) goto ushell_cmd_sync_error; // here, error the name exist } // Here the navigator have selected the folder on Destination if( !nav_dir_cd()) { if( FS_ERR_NO_DIR == fs_g_status ) { // FYC -> Copy impossible, because a file have the same name of folder } goto ushell_cmd_sync_error; } // here, the folder is created and the navigator is entered in this dir } else { printf("File found - copy file: "); //** here, a new file is found and is selected // Get name of current selection (= file name on Source) if( !nav_file_name( (FS_STRING)g_s_arg[0], USHELL_SIZE_CMD_LINE, FS_NAME_GET, false )) goto ushell_cmd_sync_error; printf((char*)g_s_arg[0]); printf("\n\r"); if( !nav_file_copy()) goto ushell_cmd_sync_error; // Paste file in current dir of Destination disk nav_select( FS_NAV_ID_USHELL_CMD ); while( !nav_file_paste_start( (FS_STRING)g_s_arg[0] ) ) { // Error if( fs_g_status != FS_ERR_FILE_EXIST ) goto ushell_cmd_sync_error; // File exists then deletes this one printf("File exists then deletes this one.\n\r"); if( !nav_file_del( true ) ) goto ushell_cmd_sync_error; // here, retry PASTE } // Copy running { uint8_t status; do{ status = nav_file_paste_state(false); }while( COPY_BUSY == status ); if( COPY_FINISH != status ) goto ushell_cmd_sync_error; } } // if dir OR file } // end of first while(1) ushell_cmd_sync_error: // Restore the position nav_select( FS_NAV_ID_USHELL_CMD ); nav_gotoindex(&sav_index); printf("!!!Copy fail\n\r"); return false; ushell_cmd_sync_finish: // Restore the position nav_select( FS_NAV_ID_USHELL_CMD ); nav_gotoindex(&sav_index); printf("End of copy\n\r"); return true; }
//! @brief This function copies a file to other location //! void ushell_cmd_copy( void ) { Fs_index sav_index; uint8_t u8_status_copy; if( g_s_arg[0][0] == 0 ) return; // Save the position sav_index = nav_getindex(); // Select source file if( !nav_setcwd( (FS_STRING)g_s_arg[0], true, false ) ) { fputs(MSG_ER_UNKNOWN_FILE, stdout); return; } // Get name of source to be used as same destination name nav_file_name( (FS_STRING)g_s_arg[0], MAX_FILE_PATH_LENGTH, FS_NAME_GET, true ); // Mark this selected file like source file if( !nav_file_copy()) { fputs(MSG_KO, stdout); goto cp_end; } // Select destination if( g_s_arg[1][0]==0 ) { // g_s_arg[1] is NULL, using mark if( !nav_gotoindex(&g_mark_index) ) goto cp_end; } else { // g_s_arg[1] exists, then go to this destination if( !nav_setcwd( (FS_STRING)g_s_arg[1], true, false ) ) { fputs(MSG_ER_UNKNOWN_FILE, stdout); goto cp_end; } } // Set the name destination and start paste if( !nav_file_paste_start((FS_STRING)g_s_arg[0]) ) { fputs(MSG_ER_PASTE, stdout); goto cp_end; } // Performs copy do { u8_status_copy = nav_file_paste_state( false ); }while( u8_status_copy == COPY_BUSY ); // Check status of copy action if( u8_status_copy == COPY_FAIL ) { fputs(MSG_ER_PASTE, stdout); goto cp_end; } cp_end: // Restore the position nav_gotoindex(&sav_index); }
//! This function opens a file list at the current position in navigator //! //! @param b_playlist if true then the current selected file is a play list file to open //! else create a file list with files included in a disk part //! @param pos If b_playlist true, then position in the play list to start //! else folder level of the current position //! //! @return false, in case of error or file list empty //! bool navauto_open( bool b_playlist , uint16_t pos ) { Navauto_mov_state state; g_navauto_b_playlist = b_playlist; g_navauto_u16_dir_level_root = 0; g_navauto_u16_nb = 0; if( b_playlist ) { g_navauto_u16_pos = pos; if( !pl_main_open(false) ) return false; g_navauto_u16_nb = pl_nav_getnbfile(); if( 0 == g_navauto_u16_nb ) return false; if( NAVAUTO_RAND_OFF == navauto_getrand() ) { if( pl_nav_setpos( g_navauto_u16_pos )) { if( nav_filelist_validpos() ) return true; } }else{ navauto_rand_init(); } // Error position then restart at the beginning g_navauto_u16_pos = 0; } else { #if( FS_NAV_AUTOMATIC_NBFILE == ENABLE ) Fs_index index; Fs_index index2; Navauto_rand rand_mode; uint16_t u16_current_pos=0; index.u8_lun = 0xFF; // Reset index (by default no valid selected file) g_navauto_u16_dir_level = pos; rand_mode = navauto_getrand(); // Save random mode navauto_setrand( NAVAUTO_RAND_OFF ); // If no valid file then found the first valid file if( !nav_file_checkext( g_navauto_filter )) { // Go to previous position because "navauto_mov_explorer()" execute a next before search valid file if( !nav_filelist_set( 0 , FS_FIND_PREV ) ) nav_filelist_reset(); state = navauto_mov_explorer(FS_FIND_NEXT, NAVAUTO_MOV_OPTS_NONE); if((NAVAUTO_MOV_OK_LOOP != state.status) && (NAVAUTO_MOV_OK != state.status) ) { navauto_setrand(rand_mode); return false; // List empty } } index = nav_getindex(); // Compute the size of file list and search the position of selected file navauto_mov_explorer_reset(); // Go to beginning of loop // Note: the number of file is updated in navauto_mov_explorer() routine when the end of list is detected while( navauto_mov_explorer( FS_FIND_NEXT, NAVAUTO_MOV_OPTS_NONE ).status == NAVAUTO_MOV_OK ) { index2 = nav_getindex(); // Check the current position with the selected file if( (index.u8_lun == index2.u8_lun) && (index.u32_cluster_sel_dir == index2.u32_cluster_sel_dir) && (index.u16_entry_pos_sel_file == index2.u16_entry_pos_sel_file) ) { u16_current_pos = g_navauto_u16_pos; // Save the position number found g_navauto_u16_dir_level_root = g_navauto_u16_dir_level; } } navauto_setrand(rand_mode); // Restore random mode if( 0 == g_navauto_u16_nb ) return false; // loop empty // Go to a file from file list if( NAVAUTO_RAND_OFF == navauto_getrand() ) { if( 0xFF != index.u8_lun ) { // Reselect the file selected at startup nav_gotoindex( &index ); // Go to this one g_navauto_u16_dir_level = g_navauto_u16_dir_level_root; // Update position file g_navauto_u16_pos = u16_current_pos; // Update folder level corresponding at file } // Else, the first file is already selected at the end of "compute file list size" loop return true; }else{ navauto_rand_init(); } #else Fs_index index; Navauto_rand rand_mode; rand_mode = navauto_getrand(); navauto_setrand(NAVAUTO_RAND_OFF); // If no valid file then find the first valid file if( !nav_file_checkext( g_navauto_filter )) { // Go to previous position because "navauto_mov_explorer()" execute a next before search valid file if( !nav_filelist_set( 0 , FS_FIND_PREV ) ) nav_filelist_reset(); state = navauto_mov_explorer(FS_FIND_NEXT, NAVAUTO_MOV_OPTS_NONE); if((NAVAUTO_MOV_OK_LOOP != state.status) && (NAVAUTO_MOV_OK != state.status) ) { navauto_setrand(rand_mode); return false; // List empty } } index = nav_getindex(); navauto_setrand(rand_mode); navauto_mov_explorer_reset(); // Compute directory level g_navauto_u16_dir_level = 0; while(nav_dir_gotoparent()) g_navauto_u16_dir_level++; g_navauto_u16_dir_level_root = g_navauto_u16_dir_level; //g_navauto_u16_dir_level = pos; // Restore index nav_gotoindex(&index); g_navauto_u16_nb = 0xFFFF; if( NAVAUTO_RAND_OFF == navauto_getrand() ) navauto_rand_init(); if( nav_file_checkext( g_navauto_filter )) { // Valid file then update position with the first position but it is not the first ! g_navauto_u16_pos = 1; return true; } #endif } // Find first file or use the random feature state = navauto_mov(FS_FIND_NEXT, NAVAUTO_MOV_OPTS_NONE); if((NAVAUTO_MOV_OK_LOOP != state.status) && (NAVAUTO_MOV_OK != state.status) ) return false; // List empty return true; }
//! This function creates a copy of the play list in case of a restore action //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! bool pl_main_modify( void ) { _MEM_TYPE_SLOW_ uint8_t name_copyfile[]="~copy.m3u"; _MEM_TYPE_SLOW_ Fs_index index; uint8_t nav_id_save; uint16_t u16_pos; uint8_t status; bool b_copy_finish = false; if( !pl_main_isopen() ) return false; if( pl_g_list_is_modify ) return true; // If an error occurs during copy process then the play list file is set in read only mode fs_g_status = FS_ERR_PL_READ_ONLY; if( pl_g_list_is_readonly ) return false; if( !pl_g_list_undo ) { pl_g_list_is_modify = true; return true; } // Save information about current play list file nav_id_save = nav_get(); nav_select( FS_NAV_ID_PLAYLIST ); u16_pos = pl_g_u16_list_sel; // Save position in play list file_close(); // Close list pl_g_list_is_open = false; index = nav_getindex(); // Get pointer on play list // Copy play list file in a temporary file #if( (FS_ASCII == true) && (FS_UNICODE == true) ) nav_string_ascii(); // copy file name stored in ASCII #endif if( !nav_file_copy()) goto pl_main_modify_end; if( !nav_file_paste_start( name_copyfile ) ) { if( FS_ERR_FILE_EXIST != fs_g_status) goto pl_main_modify_end; // File exist then delete if( !nav_file_del(true) ) goto pl_main_modify_end; // Retry paste if( !nav_file_paste_start( name_copyfile ) ) goto pl_main_modify_end; } // Run paste do{ status = nav_file_paste_state(false); // Copy running }while( COPY_BUSY == status ); if( COPY_FINISH != status ) goto pl_main_modify_end; // Save pointer on copy file copyfile_index = nav_getindex(); b_copy_finish = true; pl_main_modify_end: // Restore the play list file #if( (FS_ASCII == true) && (FS_UNICODE == true) ) nav_string_unicode(); #endif nav_gotoindex( &index ); // Go to original play list file pl_main_open( true ); // Re open play list file pl_g_list_is_modify = b_copy_finish; nav_select( nav_id_save ); pl_nav_setpos(u16_pos); // Restore position in play list return pl_g_list_is_modify; }
//! //! @brief Synchronize the contents of two directories (limited to files). //! //! @param dst_fs_idx Fs_index *: File system index for destination navigation path //! @param dst_dir const char *: Pointer to destination directory name //! @param src_fs_idx Fs_index *: File system index for source navigation path //! @param src_dir const char *: Pointer to source directory name //! //! @return bool: true on success //! //! @todo Do recursive directory copy... //! bool host_mass_storage_task_sync_dir(Fs_index *dst_fs_idx, const char *dst_dir, Fs_index *src_fs_idx, const char *src_dir) { uint8_t nb_file; uint8_t i; uint32_t free_space; uint16_t file_size; // First, check the host controller is in full operating mode with the // B-device attached and enumerated if (!Is_host_ready()) return false; // Go to source navigation nav_gotoindex(src_fs_idx); if (!goto_code_name(src_dir)) return false; // Check that source directory exists nav_dir_cd(); // Source directory exists, so go to it *src_fs_idx = nav_getindex(); // Save navigation position nav_filelist_first(FS_FILE); // Go to first file nb_file = nav_filelist_nb(FS_FILE); // Get the number of files in this directory // Go to destination navigation nav_gotoindex(dst_fs_idx); if (!goto_code_name(dst_dir)) // Destination directory does not exist, so create it { str_code_to_unicode_ram(dst_dir, ms_str_unicode); nav_dir_make(ms_str_unicode); if (!goto_code_name(dst_dir)) return false; // Check that destination directory has been created } nav_dir_cd(); *dst_fs_idx = nav_getindex(); // Get available free space free_space = nav_partition_space(); nav_gotoindex(src_fs_idx); nav_filelist_first(FS_FILE); // For all files in directory for (i = 0; i < nb_file; i++) { // Get source name to be used as destination name nav_file_name(ms_str_unicode, MAX_FILE_PATH_LENGTH, FS_NAME_GET); file_size = nav_file_lgtsector(); // Get file size if (file_size > free_space) return false; // Check that there is enough free space left // Update free space (to save time, do no call nav_partition_space() again) free_space -= file_size; // Mark source nav_file_copy(); // Save current source position *src_fs_idx = nav_getindex(); // Go to destination navigation nav_gotoindex(dst_fs_idx); if (goto_unicode_name(ms_str_unicode)) // If file already exists { nav_file_del(); // Delete it } // Paste nav_file_paste_start(ms_str_unicode); // Restore previous navigation position nav_gotoindex(src_fs_idx); // Copy while (nav_file_paste_state(false) == COPY_BUSY); // Restore previous navigation position nav_gotoindex(src_fs_idx); nav_filelist_set(0, FS_FIND_NEXT); } return true; }