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 a position in the play list //! //! @param u16_position position in play list to go //! bool pl_nav_setpos( uint16_t u16_position ) { uint8_t nav_id_save; if( (0 == u16_position ) || (pl_g_u16_list_size < u16_position) ) { fs_g_status = FS_ERR_PL_OUT_LST; return false; } if( pl_g_u16_list_sel == u16_position ) return true; // Reset previous selection nav_filelist_reset(); // Go to play list file navigator nav_id_save = nav_get(); nav_select( FS_NAV_ID_PLAYLIST ); if( pl_g_u16_list_sel > u16_position ) { // Go to at the beginning of text file reader_txt_beg(); pl_g_u16_list_sel = 0; } while( pl_g_u16_list_sel != u16_position ) { FS_STRING sz_path; bool next_pos = false; if( 0 != file_eof() ) { nav_select( nav_id_save ); // Re select the previous navigator return false; } if (pl_g_u16_list_sel+1 == u16_position) { next_pos = pl_main_readline(PL_MAIN_READLINE_OPT_GOTOPATH, nav_id_save, &sz_path, NULL); if (sz_path) PLAYLIST_BUF_FREE(sz_path); } else next_pos = pl_main_readline(PL_MAIN_READLINE_OPT_CHECKLINE, 0, NULL, NULL); if (next_pos) pl_g_u16_list_sel++; // Add a file } nav_select( nav_id_save ); // Re select the previous navigator return true; }
static void nav_reload_current(navigator_t *nav) { nav_page_t *np; if((np = nav->nav_page_current) == NULL) return; plugins_reload_dev_plugin(); TRACE(TRACE_INFO, "navigator", "Reloading %s", np->np_url); prop_unsubscribe(np->np_close_sub); prop_unsubscribe(np->np_direct_close_sub); prop_destroy(np->np_prop_root); nav_page_setup_prop(nav, np, NULL); if(prop_set_parent(np->np_prop_root, nav->nav_prop_pages)) { /* nav->nav_prop_pages is a zombie, this is an error */ abort(); } nav_select(nav, np, NULL); if(backend_open(np->np_prop_root, np->np_url)) nav_open_errorf(np->np_prop_root, _("No handler for URL")); }
/*! * \brief Is a directory present? * * \param pcStringDirName Input. Directory name string. * * \return 1 if the directory exists, 0 if the directory doesn't exist, else -1 */ int8_t fsaccess_IsDirPresent( const char *pcStringDirName ) { signed short TempoNavId; int8_t RetVal; fsaccess_take_mutex(); // Take the mutex on the file system access. TempoNavId = fsaccess_alloc_nav_id(); // Get a navigator. if( -1 == TempoNavId ) // No navigator. { // give the mutex for nav access fsaccess_give_mutex(); return( -1 ); } // select the navigator nav_select( TempoNavId ); // Try to enter in the directory. RetVal = (int8_t)nav_setcwd( (FS_STRING)pcStringDirName, true, false ); fsaccess_free_nav_id( TempoNavId ); // mark NavId as free fsaccess_give_mutex(); // give the mutex for nav access return( RetVal ); }
int fb_iterator_init(Bool type){ file_or_dir = type; fb_iterator_reset(); // if no navigator available, return an error if ((iterator_navid = fsaccess_alloc_nav_id()) < 0) return ERROR_NO_NAV_ID; fsaccess_take_mutex(); // select the navigator nav_select( iterator_navid ); // navigate to folder if(nav_setcwd((FS_STRING)currentDirectory, FALSE, FALSE) == FALSE){ fsaccess_free_nav_id(iterator_navid); return ERROR_NOT_A_DIRECTORY; } //select top of list if(nav_filelist_first(type)==FALSE){ fsaccess_free_nav_id(iterator_navid); return ERROR_UNKNOWN; } nav_filelist_single_enable( type ); filecount = nav_filelist_nb(file_or_dir); return 0; }
static void nav_insert_page(navigator_t *nav, nav_page_t *np, prop_t *origin) { nav_page_t *np2; if(prop_set_parent(np->np_prop_root, nav->nav_prop_pages)) { /* nav->nav_prop_pages is a zombie, this is an error */ abort(); } if(np->np_inhistory == 0) { if(nav->nav_page_current != NULL) { /* Destroy any previous "future" histories, * this happens if we back a few times and then jumps away * in another "direction" */ while((np2 = TAILQ_NEXT(nav->nav_page_current, np_history_link)) != NULL) nav_close(np2, 1); } TAILQ_INSERT_TAIL(&nav->nav_history, np, np_history_link); np->np_inhistory = 1; } nav_select(nav, np, origin); }
//! //! This function reads from a file. //! //! @param fd file descriptor. //! @param buf pointer for data that are read. //! @param count amount of bytes to read //! //! @return ssize_t : amount of data read (-1 if error) //! ssize_t read(int fd, void *buf, size_t count) { ssize_t ReadCount = -1; if (fd < 0) { return (-1); } // take the mutex for nav access fsaccess_take_mutex(); nav_select( fd ); if ( file_eof() ) { // give the mutex for nav access fsaccess_give_mutex(); return(-1); } ReadCount = (ssize_t)file_read_buf((uint8_t *)buf , (uint16_t)count); // give the mutex for nav access fsaccess_give_mutex(); return(ReadCount); }
//! This function removes all files in the list //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! bool pl_rem_sel_all( void ) { uint8_t nav_id_save; bool b_status; if( !pl_main_modify() ) return false; nav_id_save = nav_get(); nav_select( FS_NAV_ID_PLAYLIST ); // Go to beginning of file AND set eof to have a size = 0 file_seek( 0 , FS_SEEK_SET ); b_status = file_set_eof(); nav_select( nav_id_save ); return b_status; }
int fb_ls_ext(const char *ext){ int CurrentNavId = -1; // if no navigator available, return an error if ((CurrentNavId = fsaccess_alloc_nav_id()) < 0) return ERROR_NO_NAV_ID; // select the navigator nav_select( CurrentNavId ); // navigate to folder if(nav_setcwd((FS_STRING)currentDirectory, FALSE, FALSE) == FALSE){ fsaccess_free_nav_id(CurrentNavId); return ERROR_NOT_A_DIRECTORY; } if(nav_filelist_first(FS_FILE)==FALSE){ fsaccess_free_nav_id(CurrentNavId); return ERROR_UNKNOWN; } char filename[255]; if(nav_file_getname(filename,sizeof(filename))==FALSE){ fsaccess_free_nav_id(CurrentNavId); return ERROR_UNKNOWN; } seprintf("Contents of folder %s:\n\n",currentDirectory); nav_filelist_single_enable( FS_DIR ); int filecount = nav_filelist_nb(FS_DIR); short a; for(a=0; a < filecount; a++){ if(nav_filelist_goto(a)==FALSE)return ERROR_UNKNOWN; char filename[255]; if(nav_file_getname(filename,sizeof(filename))==FALSE){ fsaccess_free_nav_id(CurrentNavId); return ERROR_UNKNOWN; } seprintf("%d: %s\n",a,filename); } nav_filelist_single_enable( FS_FILE ); filecount = nav_filelist_nb(FS_FILE); for(a=0; a < filecount; a++){ if(nav_filelist_goto(a)==FALSE)return ERROR_UNKNOWN; if(!nav_file_checkext(ext))continue; char filename[255]; if(nav_file_getname(filename,sizeof(filename))==FALSE){ fsaccess_free_nav_id(CurrentNavId); return ERROR_UNKNOWN; } seprintf("%d: %s\n",a,filename); } fsaccess_free_nav_id(CurrentNavId); return 0; }
static void nav_fwd(navigator_t *nav) { nav_page_t *next, *np; np = nav->nav_page_current; if(np != NULL && (next = TAILQ_NEXT(np, np_history_link)) != NULL) nav_select(nav, next, NULL); }
//! This function removes the selected file in the list //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! bool pl_rem_sel( void ) { uint8_t nav_id_save; bool b_status = false; if( !pl_main_modify() ) return false; if( 0 == pl_g_u16_list_sel ) { fs_g_status = FS_ERR_PL_OUT_LST; return false; } nav_id_save = nav_get(); nav_select( FS_NAV_ID_PLAYLIST ); // Jump at the beginning of the current path #if( PL_UNICODE == true) file_string_unicode(); if( !file_seek( pl_g_u16_path_size*2 , FS_SEEK_CUR_RE )) goto pl_rem_sys_err; #else if( !file_seek( pl_g_u16_path_size , FS_SEEK_CUR_RE )) goto pl_rem_sys_err; #endif // Comment the line if( !file_putc('#')) goto pl_rem_sys_err; b_status = true; pl_g_u16_list_size--; pl_rem_sys_err: #if( PL_UNICODE == true) file_string_ascii(); #endif // Go to beginning of file AND no file selected file_seek( 0 , FS_SEEK_SET ); pl_g_u16_list_sel = 0; nav_select( nav_id_save ); return b_status; }
static void nav_back(navigator_t *nav) { nav_page_t *prev, *np = nav->nav_page_current; if(np != NULL && (prev = TAILQ_PREV(np, nav_page_queue, np_history_link)) != NULL) { nav_select(nav, prev, NULL); if(np->np_direct_close) nav_close(np, 1); } }
static void nav_page_close_set(void *opaque, int value) { nav_page_t *np = opaque, *np2; navigator_t *nav = np->np_nav; if(!value) return; if(nav->nav_page_current == np) { np2 = TAILQ_PREV(np, nav_page_queue, np_history_link); nav_select(nav, np2, NULL); } nav_close(np, 1); }
//! This function remove the dead file in the list //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! bool pl_rem_dead( void ) { uint8_t nav_id_save; pl_g_u16_list_sel = 0; nav_id_save = nav_get(); nav_select( FS_NAV_ID_PLAYLIST ); while( pl_g_u16_list_sel < pl_g_u16_list_size ) { if( nav_gotoindex( &pl_g_list[ pl_g_u16_list_sel ] )) { // the file is good -> go to next file in list pl_g_u16_list_sel++; continue; } // The file is dead -> remove this one pl_rem_sel(); } nav_select( nav_id_save ); pl_nav_setpos(0); }
//! //! This function returns the opened file size. //! //! @param fd file descriptor. //! //! @return size_t : size of the file pointed to by the descriptor //! size_t fsaccess_file_get_size(int fd) { size_t size; if (fd < 0) { return (0); } // take the mutex for nav access fsaccess_take_mutex(); // select the navigator nav_select( fd ); // get the file size size = nav_file_lgt(); // give the mutex for nav access fsaccess_give_mutex(); return (size); }
//! //! This function writes to a file. //! //! @param fd file descriptor. //! @param buf pointer from where data are written. //! @param count amount of bytes to write //! //! @return ssize_t : amount of data written (-1 if error) //! ssize_t write(int fd, const void *buf, size_t count) { ssize_t WriteCount = -1; if (fd < 0) { return (-1); } // take the mutex for nav access fsaccess_take_mutex(); nav_select( fd ); WriteCount = (ssize_t)file_write_buf((uint8_t *)buf , (uint16_t)count); // give the mutex for nav access fsaccess_give_mutex(); return(WriteCount); }
//! //! This function closes a file. //! //! @param fd file descriptor. //! //! @return int : -1 if error, 0 otherwise //! int close(int fd) { if (fd < 0) { return (-1); } // take the mutex for nav access fsaccess_take_mutex(); nav_select( fd ); file_close(); fsaccess_free_nav_id(fd); // give the mutex for nav access fsaccess_give_mutex(); return (0); }
//! This function reads and checks the next line //! //! @param opt PL_MAIN_READLINE_OPT_CHECKLINE to check the next line in the file.\n //! PL_MAIN_READLINE_OPT_READSTRING to read the string in the text file.\n //! PL_MAIN_READLINE_OPT_GOTOPATH to read, check and goto the path. //! @param id_nav ID navigator to update with the selected file (ignore if b_gotopatch == false) //! @param sz_path Address of the string returned. It is used only if PL_MAIN_READLINE_OPT_READSTRING or //! PL_MAIN_READLINE_OPT_GOTOPATH options are specified. //! @param u16_size_line The length of the path. If this parameter is NULL, then the length is not returned. //! //! @return true if a line with a correct path //! false line ignored or end of file //! bool pl_main_readline( readline_opt_t opt, uint8_t id_nav, FS_STRING *sz_path, uint16_t *u16_size_line ) { uint16_t line_beg[8]; // Contains first characters of the line uint32_t u32_file_pos; uint16_t u16_alt_length = 0; uint8_t u8_pos_path_in_line = 0; // Set output to NULL to specify if there is an error *sz_path = NULL; // Read the 3 first char in the line u32_file_pos = file_getpos(); if( E_PL_M3U == pl_g_list_type ) { // M3U path lines = "path\file" // M3U comment lines = "#..." u16_alt_length = reader_txt_get_line( true, (FS_STRING)line_beg, 2 ); if( (2 > u16_alt_length) // The line size is not correct || ('#' == line_beg[0]) ) // It is a comment line { return false; } u8_pos_path_in_line=0; } if( (E_PL_PLS == pl_g_list_type) || (E_PL_SMP == pl_g_list_type) ) { // PLS path lines = "Filexxx=path\file" // SMP path lines = "File=path\file" u16_alt_length = reader_txt_get_line( true, (FS_STRING)line_beg, 8 ); if(6 > u16_alt_length) // The line size can't contain a path line return false; // Check if it is a path line if( ('F' != line_beg[0]) || ('i' != line_beg[1]) || ('l' != line_beg[2]) || ('e' != line_beg[3]) ) { return false; } u8_pos_path_in_line=5; if('=' != line_beg[4]) { u8_pos_path_in_line++; if('=' != line_beg[5]) { u8_pos_path_in_line++; if('=' != line_beg[6]) { u8_pos_path_in_line++; if('=' != line_beg[7]) return false; } } } } // Here, the line contains a path // Store the length of the line if a buffer is set if (u16_size_line) *u16_size_line = u16_alt_length - u8_pos_path_in_line; if (opt == PL_MAIN_READLINE_OPT_CHECKLINE) return true; // else go to path // Read all characters in line file_seek( u32_file_pos, FS_SEEK_SET ); *sz_path = PLAYLIST_BUF_ALLOC( u16_alt_length * (Is_unicode? 2 : 1 ) ); if( NULL == *sz_path ) return false; // no enough memory, impossible to store the path but path present in line if( 0 == reader_txt_get_line( (FS_UNICODE==true), *sz_path, u16_alt_length ) ) return false; // Error during the read if( 0 != u8_pos_path_in_line ) { // Shift the path to the beginning of the buffer memmove(*sz_path, *sz_path + u8_pos_path_in_line * ((FS_UNICODE==true) ? 2 : 1), (u16_alt_length - u8_pos_path_in_line) * ((FS_UNICODE==true) ? 2 : 1)); } if (opt == PL_MAIN_READLINE_OPT_READSTRING) return true; // Update the navigator with the path of play list file, because the path is relative at this one nav_copy( id_nav ); nav_select( id_nav ); // Go to the path included in the line if( !nav_setcwd( (FS_STRING) *sz_path , false, false ) ) { // path no found then path is dead -> reset list to deselect a file nav_filelist_reset(); } nav_select( FS_NAV_ID_PLAYLIST ); return true; }
//! This function read the playlist's entry at a specific position.\n //! It is implemented as a non-blocking function. //! //! @param data This data has to be set to 0 if non-caching options are //! used. //! @param u16_position Position in play list. //! @param sz_path The address of the string where is stored the information. //! @param u16_size_line The length of the path. //! @param u16_n The number of line to read at one time //! bool pl_nav_readentry_non_blocking(pl_nav_readentry_context_t *data, uint16_t u16_position, FS_STRING *sz_path, uint16_t *u16_size_line, uint16_t u16_n) { ai_async_context_t ctx; uint16_t u16_current_n; typedef enum { STATE_INITIALIZATION = 0, STATE_SET_POS, STATE_READ_ENTRY } state_t; bool b_update; // If false, means it is the first call if (!ai_async_context_pop(&ctx)) ctx.state = (state_t) STATE_INITIALIZATION; // By default set the status to DONE ctx.status = CMD_DONE; switch((state_t) ctx.state) { // Initialization case STATE_INITIALIZATION: // Set output to NULL to specify if there is an error *sz_path = NULL; // Position out of range if (u16_position == 0) { fs_g_status = FS_ERR_PL_OUT_LST; return false; } // Go to play list file navigator data->nav_id_saved = nav_get(); nav_select(FS_NAV_ID_PLAYLIST); // Save current file position data->u32_file_pos_saved = file_getpos(); // In this case it means the context data is already filled with entry // information for this specific playlist. That is the reason why it is // important to fill this structure with zeros if non-caching options are // used. b_update = true; if (data->fs_entry.u8_open_mode) { if (data->u16_current_pos + 1 <= u16_position) b_update = false; } if (b_update) { // Go to the beginning of the text file reader_txt_beg(); data->u16_current_pos = 0; // Store the info of the entry memcpy(&(data->fs_entry), &fs_g_nav_entry, sizeof(data->fs_entry)); } ctx.status = CMD_EXECUTING; ctx.state = (state_t) STATE_SET_POS; break; case STATE_SET_POS: nav_select(FS_NAV_ID_PLAYLIST); // Restore the info of the entry memcpy(&fs_g_nav_entry, &(data->fs_entry), sizeof(fs_g_nav_entry)); // Look for the "u16_n"th next lines on the file u16_current_n = 0; while ((data->u16_current_pos + 1 != u16_position) && !file_eof() && u16_current_n < u16_n) { if (pl_main_readline(PL_MAIN_READLINE_OPT_CHECKLINE, 0, NULL, NULL)) data->u16_current_pos++; u16_current_n++; } // If end of file if (file_eof()) { // Restore file position file_seek(data->u32_file_pos_saved, FS_SEEK_SET); // Reselect the previous navigator nav_select(data->nav_id_saved); return false; } // If the file has been found ctx.status = CMD_EXECUTING; if (data->u16_current_pos + 1 == u16_position) ctx.state = (state_t) STATE_READ_ENTRY; // Else continue seeking... // Store the info of the entry memcpy(&(data->fs_entry), &fs_g_nav_entry, sizeof(data->fs_entry)); break; case STATE_READ_ENTRY: nav_select(FS_NAV_ID_PLAYLIST); u16_current_n = 0; b_update = false; while (!file_eof() && u16_current_n < u16_n) { if ((b_update = pl_main_readline(PL_MAIN_READLINE_OPT_GOTOPATH, data->nav_id_saved, sz_path, u16_size_line))) break; u16_current_n++; } // Need to retry if (u16_current_n >= u16_n) { ctx.status = CMD_EXECUTING; break; } // If it is the end of the file if (file_eof() && !b_update) { // Restore file position file_seek(data->u32_file_pos_saved, FS_SEEK_SET); // Reselect the previous navigator nav_select(data->nav_id_saved); return false; } // Store positions data->u16_current_pos = u16_position; // Store the info of the entry memcpy(&(data->fs_entry), &fs_g_nav_entry, sizeof(data->fs_entry)); // Restore file position file_seek(data->u32_file_pos_saved, FS_SEEK_SET); // Reselect the previous navigator nav_select(data->nav_id_saved); break; } if (ctx.status == CMD_EXECUTING) { if (!ai_async_context_push(&ctx)) return false; } return true; }
/*! * \brief Supervisor task. * * \return never */ static portTASK_FUNCTION( vSupervisorTask, pvParameters ) { portTickType xDelayLength = SUPERVISOR_DEFAULT_PERIOD; portTickType xLastFocusTime; #if configHEAP_INIT == 1 #if defined(__GNUC__) portLONG lCheckHeapDelay = 1; #endif #endif #if configCTRLPANEL_TRACE == 1 portLONG lPrintTrace = 3; #endif portLONG lUpdateTimeDelay = 1; #ifdef MMILCD_ENABLE portLONG lUpdateMMITimeDelay = 1; portCHAR DateTime[21]; struct tm *pxDate; bool ms_connected_displayed = pdFALSE; bool enum_connected_displayed = pdFALSE; #endif /* The parameters are not used. */ ( void )pvParameters; #if configCTRLPANEL_TRACE == 1 /* Initialize the dump port COM2. */ itracedump_Init(); #endif #ifdef MMILCD_ENABLE // The MMI module. if( pdFALSE == bMMI_start() ) { // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } #endif // Create the SHELL mutex. vSemaphoreCreateBinary( xSHELLFSMutex ); if( NULL == xSHELLFSMutex ) { // The mutex creation failed. // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } // Start the COM1 Shell module. vStartCom1Shell( mainCOMSH_TASK_PRIORITY ); // Create the CFG mutex. vSemaphoreCreateBinary( xCFGMutex ); if( NULL == xCFGMutex ) { // The mutex creation failed. // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } // Start the sensor module. if( false == bsensor_start() ) { // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } #if NW_INTEGRATED_IN_CONTROL_PANEL // Create the Web server mutex. vSemaphoreCreateBinary( xWEBMutex ); if( NULL == xWEBMutex ) { // The mutex creation failed. // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } // Start network tasks. vStartEthernetTaskLauncher( tskIDLE_PRIORITY + 1 ); #endif // Create the LOG mutex. vSemaphoreCreateBinary( xLOGMutex ); if( NULL == xLOGMutex ) { // The mutex creation failed. // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } // Start the data logger module. if( false == bdatalog_start( mainDATALOG_TASK_PRIORITY ) ) { // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } #ifdef USB_ENABLE #if USB_DEVICE_FEATURE == true // Create the USB mutex. vSemaphoreCreateBinary( xUSBMutex ); if( NULL == xUSBMutex ) { // The mutex creation failed. // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } // Immediately take the USB mutex. i.e. when we're a Mass Storage device, // we'll refuse to give r/w access to the host until a user action. This user // action will make the Ctrl Panel device switch to maintenance mode, in which // the Mass Storage USB host has r/w access to the Ctrl Panel file system. while( pdFALSE == x_supervisor_SemaphoreTake( xUSBMutex, 0 ) ); #endif // Start the USB module tasks. if( false == b_usbsys_start() ) { // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } #endif #ifdef MMILCD_ENABLE // Create the supervisor queue to deal with MMI actions xSUPERVISORQueue = xQueueCreate( SUPERVISOR_QUEUE_SIZE, sizeof(bool *) ); if( 0 == xSUPERVISORQueue ) { // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } /* Get a File System navigator for MMI actions. */ fsaccess_take_mutex(); sMmiNavId = fsaccess_alloc_nav_id(); nav_select( sMmiNavId ); // Select the navigator. fsaccess_give_mutex(); /* Spawn the User Action task. */ if( pdPASS != xTaskCreate( vSupervisorUserActionTask, ( const signed portCHAR * )"MMIACT", SUPERVISOR_USER_ACTION_STACK_SIZE, NULL, SUPERVISOR_USER_ACTION_TASK_PRIORITY, &xSupervisorUserActionHndl ) ) { vTaskDelete( xSupervisorUserActionHndl ); // TODO: Add msg on LCD. // vParTestSetLED( ERROR_LED_ID, pdTRUE ); while( 1 ); } #endif // #ifdef MMILCD_ENABLE /* We need to initialise xLastFlashTime prior to the first call to vTaskDelayUntil(). */ xLastFocusTime = xTaskGetTickCount(); #if defined(__GNUC__) NAKED_TRACE_COM2( "heap start @=%d, heap end @=%d", \ (portBASE_TYPE *)&__heap_start__, \ (portBASE_TYPE *)&__heap_end__ ); #endif /* Enable the watchdog timer. */ // wdt_enable( SUPERVISOR_WDT_TIMEOUT ); for(;;) { /* Delay for the flash period then check. */ vTaskDelayUntil( &xLastFocusTime, xDelayLength ); // wdt_clear(); // Kick the watchdog! /* MMI USB management. */ #ifdef MMILCD_ENABLE #ifdef USB_ENABLE /*** Start of Host behaviour ***/ // first occurrence of MS connection, Host mode if (ms_connected == true && ms_connected_displayed == pdFALSE) { // display connected logo ms_connected_displayed = pdTRUE; vMMI_DisplayUSBState(ms_connected_displayed); // Display User Menu vMMI_SetUserMenuMode(eUserMenuUSBHost, pdTRUE); } // first occurrence of MS disconnection, end of Host mode if (ms_connected == false && ms_connected_displayed == pdTRUE) { // remove connected logo ms_connected_displayed = pdFALSE; vMMI_DisplayUSBState(ms_connected_displayed); // clear User Menu vMMI_SetUserMenuMode(eUserMenuIdle, pdTRUE); } /*** End of Host behaviour ***/ /*** Start of Device behaviour ***/ #if USB_DEVICE_FEATURE == true // first occurrence of Device connection, Device mode if (Is_device_enumerated() && ( enum_connected_displayed == pdFALSE ) ) { if( true == bIsInMaintenance ) { // display connected logo enum_connected_displayed = pdTRUE; vMMI_DisplayUSBState(enum_connected_displayed); // Display User Menu vMMI_SetUserMenuMode(eUserMenuUSBDevice, pdTRUE); } } // first occurrence of Device disconnection, end of Device mode else if (!Is_device_enumerated() && enum_connected_displayed == pdTRUE) { // remove connected logo enum_connected_displayed = pdFALSE; vMMI_DisplayUSBState(enum_connected_displayed); // clear User Menu vMMI_SetUserMenuMode(eUserMenuIdle, pdTRUE); } else { // remove connected logo => this makes the USB logo blink when the Control // Panel is behaving as a USB key. enum_connected_displayed = pdFALSE; vMMI_DisplayUSBState(enum_connected_displayed); } /*** End of Device behaviour ***/ #endif // #if USB_DEVICE_FEATURE == true #endif // #ifdef USB_ENABLE #endif // #ifdef MMILCD_ENABLE /* update time every SUPERVISOR_DELAY_TIMEUPDATE seconds. */ if( 0 == --lUpdateTimeDelay ) { /* Update the local time. */ lUpdateTimeDelay = SUPERVISOR_DELAY_TIMEUPDATE; xcptime_LocalTime++; // v_cptime_UpdateLocalTime(); } #ifdef MMILCD_ENABLE /* Update time displayed on the LCD. */ if( 0 == --lUpdateMMITimeDelay) { // Get the broken-down representation of the current date. pxDate = gmtime( &xcptime_LocalTime ); // WARNING: pxDate->tm_year == number of years since 1900. // For years >= 2000, we'll display the last 2 digits only. if( pxDate->tm_year >= 100 ) pxDate->tm_year -= 100; #if DISPLAY_MMI_SECOND == 1 sprintf( DateTime, "%02d/%02d/20%02d %02d:%02d:%02d", pxDate->tm_mon +1, pxDate->tm_mday, pxDate->tm_year, pxDate->tm_hour, pxDate->tm_min, pxDate->tm_sec ); #else sprintf( DateTime, "%02d/%02d/20%02d %02d:%02d", pxDate->tm_mon +1, pxDate->tm_mday, pxDate->tm_year, pxDate->tm_hour, pxDate->tm_min ); #endif vMMI_DisplayDateAndTime(DateTime); lUpdateMMITimeDelay = SUPERVISOR_DELAY_MMI_TIMEUPDATE; } // Manage MMI vMMI_Manage(); // Manage MMI user action prv_v_manage_user_action(); #endif // #ifdef MMILCD_ENABLE #ifdef USB_ENABLE if( true == bOutOfMaintenance ) { prv_v_leave_maintenance_mode(); } #endif /* Execute a scheduled command if expiration date is up. */ v_cptime_ExecuteScheduledCmd(); #if configHEAP_INIT == 1 #if defined(__GNUC__) /* Record the malloc() heap highest consumption every SUPERVISOR_DELAY_HEAPCHECK seconds. */ if( 0 == --lCheckHeapDelay ) { lCheckHeapDelay = SUPERVISOR_DELAY_HEAPCHECK; prvCheckMallocHeap(); } #endif #endif #if configCTRLPANEL_TRACE == 1 // Display traces on USART1 every SUPERVISOR_DELAY_PRINTTASKLIST seconds. if( 0 == --lPrintTrace ) { lPrintTrace = SUPERVISOR_DELAY_PRINTTASKLIST; // Restart the delay. v_syscmds_display_traces(); } #endif } // for(;;) } /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */
//! This function opens the current selected file in the current navigator in read only mode.\n //! It is a non blocking-function that returns every n-file counted. //! //! @param u16_n The number of files to look for before returning.\n //! If it contains the special value of 0, then, it will not //! process the count of link inside the playlist. //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! bool pl_main_open_non_blocking(uint16_t u16_n) { ai_async_context_t ctx; uint16_t u16_current_count = 0; static uint8_t nav_id_save; typedef enum { STATE_INITIALIZATION = 0, STATE_GET_LINK_COUNT, STATE_INIT_PLAYLIST_CONTEXT, STATE_END } state_t; // If false, means it is the first call if (!ai_async_context_pop(&ctx)) ctx.state = (state_t) STATE_INITIALIZATION; // By default set the status to DONE ctx.status = CMD_DONE; switch((state_t) ctx.state) { // Initialization case STATE_INITIALIZATION: if (pl_main_isopen()) return false; // Select the play list file in "play list" navigator // Save current navigator nav_id_save = nav_get(); nav_copy(FS_NAV_ID_PLAYLIST); nav_select(FS_NAV_ID_PLAYLIST); // Make sure the selected file is a playlist if (nav_file_checkext("m3u")) pl_g_list_type = E_PL_M3U; else if (nav_file_checkext("pls")) pl_g_list_type = E_PL_PLS; else if (nav_file_checkext("smp")) pl_g_list_type = E_PL_SMP; else { ctx.status = CMD_EXECUTING; ctx.state = (state_t) STATE_END; break; } // Open list if (!reader_txt_open(true)) { ctx.status = CMD_EXECUTING; ctx.state = (state_t) STATE_END; break; } pl_g_u16_list_size = 0; ctx.status = CMD_EXECUTING; if (u16_n) ctx.state = (state_t) STATE_GET_LINK_COUNT; else ctx.state = (state_t) STATE_INIT_PLAYLIST_CONTEXT; break; case STATE_GET_LINK_COUNT: u16_current_count = 0; nav_select(FS_NAV_ID_PLAYLIST); while (!file_eof() && u16_current_count < u16_n) { if (pl_main_readline(PL_MAIN_READLINE_OPT_CHECKLINE, 0, NULL, NULL)) pl_g_u16_list_size++; // Check if an error occurred during the reading else if (fs_g_status == FS_ERR_FS) { // Error file system ctx.status = CMD_EXECUTING; ctx.state = (state_t) STATE_END; break; } u16_current_count++; } ctx.status = CMD_EXECUTING; if (file_eof()) ctx.state = (state_t) STATE_INIT_PLAYLIST_CONTEXT; break; case STATE_INIT_PLAYLIST_CONTEXT: nav_select(FS_NAV_ID_PLAYLIST); // Go to at the beginning of text file reader_txt_beg(); // Don't select a file pl_g_u16_list_sel = 0; // Play list file is opened pl_g_list_is_open = true; // Re select the previous navigator nav_select(nav_id_save); nav_filelist_reset(); break; case STATE_END: // Re select the previous navigator nav_select(nav_id_save); break; } if (ctx.status == CMD_EXECUTING) { if (!ai_async_context_push(&ctx)) return false; } return pl_g_list_is_open; }
//! @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; }
//! This function opens the current selected file in the current navigator //! //! @param b_undo true to authorize the undo feature //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! bool pl_main_open( bool b_undo ) { uint8_t nav_id_save; if( pl_main_isopen() ) return false; // Select the play list file in "play list" navigator nav_id_save = nav_get(); // Save current navigator nav_copy( FS_NAV_ID_PLAYLIST ); nav_select( FS_NAV_ID_PLAYLIST ); // Make sure the selected file is a playlist if( nav_file_checkext("m3u") ) { pl_g_list_type = E_PL_M3U; }else if( nav_file_checkext("pls") ) { pl_g_list_type = E_PL_PLS; }else if( nav_file_checkext("smp") ) { pl_g_list_type = E_PL_SMP; }else goto pl_main_open_end; // Open list #if( PL_READONLY == false ) pl_g_list_undo = b_undo; pl_g_list_is_modify = false; pl_g_list_is_readonly = nav_file_isreadonly(); if( pl_g_list_is_readonly ) { if( !reader_txt_open( true )) goto pl_main_open_end; }else{ if( !reader_txt_open( false )) goto pl_main_open_end; } #else if( !reader_txt_open( true )) goto pl_main_open_end; #endif // Compute the number of file in list pl_g_u16_list_size = 0; while( 0 == file_eof() ) { if( pl_main_readline(PL_MAIN_READLINE_OPT_CHECKLINE,0,NULL,NULL) ) pl_g_u16_list_size++; // Add a file } // Go to at the beginning of text file reader_txt_beg(); pl_g_u16_list_sel = 0; // Don't select a file pl_g_list_is_open = true; // Play list file is opened nav_select( nav_id_save ); // Re select the previous navigator nav_filelist_reset(); pl_main_open_end: nav_select( nav_id_save ); // Re select the previous navigator return pl_g_list_is_open; }
//! This function read the playlist's entry at a specific position //! //! @param u16_position Position in play list. //! @param sz_path The address of the string where is stored the information. //! @param u16_size_line The length of the path. //! bool pl_nav_readentry(uint16_t u16_position, FS_STRING *sz_path, uint16_t *u16_size_line ) { uint8_t nav_id_save; uint16_t u16_current_pos; uint32_t u32_file_pos; // Set output to NULL to specify if there is an error *sz_path = NULL; // Position out of range if ((0 == u16_position) || (pl_g_u16_list_size < u16_position)) { fs_g_status = FS_ERR_PL_OUT_LST; return false; } // Go to play list file navigator nav_id_save = nav_get(); nav_select(FS_NAV_ID_PLAYLIST); // Save current file position u32_file_pos = file_getpos(); if (pl_g_u16_list_sel > u16_position) { // Go to the beginning of the text file reader_txt_beg(); u16_current_pos = 0; } else { u16_current_pos = pl_g_u16_list_sel; } while(u16_current_pos != u16_position) { if (file_eof()) { // Restore file position file_seek(u32_file_pos, FS_SEEK_SET); // Reselect the previous navigator nav_select(nav_id_save); return false; } if (u16_current_pos+1 == u16_position) { if (pl_main_readline(PL_MAIN_READLINE_OPT_GOTOPATH, nav_id_save, sz_path, u16_size_line)) break; } else if (pl_main_readline(PL_MAIN_READLINE_OPT_CHECKLINE, 0, NULL, NULL)) u16_current_pos++; // Add a file } // Restore file position file_seek(u32_file_pos, FS_SEEK_SET); // Reselect the previous navigator nav_select(nav_id_save); 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 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; }
//! This function adds files in play list //! //! @param sz_filterext add file only corresponding to the extension filter //! @param u8_mode PL_ADD_FILE, PL_ADD_DIR, PL_ADD_SUBDIR //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! //! @verbatim //! It is possible to select a file or all files in a directory //! @endverbatim //! bool pl_add( const FS_STRING sz_filterext , uint8_t u8_mode ) { uint8_t nav_id_save; uint8_t u8_folder_level; if( !pl_main_modify() ) return false; nav_id_save = nav_get(); // Check last character of file nav_select( FS_NAV_ID_PLAYLIST ); if( 0!=nav_file_lgt() ) { #if( PL_UNICODE == true) file_string_unicode(); file_seek( 2, FS_SEEK_END); if( '\n' != file_getc()) { file_seek( 2, FS_SEEK_END); file_putc('\n'); } file_string_ascii(); #else file_seek( 1, FS_SEEK_END); if( '\n' != file_getc()) { file_seek( 1, FS_SEEK_END); file_putc('\n'); } #endif } nav_select( nav_id_save ); // Get path of play list file and check with current to create a relative path if( PL_ADD_FILE == u8_mode ) goto pl_add_file; // Add all files valid in current dir u8_folder_level = 0; nav_filelist_reset(); while(1) { while(1) { 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 if( 0 == u8_folder_level ) goto pl_add_end; // end of ADD // Remark, nav_dir_gotoparent() routine go to in parent dir and select the children dir in list u8_folder_level--; if( !nav_dir_gotoparent() ) return false; } if( nav_file_isdir()) { if( PL_ADD_SUBDIR == u8_mode ) { // Enter in sub dir if( !nav_dir_cd()) return false; u8_folder_level++; } } else { pl_add_file: if( nav_file_checkext( sz_filterext ) ) { // It is a valid file // Get name of current file #if( (FS_ASCII == true) && (FS_UNICODE == true) && (PL_UNICODE == false) ) nav_string_ascii(); #endif nav_getcwd( (FS_STRING)pl_cache_path, PL_CACHE_PATH_MAX_SIZE, true ); #if( (FS_ASCII == true) && (FS_UNICODE == true) && (PL_UNICODE == false) ) nav_string_unicode(); #endif // Write path in file list nav_select( FS_NAV_ID_PLAYLIST ); #if( PL_UNICODE == true) file_string_unicode(); #endif if( file_puts(pl_cache_path)) file_putc('\n'); #if( PL_UNICODE == true) file_string_ascii(); #endif nav_select( nav_id_save ); pl_g_u16_list_size++; } if( PL_ADD_FILE == u8_mode ) goto pl_add_end; } // if dir OR file } // end of first while(1) pl_add_end: // Go to beginning of file AND no file selected nav_select( FS_NAV_ID_PLAYLIST ); file_seek( 0 , FS_SEEK_SET ); pl_g_u16_list_sel = 0; nav_select( nav_id_save ); 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; }
//! //! This function opens a file. //! //! @param pathname path of the file to open. //! @param flags flags to give file access rights //! should be O_CREAT : create file if not exist //! O_APPEND : add data to the end of file //! O_RDONLY : Read Only //! O_WRONLY : Write Only //! O_RDWR : Read/Write //! @return int : file descriptor (>= 0 if OK (NavID), -1 otherwise) //! int open(const char *pathname, int flags, ...) { int CurrentNavId = -1; // take the mutex for nav access fsaccess_take_mutex(); // if no navigator available, return an error if ((CurrentNavId = fsaccess_alloc_nav_id()) < 0) goto error_exit; // select the navigator nav_select( CurrentNavId ); // the filesystem is now at the root directory if ((flags & O_CREAT) == O_CREAT) { // try to create, the flag is set if(nav_setcwd((FS_STRING)pathname, false, true) == false) { goto error_free_nav; } } else { // do not try to create, if it doesn't exist, error if(nav_setcwd((FS_STRING)pathname, false, false) == false) { goto error_free_nav; } } // if user wants to append in file if ((flags & O_APPEND) == O_APPEND) { // open the file if (file_open(FOPEN_MODE_APPEND) == false) goto error_free_nav; } else if ((flags & O_RDWR) == O_RDWR) { // open as read/write if (file_open(FOPEN_MODE_R_PLUS) == false) goto error_free_nav; } else if ((flags & O_WRONLY) == O_WRONLY) { // open as write if (file_open(FOPEN_MODE_W) == false) goto error_free_nav; } else { // open as read if (file_open(FOPEN_MODE_R) == false) goto error_free_nav; } // give the mutex for nav access fsaccess_give_mutex(); return (CurrentNavId); error_free_nav: // mark NavId as free fsaccess_free_nav_id(CurrentNavId); error_exit: // give the mutex for nav access fsaccess_give_mutex(); return(-1); }