/* Compiler: BC++ 3.1, Turbo C++ 1.01 (3.01) Compile mode: large Project: SD_QA.c ..\..\lib\upac5000.lib ..\lib\sd_vnnn.lib Hardware: uPAC-5000 [2008,09,18] by Kevin first released. [2008,09,21] by Kevin bug fixed 1. do_rm Problem:can not perform command like "rm *.*" in a sub directory. Reason: In the pc_gnext loop, the file name given to pc_del should be simeple file name (like: test1.txt) or with full path (like: a:\demo\text1.exe) statobj.path gives empty path. that makes following code error. sprintf(fullfilename,"%s\\%s",statobj.path,statobj.filename); Solution: the correct code should be following sprintf(fullfilename,"%s",statobj.filename); */ #include #include #include #include "..\..\Lib\uPAC5000.h" #include "..\lib\microSD.h" char Prompt[20]="\r\nMicroSD>"; unsigned char shell_buf[1024]; char working_buf[100]; // used by lex: must be global typedef struct dispatcher { char *cmd; int (*proc)( int argc, char **argv); char *helpstr; } DISPATCHER; DISPATCHER *lex(void); int do_quit(int agc, char **agv); int do_help(int agc, char **agv); int do_mkdir(int agc, char **agv); int do_rmdir(int agc, char **agv); int do_del(int agc, char **agv); int do_rm(int agc, char **agv); int do_deltree(int agc, char **agv); int do_move(int agc, char **agv); int do_cwd(int agc, char **agv); int do_ls(int agc, char **agv); int do_type(int agc, char **agv); int pc_seedir(char *path); int domkfs(int agc, char **agv); int do_setattr(int agc, char **agv); void prompt_user(char *prompt, char *buf); int do_newCard(int agc, char **agv); DISPATCHER cmds[] = { { "", do_help, ""}, { "CD", do_cwd, "CD PATH or CD to display PWD " }, { "DEL",do_del,"Del File (delete 1 file)"}, { "RM",do_rm, "RM File (delete files)" }, { "DELTREE", do_deltree, "DELTREE PATH"}, { "DIR", do_ls, "DIR PATH" }, { "HELP", do_help, "HELP" }, { "MKDIR", do_mkdir, "MKDIR PATH" }, { "MOVE",do_move, "MOVE filename NEWNAME" }, { "RMDIR", do_rmdir, "RMDIR PATH" }, { "TYPE",do_type,"TYPE filename"}, { "SETATTR", do_setattr, "SETATTR Name RDONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL"}, { "NewCard", do_newCard, "NewCard" }, { "QUIT", 0, "QUIT" }, }; int CmdNumber=sizeof(cmds)/sizeof(DISPATCHER); // ******************************************************************** // THIS IS THE MAIN PROGRAM FOR THE TEST SHELL // ******************************************************************** void DoCommand(void) { DISPATCHER *pcmd; do_help(0, 0); do { pcmd = lex(); if(pcmd) { if(!pcmd->proc) break; pcmd->proc(Argc-1, Argv+1); } else break; } while(1); } void _Gets(char *str) { int cnt=0; int data; unsigned cnt0; for(cnt0=0; ; cnt0++) { if(Kbhit()) { if((data=Getch())=='\r') { *str=0; Putch(data); Putch('\n'); return; } else if(data=='\b') { if(cnt) { str--; cnt--; Putch(data); Putch(' '); Putch('\b'); } } else { Putch(data); *str++=data; cnt++; } } if(cnt0>2000) { cnt0=0; RefreshWDT(); } } } // ******************************************************************** // get next command; process history log void do_prompt(char *working_buf) { Print(Prompt); _Gets(working_buf); } static char *Delimiter=" ,\r\t"; int CmdToArg(char *cmd) { char *cmd1; Argc=0; cmd1=strtok(cmd, Delimiter); while(cmd1) { Argv[Argc]=cmd1; Argc++; cmd1=strtok(NULL,Delimiter); } return Argc; } DISPATCHER *lex(void) { int i; do { do_prompt(working_buf); CmdToArg(working_buf); if(Argc>=1) { for(i=0; i 20) { Print("Press any key"); Getch(); Print("\r\n"); nprinted = 0; } } return 1; } //======== Demo programs bellow ==========================/ /* MKDIR PATH */ int do_mkdir(int agc, char **agv) { if(agc==1) { if(pc_mkdir(*agv)) return (1); return (0); } Print("Usage: MKDIR D:PATH\r\n"); return (0); } /* RMDIR PATH */ int do_rmdir(int agc, char **agv) { Print("\r\n%s ",*agv);DelayMs(0); if(agc == 1) { if(pc_rmdir(*agv)) { Print(":remove dir ok\n\r"); return (1); } else { Print(":remove dir error\n\r"); return(0); } } Print("Usage: RMDIR D:PATH\r\n"); return (0); } /* DELTREE PATH */ int do_deltree(int agc, char **agv) { if(agc==1) { if(pc_deltree(*agv)) { Print("ok\n\r"); return (1); } else { Print("error\n\r"); return(0); } } Print("Usage: DELTREE D:PATH\r\n"); return (0); } /* Delete files */ int do_rm(int agc, char **agv) { DSTAT statobj; char fullfilename[100]; int err; if (agc == 1) { /* Get the path */ strcpy(fullfilename,*agv); //fullfilename can be *.*, *.exe, t*.*, etc. if (pc_gfirst(&statobj,fullfilename)) { do { /* Construct the file name to the current entry */ sprintf(fullfilename,"%s",statobj.filename); if (!pc_isdir(fullfilename) && !pc_isvol(fullfilename)) { if (pc_del( fullfilename ) ) Print("%s deleted.\r\n",fullfilename); else { err=pc_get_errno(); Print("Can not delete: %s, error code=%d\r\n",fullfilename,err); } } } while(pc_gnext(&statobj)); pc_gdone(&statobj); } return(1); } Print("Usage: RM D:PATH\r\n"); return(0); } /* Delete one file */ int do_del(int agc, char **agv) { char filename[15]; int err; if (agc == 1) { /* Get the name */ strcpy(filename,*agv); if (pc_del(filename)) Print("%s deleted.\r\n",filename); else Print("Can not delete: %s\r\n",filename); err=pc_get_errno(); Print("Error code=%d\n\r",err); return(1); } Print("Usage: DEL D:PATH\r\n"); return(0); } /* Move file NEWNAME */ int do_move(int agc, char **agv) { int err; if(agc == 2) { if(pc_move(*agv , *(agv+1) )) return (1); err=pc_get_errno(); if(err==FSERR_EXIST) Print("File or directory already exists\r\n"); else if(err==FSERR_NOSPC) Print("Write failed\r\n"); else if(err==FSERR_NOENT) Print("Directory not found\r\n"); return(0); } Print("Usage: Move File NEWNAME \r\n"); return (0); } /* CD PATH */ int do_cwd(int agc, char **agv) { char lbuff[100]; if(agc==1) { if(pc_set_cwd(*agv)) return(1); Print("?\r\n"); return(0); } else { if (pc_get_cwd(lbuff)) { Print("%s\r\n", lbuff); return(1); } else { Print("?\r\n"); return(0); } } } /* DIR PATH */ int do_ls(int agc, char **agv) { int fcount,iRet; char *ppath; long lTotal, lFree,lUsed; ppath = 0; if (agc == 1) { ppath = *agv; } else { /* get the working dir of the default dir */ if (pc_get_cwd((char *)shell_buf)) { ppath = (char *)shell_buf; Print("path=[%s]\n\r",ppath); /* If not the root add a \\ */ if (!(ppath[1] == '\\' && ppath[2] == '\0')) strcat(ppath, "\\"); strcat(ppath, "*.*"); } } if (ppath) { /* These two lines added to make DIR A: display DIR A:*.* */ if (ppath[1] == ':' && ppath[2] == '\0') strcat(ppath,"*.*"); /* Now do the dir */ fcount = pc_seedir(ppath); Print("%d Files(s)\n\r",fcount); /* And print the bytes remaining */ lTotal=pc_get_totalSize_KB(); lFree=pc_get_freeSize_KB(); Print("total=%ld KB, free=%ld KB\n\r",lTotal,lFree); } else Print("Usage: DIR PATH, error code=%d\r\n",pc_get_errno()); return(1); } /* List directory, and return number of matching file */ int pc_seedir(char *path) { char *dirstr; int fcount = 0; DSTAT statobj; /* Get the first match */ if (pc_gfirst(&statobj, path)) { do { fcount++; Print("%-12s", statobj.filename); if (statobj.fattribute & AVOLUME){ Print(" "); goto bypass; } else if (statobj.fattribute & ADIRENT) Print(" "); else Print(" %10ld ", statobj.fsize); Print("%02d-%02d-%4d",(statobj.fdate >> 5 ) & 0xf, (statobj.fdate & 0x1f),1980+((statobj.fdate >> 9) & 0xff)); /* Date */ Print(" %02d:%02d",(statobj.ftime >> 11) & 0x1f ,(statobj.ftime >> 5) & 0x3f); /* timr */ bypass: Print(" \r\n"); }while(pc_gnext(&statobj)); pc_gdone(&statobj); /* Call gdone to free up internal resources used by statobj */ } return(fcount); } /* Set file attributes*/ int do_setattr(int agc, char **agv) { unsigned char attr; attr = 0; if (agc == 2) { if (!pc_get_attributes(*agv, &attr)) { Print("Can't get attributes\r\n"); return(0); } if (strcmp(*(agv+1),"RDONLY")==0) attr |= ARDONLY; else if (strcmp(*(agv+1),"HIDDEN")==0) attr |= AHIDDEN; else if (strcmp(*(agv+1),"SYSTEM")==0) attr |= ASYSTEM; else if (strcmp(*(agv+1),"ARCHIVE")==0) attr |= ARCHIVE; else if (strcmp(*(agv+1),"NORMAL")==0) attr = ANORMAL; else goto usage; if (pc_set_attributes(*agv, attr)) return(0); else { Print("Set attributes failed\r\n"); return(0); } } usage: Print("Usage: SETATTR D:Name RDONLY|HIDDEN|SYSTEM|ARCHIVE|NORMAL\r\n"); return (0); } int do_type(int agc, char **agv) { int in_fd; word nread; DSTAT statobj; int i,line,newline=1; long lineno=0; if (agc < 1) { Print("Usage: TYPE file_name\r\n"); return(0); } if ((in_fd = pc_open(*agv,(word) (PO_RDONLY),(word) (PS_IWRITE | PS_IREAD) ) ) < 0) { Print("Can't open %s\r\n", *agv); return(0); } line=0; while (1) { nread = (word)pc_read(in_fd,(byte*)shell_buf, 1024); if (nread > 0 && nread != (word)~0) { for(i=0;i=24) { line=0; Print("Anykey to continue...('q' to stop)"); if('q'==Getch()) goto EndType;; Puts("\r\n"); } } } }//if (nread > 0 && nread != (word)~0) else break; }//while (1) EndType: pc_close(in_fd); return(1); } int do_newCard(int agc, char **agv) { int error; if (!pc_ertfs_init()) { Print("Initialize failed\n\r"); error=pc_get_errno(); switch(error) { case PCERR_BAD_FORMAT: //1 Print("Error 01: format is not FAT\n\r"); break; case PCERR_NO_CARD: //2 Print("Error 02: no microSD card\n\r"); break; default: Print("Error %02d:\n\r",error); } } else { Print("Initialize ok.\n\r"); Print("[Disk Size=%ld KB]\n\r",pc_get_totalSize_KB()); } return 1; } void main(void) { int error; unsigned verno; char szDate[20]; InitLib(); pc_getLibDate(szDate); verno=pc_getLibVer(); Print("=============================\n"); Print("microSD libray version: %X.%02X [%s]\n\n", (verno>>8)&0xFF, verno&0xFF, szDate); if(pc_init()) { Print("Initialize ok.\n"); Print("[Disk Size=%ld KB]\n", pc_get_totalSize_KB()); } else { Print("Initialize failed\n"); error=pc_get_errno(); switch(error) { case PCERR_BAD_FORMAT: //1 Print("Error 01: format is not FAT\n"); break; case PCERR_NO_CARD: //2 Print("Error 02: no microSD card\n"); break; default: Print("Error %02d: unknow error\n", error); } } Print("=============================\n\n"); DoCommand(); }