ushell_task.c

Go to the documentation of this file.
00001 /*This file is prepared for Doxygen automatic documentation generation.*/
00013 
00014 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
00015  *
00016  * Redistribution and use in source and binary forms, with or without
00017  * modification, are permitted provided that the following conditions are met:
00018  *
00019  * 1. Redistributions of source code must retain the above copyright notice,
00020  * this list of conditions and the following disclaimer.
00021  *
00022  * 2. Redistributions in binary form must reproduce the above copyright notice,
00023  * this list of conditions and the following disclaimer in the documentation
00024  * and/or other materials provided with the distribution.
00025  *
00026  * 3. The name of Atmel may not be used to endorse or promote products derived
00027  * from this software without specific prior written permission.
00028  *
00029  * 4. This software may only be redistributed and used in connection with an Atmel
00030  * AVR product.
00031  *
00032  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
00033  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00034  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
00035  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00036  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00037  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00038  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00039  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00040  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00041  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00042  */
00043 
00044 //_____  I N C L U D E S ___________________________________________________
00045 
00046 #include "config.h"
00047 #include "ushell_task.h"
00048 #include <stdio.h>
00049 #include "lib_mem/df/df_mem.h"
00050 #include "lib_mcu/wdt/wdt_drv.h"
00051 #include "lib_mcu/uart/uart_lib.h"
00052 #include "lib_mcu/usb/usb_drv.h"
00053 #include "lib_mcu/timer/timer16_drv.h"
00054 #if (TARGET_BOARD==SPIDER)
00055 #include "lib_board/spider/spider_drv.h"
00056 #include "lib_board/intermcu_spi/intermcu_spi_drv.h"
00057 #endif
00058 #include "modules/file_system/fat.h"
00059 #include "modules/file_system/fs_com.h"
00060 #include "modules/file_system/navigation.h"
00061 #include "modules/file_system/file.h"
00062 #include "modules/file_system/nav_utils.h"
00063 #include "modules/usb/device_chap9/usb_standard_request.h"
00064 #include "modules/control_access/ctrl_access.h"
00065 
00066 #ifndef USHELL_RF
00067    #define USHELL_RF DISABLE
00068    #define ushell_putchar  uart_putchar
00069    #define ushell_test_hit uart_test_hit
00070    #define ushell_get_char uart_getchar
00071 #endif
00072 
00073 #if (USHELL_RF==ENABLE)
00074    #include "rf_task.h"
00075    void rf_task_init(void);
00076 #endif
00077 
00078 
00079 #if (USHELL_DFU==ENABLE)
00080 #include "modules/usb/host_chap9/usb_host_task.h"
00081 #include "modules/usb/host_chap9/usb_host_enum.h"
00082 #include "host_dfu_task.h"
00083 #endif
00084 
00085 #if (USHELL_USB==ENABLE)
00086 #include "conf_usb.h"
00087 #include "modules/usb/host_chap9/usb_host_task.h"
00088 #include "modules/usb/host_chap9/usb_host_enum.h"
00089 #include "modules/usb/device_chap9/usb_standard_request.h"
00090 #  if(USB_HUB_SUPPORT==ENABLE)
00091 #include "modules/usb/host_chap9/usb_host_hub.h"
00092 #  endif
00093 #endif
00094 
00095 #if (USHELL_HID==ENABLE)
00096 #include "host_hid_task.h"
00097 #endif
00098 
00099 
00100 //_____ M A C R O S ________________________________________________________
00101 
00102 #ifndef USHELL_DFU
00103 #warning USHELL_DFU is not defined as ENABLE or DISABLE, using DISABLE by default...
00104 #define  USHELL_DFU DISABLE
00105 #endif
00106 
00107 #ifndef USHELL_USB
00108 #warning USHELL_USB is not defined as ENABLE or DISABLE, using DISABLE by default...
00109 #define  USHELL_USB DISABLE
00110 #endif
00111 
00112 #ifndef USHELL_HID
00113 #warning USHELL_HID is not defined as ENABLE or DISABLE, using DISABLE by default...
00114 #define  USHELL_HID DISABLE
00115 #endif
00116 
00117 #ifndef USHELL_HISTORY
00118 #warning USHELL_HISTORY value is not defined using 10 as default value
00119 #define  USHELL_HISTORY 10
00120 #endif
00121 
00122 #ifndef USHELL_NB_LINE
00123 #warning USHELL_NB_LINE value is not defined using 20 as default value
00124 #define USHELL_NB_LINE  20
00125 #endif
00126 
00127 
00128 #ifndef USHELL_SIZE_CMD_LINE
00129 #warning USHELL_SIZE_CMD_LINE value is not defined using 30 as default value
00130 #define USHELL_SIZE_CMD_LINE  30
00131 #endif
00132 
00133 #define USHELL_MAX_NB_ARG     2
00134 
00135 //_____ D E C L A R A T I O N S ____________________________________________
00136 
00137 
00138 // Manage task
00139 static Bool g_b_ushell_task_run = FALSE;
00140 
00141 // To manage command line
00142 static U8   g_u8_escape_sequence=0;
00143 static U8   g_u8_cmd_size=0;
00144 static U8   g_u8_history_pos=0;
00145 static U8   g_u8_history_pos_search=0;
00146 static char g_s_cmd_his[USHELL_HISTORY][USHELL_SIZE_CMD_LINE];
00147 static char g_s_cmd[USHELL_SIZE_CMD_LINE];
00148 static char g_s_arg[USHELL_MAX_NB_ARG][USHELL_SIZE_CMD_LINE];
00149 
00150 // To manage a file system shortcut
00151 static Fs_index g_mark_index;
00152 
00153 
00154 //* To store all shell messages
00155 U8 code str_cd[]=STR_CD;
00156 U8 code str_mount[]=STR_MOUNT;
00157 U8 code str_cp[]=STR_CP;
00158 U8 code str_ls[]=STR_LS;
00159 U8 code str_ls_more[]=STR_LS_MORE;
00160 U8 code str_rm[]=STR_RM;
00161 U8 code str_df[]=STR_DF;
00162 U8 code str_space[]=STR_SPACE;
00163 U8 code str_mkdir[]=STR_MKDIR;
00164 U8 code str_touch[]=STR_TOUCH;
00165 U8 code str_append[]=STR_APPEND;
00166 U8 code str_cat[]=STR_CAT;
00167 U8 code str_cat_more[]=STR_CAT_MORE;
00168 U8 code str_up[]=STR_UP;
00169 U8 code str_disk[]=STR_DISK;
00170 U8 code str_mark[]=STR_MARK;
00171 U8 code str_goto[]=STR_GOTO;
00172 U8 code str_mv[]=STR_MV;
00173 U8 code str_help[]=STR_HELP;
00174 U8 code str_format[]=STR_FORMAT;
00175 U8 code str_sync[]=STR_SYNC;
00176 U8 code str_perform[]=STR_PERFORM;
00177 U8 code str_reboot[]=STR_REBOOT;
00178 #if (USHELL_USB==ENABLE)
00179 U8 code str_ls_usb[]=STR_LS_USB;
00180 U8 code str_usb_suspend[]=STR_USB_SUSPEND;
00181 U8 code str_usb_resume[]=STR_USB_RESUME;
00182 U8 code str_usb_force_enum[]=STR_USB_FORCE_ENUM;
00183 #endif
00184 #if (USHELL_DFU==ENABLE)
00185 U8 code str_dfu_erase[]=STR_DFU_ERASE;
00186 U8 code str_dfu_load[]=STR_DFU_LOAD;
00187 U8 code str_dfu_start[]=STR_DFU_START;
00188 #endif
00189 #if (USHELL_HID==ENABLE)
00190 U8 code str_hid_enter_dfu[]=STR_HID_ENTER_DFU;
00191 U8 code str_hid_get_info[]=STR_HID_GET_INFO;
00192 #endif
00193 U8 code msg_paste_fail[]=MSG_ER_PASTE;
00194 U8 code msg_prompt[]=MSG_PROMPT;
00195 U8 code msg_welcome[]=MSG_WELCOME;
00196 U8 code msg_exit[]=MSG_EXIT;
00197 U8 code msg_er_mount[]=MSG_ER_MOUNT;
00198 U8 code msg_er_drive[]=MSG_ER_DRIVE;
00199 U8 code msg_er_rm[]=MSG_ER_RM;
00200 U8 code msg_er_unknown_file[]=MSG_ER_UNKNOWN_FILE;
00201 U8 code msg_er_cmd_not_found[]=MSG_ER_CMD_NOT_FOUND;
00202 U8 code msg_er_format[]=MSG_ER_FORMAT;
00203 U8 code msg_append_welcome[]=MSG_APPEND_WELCOME;
00204 U8 code msg_help[]=MSG_HELP;
00205 U8 code msg_no_device[]=MSG_NO_DEVICE;
00206 U8 code msg_ok[]=MSG_OK;
00207 U8 code msg_ko[]=MSG_KO;
00208 #if (USHELL_USB==ENABLE)
00209 U8 code msg_remote_wake_up_ok[]=MSG_REMOTE_WAKEUP_OK;
00210 U8 code msg_remote_wake_up_ko[]=MSG_REMOTE_WAKEUP_KO;
00211 U8 code msg_device_self_powered[]=MSG_SELF_POWERED;
00212 U8 code msg_device_bus_powered[]=MSG_BUS_POWERED;
00213 U8 code msg_usb_suspended[]=MSG_USB_SUSPENDED;
00214 U8 code msg_device_full_speed[]=MSG_DEVICE_FULL_SPEED;
00215 U8 code msg_device_low_speed[]=MSG_DEVICE_LOW_SPEED;
00216 #endif
00217 
00218 
00219 // Internal sub routines
00220 Bool  ushell_cmd_scan         ( void );
00221 U8    ushell_cmd_decode       ( void );
00222 void  ushell_clean_cmd_line   ( void );
00223 void  ushell_history_up       ( void );
00224 void  ushell_history_down     ( void );
00225 void  ushell_history_display  ( void );
00226 #ifdef __GNUC__
00227    U8    mystrncmp      (char *str1,U8 *str2,U8 i);
00228    void  print_msg      (U8 *str);
00229 #else
00230    U8    mystrncmp      (char *str1,U8 code *str2,U8 i);
00231    void  print_msg      (U8 code *str);
00232 #endif
00233 Bool  ushell_more_wait        ( void );
00234 // Internal sub routines for file system commands
00235 void  ushell_cmd_nb_drive     ( void );
00236 void  ushell_cmd_free_space   ( void );
00237 void  ushell_cmd_format       ( void );
00238 void  ushell_cmd_mount        ( void );
00239 void  ushell_cmd_space        ( void );
00240 void  ushell_cmd_ls           ( Bool b_more );
00241 void  ushell_cmd_cd           ( void );
00242 void  ushell_cmd_gotoparent   ( void );
00243 void  ushell_cmd_cat          ( Bool b_more);
00244 void  ushell_cmd_help         ( void );
00245 void  ushell_cmd_mkdir        ( void );
00246 void  ushell_cmd_touch        ( void );
00247 void  ushell_cmd_rm           ( void );
00248 void  ushell_cmd_append_file  ( void );
00249 void  ushell_cmd_copy         ( void );
00250 void  ushell_cmd_rename       ( void );
00251 void  ushell_cmd_reboot       ( void );
00252 Bool  ushell_cmd_sync         ( void );
00253 void  ushell_cmd_perform      ( void );
00254 void  ushell_path_valid_syntac( char *path );
00255 // Internal sub routines for USB commands
00256 void  ushell_cmdusb_ls        ( void );
00257 void  ushell_cmdusb_suspend   ( void );
00258 void  ushell_cmdusb_resume    ( void );
00259 void  ushell_cmdusb_force_enum( void );
00260 // Internal sub routines for USB DFU commands
00261 void  ushell_cmddfu_erase     ( void );
00262 void  ushell_cmddfu_load      ( void );
00263 void  ushell_cmddfu_start     ( void );
00264 // Internal sub routines for USB HID commands
00265 void  ushell_cmdhid_enter_dfu ( void );
00266 void  ushell_cmdhid_getinfo   ( void );
00267 
00268 
00269 
00272 void ushell_task_init(void)
00273 {
00274    U8 u8_i;
00275 #if (USHELL_RF==ENABLE)
00276    rf_task_init();
00277 #else
00278    uart_init();
00279 #endif
00280 
00281 #ifdef __GNUC__
00282    fdevopen((int (*)(char, FILE*))(ushell_putchar),(int (*)(FILE*))ushell_get_char); //for printf redirection
00283 #endif
00284    g_b_ushell_task_run = FALSE;
00285    for( u8_i=0; u8_i<USHELL_HISTORY; u8_i++ ) {
00286       g_s_cmd_his[u8_i][0] = 0;  // Set end of line for all cmd line history
00287    }
00288   
00289 }
00290 
00291 
00296 void ushell_task(void)
00297 {
00298    //** Check the USB mode and autorize/unautorize ushell
00299    if(!g_b_ushell_task_run)
00300    {
00301       if( Is_usb_id_device() )
00302          return;
00303       g_b_ushell_task_run = TRUE;
00304       print_msg((U8 code *)msg_welcome);
00305       ushell_cmd_nb_drive();
00306       print_msg((U8 code *)msg_prompt);
00307       // Reset the embedded FS on ushell navigator and on first drive
00308       nav_reset();
00309       nav_select( FS_NAV_ID_USHELL_CMD );
00310    }else{
00311       if( Is_usb_id_device() )
00312       {
00313          g_b_ushell_task_run = FALSE;
00314          print_msg((U8 code *)msg_exit);
00315          nav_exit();
00316          return;
00317       }
00318    }
00319 
00320    if( !ushell_cmd_scan() )
00321       return;
00322 
00323    //** Command ready then decode and execute this one
00324    switch( ushell_cmd_decode() )
00325    {
00326       // Displays number of  drives
00327       case CMD_NB_DRIVE:
00328       ushell_cmd_nb_drive();
00329       break;
00330 
00331       // Displays free space information for all connected drives
00332       case CMD_DF:
00333       ushell_cmd_free_space();
00334       break;
00335 
00336       // Formats disk
00337       case CMD_FORMAT:
00338       ushell_cmd_format();
00339       break;
00340       
00341       // Mounts a drive (e.g. "b:")
00342       case CMD_MOUNT:
00343       ushell_cmd_mount();
00344       break;
00345 
00346       // Displays the space information for current drive
00347       case CMD_SPACE:
00348       ushell_cmd_space();
00349       break;
00350       
00351       // Lists the files present in current directory (e.g. "ls")
00352       case CMD_LS:
00353       ushell_cmd_ls(FALSE);
00354       break;
00355       case CMD_LS_MORE:
00356       ushell_cmd_ls(TRUE);
00357       break;
00358 
00359       // Enters in a directory (e.g. "cd folder_toto")
00360       case CMD_CD:
00361       ushell_cmd_cd();
00362       break;
00363 
00364       // Enters in parent directory ("cd..")
00365       case CMD_UP:
00366       ushell_cmd_gotoparent();
00367       break;
00368 
00369       // Displays a text file
00370       case CMD_CAT:
00371       ushell_cmd_cat(FALSE);
00372       break;
00373       case CMD_CAT_MORE:
00374       ushell_cmd_cat(TRUE);
00375       break;
00376          
00377       // Displays the help
00378       case CMD_HELP:
00379       ushell_cmd_help();
00380       break;
00381 
00382       // Creates directory
00383       case CMD_MKDIR:
00384       ushell_cmd_mkdir();
00385       break;
00386 
00387       // Creates file
00388       case CMD_TOUCH:
00389       ushell_cmd_touch();
00390       break;
00391       
00392       // Deletes files or directories
00393       case CMD_RM:
00394       ushell_cmd_rm();
00395       break;
00396 
00397       // Appends char to selected file
00398       case CMD_APPEND:
00399       ushell_cmd_append_file();
00400       break;
00401 
00402       // Index routines (= specific shortcut from ATMEL FileSystem)
00403       case CMD_SET_ID:
00404       g_mark_index = nav_getindex();
00405       break;
00406       case CMD_GOTO_ID:
00407       nav_gotoindex( &g_mark_index );
00408       break;
00409       
00410       // Copys file to other location
00411       case CMD_CP:
00412       ushell_cmd_copy();
00413       break;
00414 
00415       // Renames file
00416       case CMD_MV:
00417       ushell_cmd_rename();
00418       break;
00419 
00420       // Synchronize folders
00421       case CMD_SYNC:
00422       ushell_cmd_sync();
00423       break;
00424 
00425       // Perform transfer
00426       case CMD_PERFORM:
00427       ushell_cmd_perform();
00428       break;
00429 
00430       // Reboot target
00431       case CMD_REBOOT:
00432       ushell_cmd_reboot();
00433       break;
00434 
00435       // USB commands
00436 #if (USHELL_USB==ENABLE)
00437       case CMD_LS_USB:
00438       ushell_cmdusb_ls();
00439       break;
00440       case CMD_USB_SUSPEND:
00441       ushell_cmdusb_suspend();
00442       break;
00443       case CMD_USB_RESUME:
00444       ushell_cmdusb_resume();
00445       break;
00446       case CMD_USB_FORCE_ENUM:
00447       ushell_cmdusb_force_enum();
00448       break;
00449 #endif
00450 
00451       // DFU commands
00452 #if (USHELL_DFU==ENABLE)
00453       case CMD_DFU_ERASE:
00454       ushell_cmddfu_erase();
00455       break;
00456       case CMD_DFU_LOAD:
00457       ushell_cmddfu_load();
00458       break;
00459       case CMD_DFU_START:
00460       ushell_cmddfu_start();
00461       break;
00462 #endif
00463 
00464       // HID commands
00465 #if (USHELL_HID==ENABLE)
00466       case CMD_HID_ENTER_DFU:
00467       ushell_cmdhid_enter_dfu();
00468       break;
00469       case CMD_HID_GET_INFO:
00470       ushell_cmdhid_getinfo();
00471       break;
00472 #endif
00473 
00474       // Unknown command
00475       default:
00476       print_msg((U8 code *)msg_er_cmd_not_found);
00477       break;
00478    }
00479 
00480    print_msg((U8 code *)msg_prompt);
00481 }
00482 
00483 
00488 Bool ushell_cmd_scan(void)
00489 {
00490    char c_key;
00491 
00492    // Something new of the UART ?
00493    if(!ushell_test_hit())   
00494       return FALSE;
00495 
00496    c_key=ushell_get_char();
00497    
00498    if( 0 != g_u8_escape_sequence )
00499    {
00500       //** Decode escape sequence
00501       if( 1 == g_u8_escape_sequence )
00502       {
00503          if( 0x5B != c_key )
00504          {
00505             g_u8_escape_sequence=0;
00506             return FALSE;  // Escape sequence cancel
00507          }
00508          g_u8_escape_sequence=2;
00509       }
00510       else
00511       {
00512          // Decode value of the sequence
00513          switch (c_key)
00514          {
00515 /*
00516 Note: OVERRUN error on USART with an RTOS and USART without interrupt management
00517 If you want support "Escape sequence", then you have to implement USART interrupt management
00518             case 0x41:     // UP command
00519             ushell_clean_cmd_line();
00520             ushell_history_up();
00521             ushell_history_display();
00522             break;
00523             case 0x42:     // DOWN command           
00524             ushell_clean_cmd_line();
00525             ushell_history_down();
00526             ushell_history_display();
00527             break;
00528 */            
00529             default:       // Ignore other command
00530             break;
00531          }
00532          g_u8_escape_sequence=0; // End of Escape sequence 
00533       }
00534       return FALSE;
00535    }
00536    
00537    //** Normal sequence
00538    switch (c_key)
00539    {
00540       //** Command validation
00541       case ASCII_CR:
00542       ushell_putchar(ASCII_CR);     // Echo
00543       ushell_putchar(ASCII_LF);     // Add new line flag
00544       g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size]=0;  // Add NULL terminator at the end of command line
00545       return TRUE;
00546       
00547       //** Enter in escape sequence
00548       case ASCII_ESCAPE:
00549       g_u8_escape_sequence=1;
00550       break;
00551       
00552       //** backspace
00553       case ASCII_BKSPACE:
00554       if(g_u8_cmd_size>0)        // Beginning of line ?
00555       {
00556          // Remove the last character on terminal
00557          ushell_putchar(ASCII_BKSPACE);   // Send a backspace to go in previous character
00558          ushell_putchar(' ');             // Send a space to erase previous character
00559          ushell_putchar(ASCII_BKSPACE);   // Send a backspace to go in new end position (=previous character position)
00560          // Remove the last character on cmd line buffer
00561          g_u8_cmd_size--;
00562       }
00563       break;
00564       
00565       // History management
00566       case '!':
00567       ushell_clean_cmd_line();
00568       ushell_history_up();
00569       ushell_history_display();
00570       break;
00571       case '$':
00572       ushell_clean_cmd_line();
00573       ushell_history_down();
00574       ushell_history_display();
00575       break;
00576 
00577       //** Other char
00578       default:
00579       if( (0x1F<c_key) && (c_key<0x7F) && (USHELL_SIZE_CMD_LINE!=g_u8_cmd_size) )
00580       {
00581          // Accept char
00582          ushell_putchar(c_key);                                   // Echo
00583          g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size++] = c_key;  // append to cmd line
00584       }
00585       break;
00586    }
00587    return FALSE;
00588 }
00589 
00590 
00600 U8 ushell_cmd_decode( void )
00601 {
00602    U8 cmd_type;
00603    U8 u8_i,u8_j,u8_k;
00604    U8 u8_cmd_size;
00605    Bool b_arg_include_space;
00606    
00607    if(0==g_u8_cmd_size)
00608    {
00609       // Command line empty
00610       print_msg((U8 code *)msg_prompt);
00611       return CMD_NONE;
00612    }
00613 
00614    // Get command string and Change command to lower case
00615    for( u8_i=0; (g_s_cmd_his[g_u8_history_pos][u8_i]!=' ') && (u8_i<=g_u8_cmd_size); u8_i++)
00616    {
00617       g_s_cmd[u8_i] = g_s_cmd_his[g_u8_history_pos][u8_i];
00618       if( ('A'<=g_s_cmd[u8_i]) && (g_s_cmd[u8_i]<='Z') )
00619          g_s_cmd[u8_i] += ('a'-'A');
00620    }
00621    g_s_cmd[u8_i]=0;
00622    u8_cmd_size = u8_i-1;
00623 
00624    // Get arguments strings
00625    for( u8_j=0; u8_j<USHELL_MAX_NB_ARG; u8_j++ )
00626    {
00627       u8_i++;     // Jump space character
00628       // Check "
00629       b_arg_include_space = ( g_s_cmd_his[g_u8_history_pos][u8_i] == '"' );
00630       if( b_arg_include_space ) {
00631         u8_i++;
00632       }
00633       for( u8_k=0;
00634            (b_arg_include_space || (g_s_cmd_his[g_u8_history_pos][u8_i] != ' '))
00635            && ((!b_arg_include_space) || (g_s_cmd_his[g_u8_history_pos][u8_i] != '"'))
00636            && (u8_i<=g_u8_cmd_size);
00637            u8_i++, u8_k++ )
00638       {
00639          g_s_arg[u8_j][u8_k] = g_s_cmd_his[g_u8_history_pos][u8_i];
00640       }
00641       if( b_arg_include_space ) {
00642         u8_i++;   // Jump last "
00643       }
00644       g_s_arg[u8_j][u8_k] = 0;
00645    }
00646            
00647    // Reset command size and update history       
00648    g_u8_cmd_size=0;
00649    g_u8_history_pos++;
00650    if( g_u8_history_pos == USHELL_HISTORY)
00651       g_u8_history_pos = 0;
00652    g_u8_history_pos_search = g_u8_history_pos;
00653    
00654    // Decode command type
00655    if ( mystrncmp(g_s_cmd,(U8 code *)str_disk,u8_cmd_size))
00656    {  cmd_type=CMD_NB_DRIVE; }
00657    else if ( mystrncmp(g_s_cmd,(U8 code *)str_df,u8_cmd_size))
00658    {  cmd_type=CMD_DF; }
00659    else if ( mystrncmp(g_s_cmd,(U8 code *)str_format,u8_cmd_size))
00660    {  cmd_type=CMD_FORMAT; }
00661    else if ( mystrncmp(g_s_cmd,(U8 code *)str_mount,u8_cmd_size))
00662    {  cmd_type=CMD_MOUNT; }
00663    else if ( g_s_cmd[1]==':' )
00664    {  cmd_type=CMD_MOUNT; g_s_arg[0][0]=g_s_cmd[0];g_s_arg[0][1]='0'; }
00665    else if ( mystrncmp(g_s_cmd,(U8 code *)str_space,u8_cmd_size))
00666    {  cmd_type=CMD_SPACE; }
00667    else if ( mystrncmp(g_s_cmd,(U8 code *)str_ls,u8_cmd_size))
00668    {  cmd_type=CMD_LS; }
00669    else if ( mystrncmp(g_s_cmd,(U8 code *)str_ls_more,u8_cmd_size))
00670    {  cmd_type=CMD_LS_MORE; }   
00671    else if (mystrncmp(g_s_cmd,(U8 code *)str_cd,u8_cmd_size))
00672    {  cmd_type=CMD_CD; }
00673    else if ( mystrncmp(g_s_cmd,(U8 code *)str_up,u8_cmd_size))
00674    {  cmd_type=CMD_UP; }
00675    else if ( mystrncmp(g_s_cmd,(U8 code *)str_cat,u8_cmd_size))
00676    {  cmd_type=CMD_CAT; }
00677    else if ( mystrncmp(g_s_cmd,(U8 code *)str_cat_more,u8_cmd_size))
00678    {  cmd_type=CMD_CAT_MORE; }   
00679    else if ( mystrncmp(g_s_cmd,(U8 code *)str_help,u8_cmd_size))
00680    {  cmd_type=CMD_HELP; }
00681    else if ( mystrncmp(g_s_cmd,(U8 code *)str_mkdir,u8_cmd_size))
00682    {  cmd_type=CMD_MKDIR; }
00683    else if ( mystrncmp(g_s_cmd,(U8 code *)str_touch,u8_cmd_size))
00684    {  cmd_type=CMD_TOUCH; }
00685    else if ( mystrncmp(g_s_cmd,(U8 code *)str_rm,u8_cmd_size))
00686    {  cmd_type=CMD_RM; }
00687    else if ( mystrncmp(g_s_cmd,(U8 code *)str_append,u8_cmd_size))
00688    {  cmd_type=CMD_APPEND; }
00689    else if ( mystrncmp(g_s_cmd,(U8 code *)str_mark,u8_cmd_size))
00690    {  cmd_type=CMD_SET_ID; }
00691    else if ( mystrncmp(g_s_cmd,(U8 code *)str_goto,u8_cmd_size))
00692    {  cmd_type=CMD_GOTO_ID; }
00693    else if ( mystrncmp(g_s_cmd,(U8 code *)str_cp,u8_cmd_size))
00694    {  cmd_type=CMD_CP; }
00695    else if ( mystrncmp(g_s_cmd,(U8 code *)str_mv,u8_cmd_size))
00696    {  cmd_type=CMD_MV; }
00697    else if ( mystrncmp(g_s_cmd,(U8 code *)str_sync,u8_cmd_size))
00698    {  cmd_type=CMD_SYNC; }
00699    else if ( mystrncmp(g_s_cmd,(U8 code *)str_perform,u8_cmd_size))
00700    {  cmd_type=CMD_PERFORM; }
00701    else if ( mystrncmp(g_s_cmd,(U8 code *)str_reboot,u8_cmd_size))
00702    {  cmd_type=CMD_REBOOT; }
00703 #if (USHELL_USB==ENABLE)
00704    else if ( mystrncmp(g_s_cmd,(U8 code *)str_ls_usb,u8_cmd_size))
00705    {  cmd_type=CMD_LS_USB; }
00706    else if ( mystrncmp(g_s_cmd,(U8 code *)str_usb_suspend,u8_cmd_size))
00707    {  cmd_type=CMD_USB_SUSPEND; }
00708    else if ( mystrncmp(g_s_cmd,(U8 code *)str_usb_resume,u8_cmd_size))
00709    {  cmd_type=CMD_USB_RESUME; }
00710    else if ( mystrncmp(g_s_cmd,(U8 code *)str_usb_force_enum,u8_cmd_size))
00711    {  cmd_type=CMD_USB_FORCE_ENUM; }
00712 #endif
00713 #if (USHELL_DFU==ENABLE)
00714    else if ( mystrncmp(g_s_cmd,(U8 code *)str_dfu_erase,u8_cmd_size))
00715    {  cmd_type=CMD_DFU_ERASE; }
00716    else if ( mystrncmp(g_s_cmd,(U8 code *)str_dfu_load,u8_cmd_size))
00717    {  cmd_type=CMD_DFU_LOAD; }
00718    else if ( mystrncmp(g_s_cmd,(U8 code *)str_dfu_start,u8_cmd_size))
00719    {  cmd_type=CMD_DFU_START; }
00720 #endif
00721 #if (USHELL_HID==ENABLE)
00722    else if ( mystrncmp(g_s_cmd,(U8 code *)str_hid_enter_dfu,u8_cmd_size))
00723    {  cmd_type=CMD_HID_ENTER_DFU; }
00724    else if ( mystrncmp(g_s_cmd,(U8 code *)str_hid_get_info,u8_cmd_size))
00725    {  cmd_type=CMD_HID_GET_INFO; }
00726 #endif
00727    else
00728    {
00729       print_msg((U8 code *)msg_er_cmd_not_found);
00730       print_msg((U8 code *)msg_prompt);
00731       return CMD_NONE;
00732    }
00733    return cmd_type;
00734 }
00735 
00736 
00739 void ushell_clean_cmd_line( void )
00740 {
00741    // Clean command line display
00742    while( 0 != g_u8_cmd_size )
00743    {
00744       // Remove the last character on cmd line buffer
00745       putchar(ASCII_BKSPACE); // Send a backspace to go in previous character
00746       putchar(' ');           // Send a space to erase previous character
00747       putchar(ASCII_BKSPACE); // Send a backspace to go in new end position (=previous character position)
00748       g_u8_cmd_size--;
00749    }
00750 }
00751 
00752 
00755 void ushell_history_up( void )
00756 {
00757    if( g_u8_history_pos_search == 0 )
00758    {
00759       if( (USHELL_HISTORY-1) == g_u8_history_pos )
00760          return;  // End of history list
00761       g_u8_history_pos_search = USHELL_HISTORY-1;
00762    }else{
00763       if( (g_u8_history_pos_search-1) == g_u8_history_pos )
00764          return;  // End of history list
00765       g_u8_history_pos_search--;
00766    }
00767    if( 0 == g_s_cmd_his[g_u8_history_pos_search][0] )
00768    {
00769       // History empty then go to previous selection
00770       ushell_history_down();
00771    }
00772 }
00773 
00774 
00777 void ushell_history_down( void )
00778 {
00779    if( g_u8_history_pos_search == g_u8_history_pos )
00780       return;  // End of history list
00781    if( g_u8_history_pos == 0 )
00782    {
00783       if( (USHELL_HISTORY-1) == g_u8_history_pos_search )
00784          return;  // End of history list
00785       g_u8_history_pos_search++;
00786    }else{
00787       if( (g_u8_history_pos_search+1) == g_u8_history_pos )
00788          return;  // End of history list
00789    }
00790    g_u8_history_pos_search++;
00791    if( USHELL_HISTORY == g_u8_history_pos_search )
00792       g_u8_history_pos_search = 0;
00793 }
00794            
00795 
00798 void ushell_history_display( void )
00799 {
00800    g_u8_cmd_size=0;
00801    while( g_s_cmd_his[g_u8_history_pos_search][g_u8_cmd_size] != 0 )
00802    {
00803       putchar( g_s_cmd_his[g_u8_history_pos_search][g_u8_cmd_size] );
00804       g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size] = g_s_cmd_his[g_u8_history_pos_search][g_u8_cmd_size];
00805       g_u8_cmd_size++;
00806    }
00807    g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size] = 0;
00808 }           
00809 
00810    
00811 
00818 #ifdef __GNUC__
00819 U8 mystrncmp(char *str1,U8 *str2,U8 u8_i)
00820 #else
00821 U8 mystrncmp(char *str1,U8 code *str2,U8 u8_i)
00822 #endif
00823 {
00824    U8 j;
00825    for(j=0;j<=u8_i;j++)
00826    {
00827 #ifndef __GNUC__
00828       if(*str1!=*str2)
00829 #else
00830       if( *str1 != pgm_read_byte_near((unsigned int)str2))
00831 #endif
00832       {
00833          return FALSE;
00834       }
00835       str1++;str2++;
00836    }
00837    return TRUE;
00838 }
00839 
00840 
00845 #ifdef __GNUC__
00846 void print_msg(U8 *str)
00847 #else
00848 void print_msg(U8 code *str)
00849 #endif
00850 {
00851    char c;
00852 #ifndef __GNUC__
00853    c=*str++;
00854    while(c!=0)
00855    {
00856       ushell_putchar(c);
00857       c=*str++;
00858    }
00859 #else    // AVRGCC does not support point to PGM space
00860    c=pgm_read_byte_near((unsigned int)str++);
00861    while(c!=0)
00862    {
00863       ushell_putchar(c);
00864       c=pgm_read_byte_near((unsigned int)str++);
00865    }
00866 #endif
00867 
00868 }
00869 
00870 
00875 Bool ushell_more_wait( void )
00876 {
00877    char c_key;
00878    printf("\n\r-- space for more--"); 
00879    c_key=0;
00880    while( (c_key!='q') && (c_key!=' ') )
00881    {
00882      c_key=ushell_get_char();
00883    }
00884    printf("\r                 \r");
00885    return (c_key==' ');
00886 }
00887 
00888 
00891 void ushell_cmd_nb_drive( void )
00892 {
00893    U8 u8_tmp;
00894    
00895    printf("Memory interface available:\r\n");
00896    for( u8_tmp=0; u8_tmp<nav_drive_nb(); u8_tmp++ )
00897    {
00898       // Display drive letter name (a, b...)
00899       ushell_putchar(u8_tmp+'a');
00900       ushell_putchar(':');
00901       ushell_putchar(' ');
00902       print_msg((U8 code *)mem_name(u8_tmp));
00903       ushell_putchar(ASCII_CR); ushell_putchar(ASCII_LF);
00904    }
00905 }
00906 
00907 
00910 void ushell_cmd_free_space( void )
00911 {
00912    U8 u8_tmp;
00913    Fs_index sav_index = nav_getindex();      // Save current position
00914    for( u8_tmp=0; u8_tmp<nav_drive_nb(); u8_tmp++ )
00915    {
00916       nav_drive_set( u8_tmp );      // Select drive
00917       if( !nav_partition_mount() )  // Mount drive
00918          continue;
00919       
00920       // Display drive letter name (a, b...)
00921       ushell_putchar( u8_tmp+'a' );
00922       ushell_putchar(':');
00923       ushell_putchar(' ');
00924       print_msg((U8 code *)mem_name(u8_tmp));
00925       printf("\n\r");
00926       
00927       if( g_s_arg[0][0]=='l' )        // Choose command option
00928       {
00929          // Long and exact fonction
00930          printf("Free space: %lu KBytes / %lu KBytes\n\r", 
00931                    ((unsigned long)nav_partition_freespace()>>1),
00932                    ((unsigned long)nav_partition_space()>>1));
00933       }
00934       else                    
00935       {
00936          // Otherwise use fast command
00937          printf("Free space: %u %%\n\r", nav_partition_freespace_percent() );
00938       }
00939    }
00940    nav_gotoindex(&sav_index);       // Restore position
00941 }
00942 
00943 
00946 void ushell_cmd_format( void )
00947 {
00948    if( g_s_arg[0][0] == 0 )
00949       return;
00950    
00951    // Select drive to format
00952    nav_drive_set( g_s_arg[0][0]-'a');
00953    if( !nav_drive_format(FS_FORMAT_DEFAULT) )
00954    {
00955       print_msg((U8 code *)msg_er_format);
00956       return;
00957    }
00958 }
00959 
00960 
00963 void ushell_cmd_mount( void )
00964 {
00965    U8 u8_drive_lun;
00966    Fs_index sav_index;
00967 
00968    if( g_s_arg[0][0] == 0 )
00969       return;
00970    
00971    // Compute the logical unit number of drive
00972    u8_drive_lun=g_s_arg[0][0]-'a';
00973    // Check lun number
00974    if( u8_drive_lun >= nav_drive_nb() )
00975    {
00976       print_msg((U8 code *)msg_er_drive);
00977       return;
00978    }
00979 
00980    // Mount drive
00981    sav_index = nav_getindex();      // Save previous position
00982    if( nav_drive_set(u8_drive_lun))
00983    {
00984       if( nav_partition_mount() )
00985          return;                    // Here, drive mounted
00986    }
00987    print_msg((U8 code *)msg_er_mount);
00988    nav_gotoindex(&sav_index);       // Restore previous position
00989 }
00990 
00991 
00994 void ushell_cmd_space( void )
00995 {
00996    U32 u32_space;
00997    // Display drive letter name (a, b...)
00998    print_msg((U8 code *)mem_name(nav_drive_get()));
00999    ushell_putchar(' ');
01000    ushell_putchar( nav_drive_get()+'a');
01001    // Otherwise use fast command
01002    u32_space = nav_partition_space();
01003    if( 1024 >(u32_space % (2*1024)) )
01004    {
01005       u32_space = u32_space/(2*1024);
01006    }else{
01007       u32_space = (u32_space/(2*1024))+1;
01008    }
01009    printf(": space: %luMB \n\r", u32_space );
01010 }
01011 
01012 
01017 void ushell_cmd_ls( Bool b_more )
01018 {
01019    U8 str_char[MAX_FILE_LENGHT];
01020    U16 u16_i,u16_nb_file,u16_nb_dir,last_i;
01021    U8 ext_filter=FALSE;
01022 
01023    //** Print drive name
01024    printf("%c: volume is ", 'a'+nav_drive_get() );
01025    print_msg((U8 code *)mem_name(nav_drive_get()));
01026    printf("\n\rDrive uses ");
01027    switch (nav_partition_type())
01028    {
01029       case FS_TYPE_FAT_12:
01030       printf("FAT12\n\r");
01031       break;
01032       
01033       case FS_TYPE_FAT_16:
01034       printf("FAT16\n\r");
01035       break;
01036       
01037       case FS_TYPE_FAT_32:
01038       printf("FAT32\n\r");
01039       break;
01040       
01041       default:
01042       printf("an unknown partition type\r\n");
01043       return;
01044    }
01045    
01046    //** Print directory name
01047    if( !nav_dir_name( (FS_STRING)str_char, MAX_FILE_LENGHT ) )
01048    {
01049       printf("ROOT directory\n\r");
01050    }else{
01051       printf("Dir name is %s\n\r",str_char);
01052    }
01053 
01054    //** Check extension filter in extra parameters
01055    if(g_s_arg[0][0]!=0)
01056    {
01057       if(g_s_arg[0][0] == '*' && g_s_arg[0][1]=='.')
01058       {
01059          ext_filter=TRUE;
01060          for(u16_i=2; u16_i<USHELL_SIZE_CMD_LINE; u16_i++)
01061          {
01062             g_s_arg[0][u16_i-2]=g_s_arg[0][u16_i];
01063          }
01064       }
01065    }
01066    
01067    //** Print files list
01068    printf("          Size  Name\n\r");
01069    // Init loop at the begining of directory
01070    nav_filelist_reset();
01071    u16_nb_file=0;
01072    u16_nb_dir=0;
01073    last_i=0;
01074    // For each file in list
01075    while( nav_filelist_set(0,FS_FIND_NEXT) )
01076    {  
01077       if(!ext_filter)
01078       {
01079          // No extension filter
01080          if( nav_file_isdir() )
01081          {
01082             printf("Dir ");
01083             u16_nb_dir++;              // count the number of directory
01084          }else{
01085             printf("    ");
01086          }
01087       }
01088       else
01089       {
01090          // If extension filter then ignore directories
01091          if(nav_file_isdir())
01092             continue;
01093          // Check extension
01094          if(!nav_file_checkext((FS_STRING)g_s_arg[0]))
01095             continue;
01096       }
01097       u16_nb_file++;                   // count the total of files (directories and files)
01098 
01099       // Check 'more' step
01100       if( b_more && ((u16_nb_file%USHELL_NB_LINE)==0) && (u16_nb_file!=0) && (last_i != u16_nb_file) )
01101       {
01102          last_i=u16_nb_file;
01103          if( !ushell_more_wait() )
01104             return;  // Exit LS command
01105       }
01106       
01107       // Display file
01108       nav_file_name((FS_STRING)str_char, MAX_FILE_LENGHT, FS_NAME_GET, TRUE);
01109       printf("%10lu  %s\n\r", nav_file_lgt(), str_char);
01110    }
01111    // Display total number
01112    printf(" %4i Files\r\n", u16_nb_file-u16_nb_dir );
01113    printf(" %4i Dir\r\n", u16_nb_dir );
01114 }
01115 
01116 
01119 void ushell_cmd_cd( void )
01120 { 
01121    if( g_s_arg[0][0] == 0 )
01122       return;
01123    
01124    // Add '\' at the end of path, else the nav_setcwd select the directory but don't enter into.
01125    ushell_path_valid_syntac( g_s_arg[0] );
01126    
01127    // Call file system routine
01128    if( nav_setcwd((FS_STRING)g_s_arg[0],TRUE,FALSE) == FALSE )
01129    {
01130       print_msg((U8 code *)msg_er_unknown_file);
01131    }
01132 }
01133 
01134 
01137 void ushell_cmd_gotoparent( void )
01138 {
01139    nav_dir_gotoparent();
01140 }
01141 
01142 
01149 void ushell_cmd_cat( Bool b_more)
01150 {
01151    char c_file_character;
01152    U8 n_line=0;
01153    
01154    if( g_s_arg[0][0] == 0 )
01155       return;
01156    
01157    // Select file
01158    if( !nav_setcwd((FS_STRING)g_s_arg[0],TRUE,FALSE) )
01159    {
01160       print_msg((U8 code *)msg_er_unknown_file);
01161       return;
01162    }
01163      
01164    // Open file
01165    file_open(FOPEN_MODE_R);
01166    while (file_eof()==FALSE)
01167    {
01168       // Check 'more' option
01169       if( b_more && (n_line >= USHELL_NB_LINE))
01170       {
01171          n_line = 0;
01172          if( !ushell_more_wait() )
01173             break;   // Stop cat command
01174       }
01175 
01176       // Display a character
01177       c_file_character = file_getc();
01178       ushell_putchar( c_file_character );
01179 
01180       // Count the line number
01181       if (c_file_character==ASCII_LF)
01182          n_line++;
01183    }
01184    file_close();
01185 
01186    // Jump in a new line
01187    ushell_putchar(ASCII_CR);ushell_putchar(ASCII_LF);
01188 }
01189 
01190 
01193 void ushell_cmd_help( void )
01194 {
01195    print_msg((U8 code *)msg_help);
01196 }
01197 
01198 
01201 void ushell_cmd_mkdir( void )
01202 {
01203    if( g_s_arg[0][0] == 0 )
01204       return;
01205    
01206    if( !nav_dir_make((FS_STRING)g_s_arg[0]) )
01207       print_msg((U8 code *)msg_ko);      
01208 }
01209 
01210 
01213 void ushell_cmd_touch( void )
01214 {
01215    if( g_s_arg[0][0] == 0 )
01216       return;
01217    
01218    nav_file_create((FS_STRING)g_s_arg[0]);
01219 }
01220 
01221 
01224 void ushell_cmd_rm( void )
01225 {
01226    U8 u8_i = 0;
01227    Fs_index sav_index;
01228 
01229    if( g_s_arg[0][0] == 0 )
01230       return;
01231    
01232    // Save the position
01233    sav_index = nav_getindex();
01234    
01235    while( 1 )
01236    {
01237       // Restore the position
01238       nav_gotoindex(&sav_index);
01239       // Select file or directory
01240       if( !nav_setcwd( (FS_STRING)g_s_arg[0], TRUE, FALSE ) )
01241          break;
01242       // Delete file or directory
01243       if( !nav_file_del( FALSE ) )
01244       {
01245          print_msg((U8 code *)msg_ko);      
01246          break;
01247       }
01248       u8_i++;
01249    }
01250    printf( "%u file(s) deleted\n\r", u8_i );
01251 }
01252 
01253 
01260 void ushell_cmd_append_file( void )
01261 {
01262    char c_key;
01263   
01264    if( g_s_arg[0][0] == 0 )
01265       return;
01266    
01267    // Select file or directory
01268    if( !nav_setcwd( (FS_STRING)g_s_arg[0], TRUE, FALSE ) )
01269    {
01270       print_msg((U8 code *)msg_er_unknown_file);
01271       return;
01272    }
01273    // Open file
01274    if( !file_open(FOPEN_MODE_APPEND) )
01275    {
01276       print_msg((U8 code *)msg_ko);
01277       return;
01278    }
01279 
01280    // Append file
01281    print_msg((U8 code *)msg_append_welcome);
01282    while( 1 )
01283    {
01284       c_key = ushell_get_char();
01285 
01286       if( c_key == ASCII_CTRL_Q )
01287          break;   // ^q to quit
01288       
01289       ushell_putchar( c_key );
01290       file_putc( c_key );
01291       if( c_key == ASCII_CR )
01292       {
01293          ushell_putchar(ASCII_LF);
01294          file_putc(ASCII_LF);
01295       }
01296    }
01297 
01298    // Close file
01299    file_close();
01300    ushell_putchar(ASCII_CR); ushell_putchar(ASCII_LF);
01301 }
01302 
01303 
01306 void ushell_cmd_copy( void )
01307 {
01308    Fs_index sav_index;
01309    U8 u8_status_copy;
01310 
01311    if( g_s_arg[0][0] == 0 )
01312       return;
01313    
01314    // Save the position
01315    sav_index = nav_getindex();
01316    
01317    // Select source file
01318    if( !nav_setcwd( (FS_STRING)g_s_arg[0], TRUE, FALSE ) )
01319    {
01320       print_msg((U8 code *)msg_er_unknown_file);
01321       return;
01322    }
01323    // Get name of source to be used as same destination name
01324    nav_file_name( (FS_STRING)g_s_arg[0], MAX_FILE_LENGHT, FS_NAME_GET, TRUE );              
01325    // Mark this selected file like source file
01326    if( !nav_file_copy())
01327    {
01328       print_msg((U8 code *)msg_ko);
01329       goto cp_end;
01330    }
01331 
01332    // Select destination
01333    if( g_s_arg[1][0]==0 )
01334    {
01335       // g_s_arg[1] is NULL, using mark
01336       if( !nav_gotoindex(&g_mark_index) )
01337          goto cp_end;
01338    }
01339    else
01340    {
01341       // g_s_arg[1] exists, then go to this destination
01342       if( !nav_setcwd( (FS_STRING)g_s_arg[1], TRUE, FALSE ) )
01343       {
01344          print_msg((U8 code *)msg_er_unknown_file);
01345          goto cp_end;
01346       }
01347    }
01348    
01349    // Set the name destination and start paste
01350    if( !nav_file_paste_start((FS_STRING)g_s_arg[0]) )
01351    {
01352       print_msg((U8 code *)msg_paste_fail);
01353       goto cp_end;
01354    }
01355    
01356    // Performs copy
01357    do
01358    {
01359       u8_status_copy = nav_file_paste_state( FALSE );
01360    }while( u8_status_copy == COPY_BUSY );
01361 
01362    // Check status of copy action
01363    if( u8_status_copy == COPY_FAIL )
01364    {
01365       print_msg((U8 code *)msg_paste_fail);
01366       goto cp_end;
01367    }
01368 
01369 cp_end:
01370    // Restore the position
01371    nav_gotoindex(&sav_index);
01372 }
01373 
01374 
01377 void ushell_cmd_rename( void )
01378 {
01379    if( g_s_arg[0][0] == 0 )
01380       return;
01381    if( g_s_arg[1][0] == 0 )
01382       return;
01383    
01384    // Select source file
01385    if( !nav_setcwd( (FS_STRING)g_s_arg[0], TRUE, FALSE ) )
01386    {
01387       print_msg((U8 code *)msg_er_unknown_file);
01388       return;
01389    }
01390    // Rename file or directory
01391    if( !nav_file_rename( (FS_STRING)g_s_arg[1] ) )
01392    {
01393       print_msg((U8 code *)msg_ko);
01394       return;
01395    }
01396 }
01397 
01398 
01403 Bool ushell_cmd_sync( void )
01404 {
01405    Fs_index sav_index;
01406    U8 u8_folder_level = 0;
01407 
01408    if( g_s_arg[0][0] == 0 )
01409       return FALSE;
01410    if( g_s_arg[1][0] == 0 )
01411       return FALSE;
01412    // Add '\' at the end of path, else the nav_setcwd select the directory but don't enter into.
01413    ushell_path_valid_syntac( g_s_arg[0] );
01414    ushell_path_valid_syntac( g_s_arg[1] );
01415    
01416    printf("Synchronize folders:\n\r");
01417    sav_index = nav_getindex();   // Save the position
01418    
01419    // Select source directory in COPYFILE navigator handle
01420    nav_select( FS_NAV_ID_COPYFILE );
01421    printf("Select source directory\n\r");
01422    if( !nav_setcwd( (FS_STRING)g_s_arg[0], TRUE, FALSE ) )
01423       goto ushell_cmd_sync_error;
01424    nav_filelist_reset();
01425 
01426    // Select destination directory in USHELL navigator handle
01427    nav_select( FS_NAV_ID_USHELL_CMD );
01428    printf("Select destination directory\n\r");
01429    if( !nav_setcwd( (FS_STRING)g_s_arg[1], TRUE, TRUE ) )
01430       goto ushell_cmd_sync_error;
01431    nav_filelist_reset();
01432 
01433    // loop to scan and create ALL folders and files
01434    while(1)
01435    {
01436       while(1)
01437       {
01438          // Loop to Search files or directories
01439          // Reselect Source
01440          nav_select( FS_NAV_ID_COPYFILE );
01441          if( nav_filelist_set( 0 , FS_FIND_NEXT ) )
01442             break;   // a next file and directory is found
01443    
01444          // No other dir or file in current dir then go to parent dir on Source and Destination disk
01445          if( 0 == u8_folder_level )
01446          {
01447             // end of update folder
01448             //********* END OF COPY **************
01449             goto ushell_cmd_sync_finish;
01450          }
01451 
01452          printf("Go to parent\n\r");
01453          // Remark, nav_dir_gotoparent() routine go to in parent dir and select the children dir in list
01454          u8_folder_level--;
01455          if( !nav_dir_gotoparent() )
01456             goto ushell_cmd_sync_error;
01457          // Select Destination navigator and go to the same dir of Source
01458          nav_select( FS_NAV_ID_USHELL_CMD );
01459          if( !nav_dir_gotoparent() )
01460             goto ushell_cmd_sync_error;
01461       } // end of while (1)
01462       
01463       if( nav_file_isdir())
01464       {
01465          printf("Dir found - create dir: ");
01466          //** here, a new directory is found and is selected
01467          // Get name of current selection (= dir name on Source)
01468          if( !nav_file_name( (FS_STRING)g_s_arg[0], USHELL_SIZE_CMD_LINE, FS_NAME_GET, FALSE ))
01469             goto ushell_cmd_sync_error;
01470          // Enter in dir (on Source)
01471          if( !nav_dir_cd())
01472             goto ushell_cmd_sync_error;
01473          u8_folder_level++;
01474          // Select Destination disk
01475          nav_select( FS_NAV_ID_USHELL_CMD );
01476          // Create folder in Destination disk
01477          printf((char*)g_s_arg[0]);
01478          printf("\n\r");
01479          if( !nav_dir_make( (FS_STRING )g_s_arg[0] ))
01480          {
01481             if( FS_ERR_FILE_EXIST != fs_g_status )
01482                goto ushell_cmd_sync_error;
01483             // here, error the name exist
01484          }
01485          // Here the navigator have selected the folder on Destination
01486          if( !nav_dir_cd())
01487          {
01488             if( FS_ERR_NO_DIR == fs_g_status )
01489             {
01490                // FYC -> Copy impossible, because a file have the same name of folder
01491             }
01492             goto ushell_cmd_sync_error;
01493          }
01494          // here, the folder is created and the navigatorS is entered in this dir
01495       }
01496       else
01497       {
01498          printf("File found - copy file: ");
01499          //** here, a new file is found and is selected
01500          // Get name of current selection (= file name on Source)
01501          if( !nav_file_name( (FS_STRING)g_s_arg[0], USHELL_SIZE_CMD_LINE, FS_NAME_GET, FALSE ))
01502             goto ushell_cmd_sync_error;
01503          printf((char*)g_s_arg[0]);
01504          printf("\n\r");
01505          if( !nav_file_copy())
01506             goto ushell_cmd_sync_error;
01507 
01508          // Paste file in current dir of Destination disk
01509          nav_select( FS_NAV_ID_USHELL_CMD );
01510          while( !nav_file_paste_start( (FS_STRING)g_s_arg[0] ) )
01511          {
01512             // Error
01513             if( fs_g_status != FS_ERR_FILE_EXIST )
01514                goto ushell_cmd_sync_error;
01515             // File exists then deletes this one
01516             printf("File exists then deletes this one.\n\r");
01517             if( !nav_file_del( TRUE ) )
01518                goto ushell_cmd_sync_error;
01519             // here, retry PASTE                   
01520          }
01521          // Copy running
01522          {
01523          U8 status;
01524          do{
01525             status = nav_file_paste_state(FALSE);
01526          }while( COPY_BUSY == status );
01527 
01528          if( COPY_FINISH != status )
01529             goto ushell_cmd_sync_error;
01530          }
01531       } // if dir OR file
01532    } // end of first while(1)
01533  
01534 ushell_cmd_sync_error:
01535    // Restore the position
01536    nav_select( FS_NAV_ID_USHELL_CMD );
01537    nav_gotoindex(&sav_index);
01538    printf("!!!Copy fail\n\r");
01539    return FALSE;
01540    
01541 ushell_cmd_sync_finish:
01542    // Restore the position
01543    nav_select( FS_NAV_ID_USHELL_CMD );
01544    nav_gotoindex(&sav_index);
01545    printf("End of copy\n\r");
01546    return TRUE;
01547 }
01548 
01549 // File alloc space (unit sector 512B)
01550 #define  FILE_ALLOC_SIZE      ((1024*1024L)/512L)      // 1MB
01551 
01552 Fs_file_segment ushell_cmd_perform_alloc( U8 lun, U16 size_alloc )
01553 {
01554    const FS_STRING file_tmp_name = "tmp.bin";
01555    Fs_file_segment g_recorder_seg;   
01556    g_recorder_seg.u16_size = 0;   
01557 
01558    if( !nav_drive_set(lun))
01559       return g_recorder_seg;
01560 
01561    if( !nav_partition_mount() )
01562       return g_recorder_seg;
01563 
01564    if( !nav_file_create((FS_STRING)file_tmp_name))
01565    {
01566       if( FS_ERR_FILE_EXIST != fs_g_status)
01567          return g_recorder_seg;
01568       nav_file_del(FALSE);
01569       if( !nav_file_create((FS_STRING)file_tmp_name))
01570          return g_recorder_seg;
01571    }
01572    // Open file
01573    if( !file_open(FOPEN_MODE_W) )
01574    {
01575       nav_file_del(FALSE);
01576       return g_recorder_seg;
01577    }
01578    // Define the size of segment to alloc (unit 512B)
01579    // Note: you can alloc more in case of you don't know total size
01580    g_recorder_seg.u16_size = size_alloc;   
01581    // Alloc in FAT a cluster list equal or inferior at segment size
01582    if( !file_write( &g_recorder_seg ))
01583    {
01584       g_recorder_seg.u16_size = 0;   
01585       file_close();
01586       nav_file_del(FALSE);
01587    }
01588    return g_recorder_seg;   //** File open and FAT allocated
01589 }
01590 
01591 void ushell_cmd_perform_transfer( Fs_file_segment seg_src, Fs_file_segment seg_dest )
01592 {
01593    U8 id_trans_memtomem;
01594    Ctrl_status status_stream;
01595    U16 u16_i, u16_ctn, u16_trans_max;
01596    U32 u32_tmp;
01597    
01598    Timer16_set_waveform_mode(TIMER16_COMP_MODE_NORMAL);
01599    Timer16_set_clock(TIMER16_CLKIO_BY_1024); // 8MHz / 1024
01600    u16_trans_max = ( seg_src.u16_size < seg_dest.u16_size )?  seg_src.u16_size : seg_dest.u16_size;
01601    for( u16_ctn=0,u16_i=2; u16_i<=u16_trans_max; u16_i*=10 )
01602    {
01603       Timer16_clear_overflow_it();
01604       Timer16_set_counter(0);
01605       id_trans_memtomem = stream_mem_to_mem( seg_src.u8_lun , seg_src.u32_addr , seg_dest.u8_lun , seg_dest.u32_addr , u16_i );
01606       if( ID_STREAM_ERR == id_trans_memtomem )
01607       {
01608          printf( "Transfert error\r\n");
01609          return;
01610       }
01611       while(1)
01612       {
01613          status_stream = stream_state( id_trans_memtomem );
01614          if( CTRL_BUSY == status_stream ) continue;
01615          if( CTRL_GOOD == status_stream ) break;
01616          if( CTRL_FAIL == status_stream ) {
01617             printf( "Transfert error\r\n");
01618             return;
01619          }
01620       }
01621       u16_ctn = Timer16_get_counter();
01622       if( Timer16_get_overflow_it() )
01623       {
01624          // Counter too small to get time
01625          if( 1 == u16_i )
01626             printf( "Transfert too slow\r\n");
01627          break;
01628       }
01629       u32_tmp = ((U32)u16_i*1000)/((2*(U32)u16_ctn*1024)/8000);
01630       printf( "Transfert rate %4luKB/s - stream size %4iKB\r\n", u32_tmp, u16_i/2 );
01631    }
01632 }
01633 
01634 void ushell_cmd_perform_access( Bool b_sens_write, Fs_file_segment seg )
01635 {
01636    U32 u32_tmp;
01637    U16 u16_trans,u16_ctn;
01638    
01639    fat_cache_flush();
01640    fat_cache_reset();
01641    Timer16_set_waveform_mode(TIMER16_COMP_MODE_NORMAL);
01642    Timer16_set_clock(TIMER16_CLKIO_BY_1024); // 8MHz / 1024
01643    Timer16_clear_overflow_it();
01644    Timer16_set_counter(0);
01645    for( u16_ctn=0,u16_trans=0; u16_trans<seg.u16_size; u16_trans++ )
01646    {         
01647       if( b_sens_write )
01648       {
01649          if( CTRL_GOOD != ram_2_memory( seg.u8_lun , seg.u32_addr , fs_g_sector )) {
01650             printf( "Transfert error\r\n");
01651             return;
01652          }
01653       }else{
01654          if( CTRL_GOOD != memory_2_ram( seg.u8_lun , seg.u32_addr , fs_g_sector )) {
01655             printf( "Transfert error\r\n");
01656             return;
01657          }
01658       }
01659       seg.u32_addr++;
01660       if( Timer16_get_overflow_it() )
01661          break;
01662       u16_ctn = Timer16_get_counter();
01663    }
01664    u32_tmp = ((U32)u16_trans*1000)/((2*(U32)u16_ctn*1024)/8000);
01665    if( b_sens_write )
01666       printf( "Transfert rate - WRITE %4luKB/s\r\n", u32_tmp );
01667    else
01668       printf( "Transfert rate - READ %4luKB/s\r\n", u32_tmp );
01669 }
01670 
01671 #ifndef USHELL_SIZE_OF_EXT_BUFFER_TO_PERF_CMD
01672 #warning Define USHELL_SIZE_OF_EXT_BUFFER_TO_PERF_CMD in config.h file
01673 #endif
01674 
01675 static   U8  u8_ext_buffer[512*USHELL_SIZE_OF_EXT_BUFFER_TO_PERF_CMD];
01676 
01677 void ushell_cmd_perform_extaccess( Bool b_sens_write, Fs_file_segment seg )
01678 {
01679    U16 u16_trans,u16_ctn;
01680    U32 u32_tmp;
01681    U8  u8_nb_trans_usb=0;
01682    
01683    fat_cache_flush();
01684    fat_cache_reset();
01685 
01686    Timer16_set_waveform_mode(TIMER16_COMP_MODE_NORMAL);
01687    Timer16_set_clock(TIMER16_CLKIO_BY_1024); // 8MHz / 1024
01688    Timer16_clear_overflow_it();
01689    Timer16_set_counter(0);
01690 
01691    u16_trans=u16_ctn=0;
01692    while( seg.u16_size!=0 )
01693    {         
01694       if( 0 == (seg.u32_addr % USHELL_SIZE_OF_EXT_BUFFER_TO_PERF_CMD) )
01695       {
01696          u8_nb_trans_usb = USHELL_SIZE_OF_EXT_BUFFER_TO_PERF_CMD;
01697       }else{
01698          u8_nb_trans_usb = USHELL_SIZE_OF_EXT_BUFFER_TO_PERF_CMD - (seg.u32_addr % USHELL_SIZE_OF_EXT_BUFFER_TO_PERF_CMD);  // to align access with usual memory mapping
01699       }
01700       if (u8_nb_trans_usb > seg.u16_size)
01701         u8_nb_trans_usb = seg.u16_size;
01702       
01703       if( b_sens_write )
01704       {
01705          if( CTRL_GOOD != host_mem_ram_2_mem_ext( seg.u8_lun-LUN_ID_USB, seg.u32_addr , u8_ext_buffer, u8_nb_trans_usb )) {
01706             printf( "Transfert error\r\n");
01707             return;
01708          }
01709       }else{        
01710          if( CTRL_GOOD != host_mem_mem_2_ram_ext( seg.u8_lun-LUN_ID_USB, seg.u32_addr , u8_ext_buffer, u8_nb_trans_usb )) {
01711             printf( "Transfert error\r\n");
01712             return;
01713          }
01714       }
01715       
01716       if( Timer16_get_overflow_it() )
01717       {
01718          break;
01719       }
01720 
01721       u16_ctn = Timer16_get_counter();
01722       seg.u16_size -= u8_nb_trans_usb;
01723       u16_trans    += u8_nb_trans_usb;
01724       seg.u32_addr += u8_nb_trans_usb;
01725    }
01726    u32_tmp = ((U32)u16_trans*1000)/((2*(U32)u16_ctn*1024)/8000);
01727    if( b_sens_write )
01728       printf( "Transfert rate - WRITE %4luKB/s\r\n", u32_tmp);
01729    else
01730       printf( "Transfert rate - READ %4luKB/s\r\n", u32_tmp );
01731 }
01732 
01733 
01736 void ushell_cmd_perform( void )
01737 {
01738    Fs_index sav_index;
01739    Fs_file_segment seg1, seg2;
01740 
01741    if( g_s_arg[0][0] == 0 )
01742       return;
01743    
01744    sav_index = nav_getindex();   // Save the position
01745    
01746    // Alloc a file on each devices
01747    printf("Alloc a file on each devices\n\r");
01748    seg1 = ushell_cmd_perform_alloc( (g_s_arg[0][0]-'a') , FILE_ALLOC_SIZE );
01749    if( seg1.u16_size == 0 )
01750    {
01751       printf("!!!Error allocation on device 1\n\r");
01752       // Restore the position
01753       nav_gotoindex(&sav_index);
01754       return;
01755    }
01756    if( g_s_arg[1][0] != 0 )
01757    {
01758       nav_select( FS_NAV_ID_COPYFILE );
01759       seg2 = ushell_cmd_perform_alloc( (g_s_arg[1][0]-'a') , FILE_ALLOC_SIZE );
01760       if( seg2.u16_size == 0 )
01761       {
01762          nav_select( FS_NAV_ID_USHELL_CMD );   
01763          file_close();
01764          nav_file_del(FALSE);
01765          printf("!!!Error allocation on device 2\n\r");
01766          // Restore the position
01767          nav_gotoindex(&sav_index);
01768          return;
01769       }   
01770       
01771       // Transfert data from device 1 to device 2
01772       printf("Transfert data from device 1 to device 2\r\n");
01773       ushell_cmd_perform_transfer(seg1,seg2);
01774       printf("Transfert data from device 2 to device 1\r\n");
01775       ushell_cmd_perform_transfer(seg2,seg1);
01776       // Delete files allocated
01777       nav_select( FS_NAV_ID_COPYFILE );   
01778       file_close();
01779       nav_file_del(FALSE);
01780       nav_select( FS_NAV_ID_USHELL_CMD );
01781    }
01782    else
01783    {
01784       ushell_cmd_perform_access( FALSE, seg1 );
01785       ushell_cmd_perform_access( TRUE, seg1 );
01786       if( LUN_ID_USB <= nav_drive_get() )
01787       {
01788          printf("Transfert large buffer on USB\r\n");
01789          ushell_cmd_perform_extaccess( FALSE, seg1 );
01790          ushell_cmd_perform_extaccess( TRUE, seg1 );
01791       }
01792       
01793    }
01794    
01795    file_close();
01796    nav_file_del(FALSE);
01797    // Restore the position
01798    nav_gotoindex(&sav_index);
01799    printf("End of test\n\r");
01800    return;   
01801 }
01802 
01803 
01804 
01805 
01808 void ushell_path_valid_syntac( char *path )
01809 {
01810    U8 u8_tmp;
01811    
01812    // Compute size of substitute
01813    for( u8_tmp=0; u8_tmp<MAX_FILE_LENGHT; u8_tmp++ )
01814    {
01815       if( path[u8_tmp]==0)
01816          break;
01817    }
01818    // Append the '\' char for the nav_setcwd to enter the found directory
01819    if ( path[u8_tmp-1] != '\\')
01820    {
01821       path[u8_tmp]='\\';
01822       path[u8_tmp+1]=0;
01823    }
01824 }
01825 
01826 
01829 void ushell_cmd_reboot( void )
01830 {
01831    // Reset SPI interface
01832 #ifdef SPIDER_ADC_BRIDGE
01833    #if (TARGET_BOARD==SPIDER)
01834    SPI_InterMCU_Ready();
01835    Spider_bridge_reset();
01836    SPI_InterMCU_Suspend();
01837    #endif
01838 #endif
01839    // Enable watch dog
01840    wdtdrv_enable(WDTO_16MS);
01841    // Wait watch dog event
01842    while(1);
01843 }
01844 
01845 
01846 #if (USHELL_USB==ENABLE)
01851 void ushell_cmdusb_ls(void)
01852 {
01853    U8 i,j,n,s;
01854 
01855    // Check USB host status
01856    if( (!Is_host_ready()) && (!Is_host_suspended()) )
01857    {
01858       print_msg((U8 code *)msg_no_device);
01859       return;
01860    }
01861    if( Is_host_suspended() )
01862    {
01863       print_msg((U8 code *)msg_usb_suspended);
01864    }
01865    
01866    s = selected_device;
01867    for( n=0; n<Get_nb_device(); n++ )
01868    {
01869       Host_select_device(n);
01870       printf("\n\rDevice %i @:0x%02X\n\r",n+1,usb_tree.device[selected_device].device_address);
01871       printf("VID:%04X, PID:%04X, ",Get_VID(),Get_PID());
01872       printf("MaxPower is %imA, ",2*Get_maxpower());
01873       if (Is_device_self_powered())
01874       {  print_msg((U8 code *)msg_device_self_powered); }
01875       else
01876       {  print_msg((U8 code *)msg_device_bus_powered); }
01877       printf("Control Endpoint is %i bytes, ",Get_ep0_size()); 
01878       if (Is_host_full_speed())
01879       {  print_msg((U8 code *)msg_device_full_speed); }
01880       else
01881       {  print_msg((U8 code *)msg_device_low_speed); }
01882       if (Is_device_supports_remote_wakeup())
01883       {  print_msg((U8 code *)msg_remote_wake_up_ok); }
01884       else
01885       {  print_msg((U8 code *)msg_remote_wake_up_ko); }
01886       printf("Supported interface(s):%02i\n\r",Get_nb_supported_interface());
01887       for(i=0;i<Get_nb_supported_interface();i++)
01888       {
01889          printf("Interface nb:%02i, AltS nb:%02i, Class:%02i, SubClass:%02i, Protocol:%02i\n\r",\
01890             Get_interface_number(i), Get_alts_s(i), Get_class(i), Get_subclass(i), Get_protocol(i));
01891          printf(" Endpoint(s) Addr:");
01892          if(Get_nb_ep(i))
01893          {
01894             for(j=0;j<Get_nb_ep(i);j++)
01895             {
01896                printf(" %02X", Get_ep_addr(i,j));
01897             }
01898          }
01899          else
01900          {
01901             printf("None");
01902          }
01903          ushell_putchar(ASCII_CR);ushell_putchar(ASCII_LF);
01904          printf(" Physical pipe(s):");
01905          if(Get_nb_ep(i))
01906          {
01907             for(j=0;j<Get_nb_ep(i);j++)
01908             {
01909                printf(" %02X", usb_tree.device[selected_device].interface[i].ep[j].pipe_number);
01910             }
01911          }
01912          else
01913          {
01914             printf("None");
01915          }
01916          ushell_putchar(ASCII_CR);ushell_putchar(ASCII_LF);         
01917       }
01918    }
01919    selected_device=s;
01920 }
01921 
01924 void ushell_cmdusb_suspend(void)
01925 {
01926    if( !Is_host_ready() )
01927    {
01928       print_msg((U8 code *)msg_no_device);
01929    }
01930    Host_request_suspend();
01931 }
01932 
01935 void ushell_cmdusb_resume(void)
01936 {
01937    if( !Is_host_suspended() )
01938    {
01939       print_msg((U8 code *)msg_no_device);
01940    }
01941    Host_request_resume();
01942 }
01943 
01944 
01947 void ushell_cmdusb_force_enum(void)
01948 {
01949    if( !Is_host_ready() )
01950    {
01951       print_msg((U8 code *)msg_no_device);
01952    }
01953    Host_force_enumeration();
01954 }
01955 #endif //USHELL_USB==ENABLE
01956 
01957 
01958 #if (USHELL_DFU==ENABLE)
01961 void ushell_cmddfu_erase( void )
01962 {
01963    if( !Is_dfu_connected() )
01964    {
01965       print_msg((U8 code *)msg_no_device);
01966       return;
01967    }
01968    Dfu_erase();
01969 }
01970 
01973 void ushell_cmddfu_load( void )
01974 {
01975    if( !Is_dfu_connected() )
01976    {
01977       print_msg((U8 code *)msg_no_device);
01978       return;
01979    }
01980    // Select source file
01981    if( !nav_setcwd( (FS_STRING)g_s_arg[0], TRUE, FALSE ) )
01982    {
01983       print_msg((U8 code *)msg_er_unknown_file);
01984       return;
01985    }
01986    Dfu_erase();
01987    if( !dfu_load_hex() )
01988    {
01989       print_msg((U8 code *)msg_ko);
01990       return;
01991    }
01992    print_msg((U8 code *)msg_ok);
01993 }
01994 
01997 void ushell_cmddfu_start( void )
01998 {
01999    if( !Is_dfu_connected() )
02000    {
02001       print_msg((U8 code *)msg_no_device);
02002       return;
02003    }
02004    Dfu_start_appli();
02005 }
02006 #endif   // (USHELL_DFU==ENABLE)
02007 
02008 
02009 #if (USHELL_HID==ENABLE)
02012 void ushell_cmdhid_enter_dfu(void)
02013 {
02014    if( !Is_hid_connected() )
02015    {
02016       print_msg((U8 code *)msg_no_device);
02017    }
02018    Hid_send_enter_dfu();
02019 }
02020 
02023 void ushell_cmdhid_getinfo(void)
02024 {
02025    if( !Is_hid_connected() )
02026    {
02027       print_msg((U8 code *)msg_no_device);
02028       return;
02029    }         
02030 #if( HID_GENERIC_DEMO_FULL == ENABLE )         
02031    printf("Temperature %i C\n\r",Hid_get_temperature());
02032    printf("Potentiometer %i\n\r",Hid_get_potentiometer());
02033 #else
02034    printf("No data available with this HID generic configuration.\n\r");
02035 #endif
02036 }
02037 #endif // (USHELL_HID==ENABLE)
02038 
02039 
02040 #ifdef   LOG_STR_CODE
02045 extern void ushell_trace_msg(U8 code *str)
02046 {
02047    ushell_putchar(CR);
02048    ushell_putchar(LF);
02049    print_msg((U8 code *)str);
02050    ushell_putchar(CR);
02051    ushell_putchar(LF);
02052    print_msg((U8 code *)msg_prompt);
02053 }
02054 #endif
02055 

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