A UNIX emulation shell to access the underlying SDCard FileSystem through a terminal interface

Dependents:   Waldo_Embed_V2

Information

SDShell does not change the com baudrate. Access is made using the baud as initialized by the Serial object when passed into the SDShell object

Example

#include "mbed.h"
#include "SDFileSystem.h"
#include "SDShell.h"

Serial com(USBTX, USBRX);
SDFileSystem sd(p11, p12, p13, p14, "sd");
SDShell emulate;

int main()
{
    emulate.init();
    emulate.shell(com, sd, "/sd");
}
Committer:
sam_grove
Date:
Mon May 06 04:09:32 2013 +0000
Revision:
6:743600852c66
Parent:
5:3417ba8cb1e4
Child:
7:7892fcd8a1ad
Added packetization to bcat

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sam_grove 1:514f321aa528 1
sam_grove 1:514f321aa528 2 //http://mbed.org/users/shimniok/code/SDCardShell/file/792bddcf799d/main.cpp
sam_grove 0:618e98bf18ce 3
sam_grove 0:618e98bf18ce 4 #include "SDShell.h"
sam_grove 0:618e98bf18ce 5
sam_grove 0:618e98bf18ce 6 SDShell::SDShell()
sam_grove 0:618e98bf18ce 7 {
sam_grove 1:514f321aa528 8 _debug = 0;
sam_grove 1:514f321aa528 9
sam_grove 0:618e98bf18ce 10 return;
sam_grove 0:618e98bf18ce 11 }
sam_grove 0:618e98bf18ce 12
sam_grove 0:618e98bf18ce 13 void SDShell::init(void)
sam_grove 0:618e98bf18ce 14 {
sam_grove 1:514f321aa528 15 // add known commands to a linked list
sam_grove 2:b3107e463974 16 _cmds.attachMsg("ls" , this, &SDShell::ls);
sam_grove 2:b3107e463974 17 _cmds.attachMsg("cd" , this, &SDShell::cd);
sam_grove 2:b3107e463974 18 _cmds.attachMsg("pwd" , this, &SDShell::pwd);
sam_grove 2:b3107e463974 19 _cmds.attachMsg("head" , this, &SDShell::head);
sam_grove 2:b3107e463974 20 _cmds.attachMsg("cat" , this, &SDShell::cat);
sam_grove 5:3417ba8cb1e4 21 _cmds.attachMsg("bcat" , this, &SDShell::bcat);
sam_grove 2:b3107e463974 22 _cmds.attachMsg("mkdir", this, &SDShell::create);
sam_grove 2:b3107e463974 23 _cmds.attachMsg("touch", this, &SDShell::touch);
sam_grove 2:b3107e463974 24 _cmds.attachMsg("rm" , this, &SDShell::rm);
sam_grove 2:b3107e463974 25 _cmds.attachMsg("exit" , this, &SDShell::exit);
sam_grove 2:b3107e463974 26 _cmds.attachMsg("debug", this, &SDShell::debug);
sam_grove 2:b3107e463974 27
sam_grove 0:618e98bf18ce 28 return;
sam_grove 0:618e98bf18ce 29 }
sam_grove 0:618e98bf18ce 30
sam_grove 2:b3107e463974 31 void SDShell::shell(Serial &com, SDFileSystem &storage, char const *cwd)
sam_grove 0:618e98bf18ce 32 {
sam_grove 1:514f321aa528 33 uint32_t done = 0;
sam_grove 1:514f321aa528 34
sam_grove 1:514f321aa528 35 // get local copies of the initialized objects
sam_grove 0:618e98bf18ce 36 _com = &com;
sam_grove 1:514f321aa528 37 _storage = &storage;
sam_grove 1:514f321aa528 38
sam_grove 1:514f321aa528 39 // put the current working directory to the root of the card - should be pulled in I think
sam_grove 2:b3107e463974 40 strcpy(_cwd, cwd);
sam_grove 1:514f321aa528 41
sam_grove 1:514f321aa528 42 while(0 == done)
sam_grove 0:618e98bf18ce 43 {
sam_grove 1:514f321aa528 44 // gather input from the Serial object
sam_grove 1:514f321aa528 45 shellInput();
sam_grove 1:514f321aa528 46 // break up the command line arguemnt
sam_grove 2:b3107e463974 47 _arg = split(_cmd, _cmdline, 64, ' ');
sam_grove 1:514f321aa528 48 // look at the arg and get paths and files separated if present
sam_grove 2:b3107e463974 49 resolveDirectory(_newpath, _arg);
sam_grove 2:b3107e463974 50 // print parsed members if we're debugging
sam_grove 1:514f321aa528 51 if(_debug)
sam_grove 1:514f321aa528 52 {
sam_grove 2:b3107e463974 53 LOG("cmdline:<%s> cmd:<%s> arg:<%s> newpath:<%s>\n", _cmdline, _cmd, _arg, _newpath);
sam_grove 1:514f321aa528 54 }
sam_grove 2:b3107e463974 55 // now service known messages
sam_grove 2:b3107e463974 56 char* result = _cmds.serviceMessage(_cmd);
sam_grove 2:b3107e463974 57 // look at the result > 0 means we found somehting
sam_grove 2:b3107e463974 58 if(result == (char *)EXIT)
sam_grove 1:514f321aa528 59 {
sam_grove 2:b3107e463974 60 done = 1; // force an exit
sam_grove 1:514f321aa528 61 }
sam_grove 2:b3107e463974 62 else if (result == (char *)UNKNOWN) // didnt know what that was
sam_grove 1:514f321aa528 63 {
sam_grove 2:b3107e463974 64 uint32_t cnt = 1;
sam_grove 2:b3107e463974 65 LOG("Unknown Message from Terminal: Options are\n");
jekain314 4:6ff0a3d92778 66 do{
sam_grove 2:b3107e463974 67 result = _cmds.messageLookup(cnt++);
sam_grove 2:b3107e463974 68 _com->printf(" %s\n", result);
sam_grove 2:b3107e463974 69 } while(result != NULL);
sam_grove 0:618e98bf18ce 70 }
sam_grove 0:618e98bf18ce 71 else
sam_grove 0:618e98bf18ce 72 {
sam_grove 2:b3107e463974 73 // that should have done something
sam_grove 0:618e98bf18ce 74 }
sam_grove 0:618e98bf18ce 75 }
sam_grove 1:514f321aa528 76 }
sam_grove 0:618e98bf18ce 77
sam_grove 1:514f321aa528 78 void SDShell::shellInput(void)
sam_grove 0:618e98bf18ce 79 {
sam_grove 1:514f321aa528 80 int i=0;
sam_grove 1:514f321aa528 81 char c;
sam_grove 1:514f321aa528 82 uint32_t done = 0;
sam_grove 1:514f321aa528 83 // clear the last command
sam_grove 2:b3107e463974 84 // memset(_cmdline, 0, SHELL_BUF_SIZE);
sam_grove 1:514f321aa528 85 _com->printf("# ", _cwd);
sam_grove 1:514f321aa528 86 do
sam_grove 0:618e98bf18ce 87 {
sam_grove 2:b3107e463974 88 _cmdline[i] = 0; // clearing the next loc before using it is faster than memset
sam_grove 2:b3107e463974 89 c = _com->getc(); // get a char
sam_grove 2:b3107e463974 90 if (c == '\r') // process on "enter"
sam_grove 1:514f321aa528 91 {
sam_grove 1:514f321aa528 92 done = 1;
sam_grove 1:514f321aa528 93 }
sam_grove 2:b3107e463974 94 else if (i < SHELL_BUF_MASK) // once full the user can only press enter
sam_grove 0:618e98bf18ce 95 {
sam_grove 2:b3107e463974 96 if (c == 0x7f) // backspace
sam_grove 2:b3107e463974 97 {
sam_grove 2:b3107e463974 98 if (i > 0) // if we're at the beginning, do nothing
sam_grove 2:b3107e463974 99 {
sam_grove 1:514f321aa528 100 i--;
sam_grove 1:514f321aa528 101 _com->printf("\b \b");
sam_grove 1:514f321aa528 102 }
sam_grove 1:514f321aa528 103 }
sam_grove 2:b3107e463974 104 else // valid keystrokes get stored and echo'd
sam_grove 1:514f321aa528 105 {
sam_grove 1:514f321aa528 106 _com->putc(c);
sam_grove 2:b3107e463974 107 _cmdline[i++] = c;
sam_grove 1:514f321aa528 108 }
sam_grove 0:618e98bf18ce 109 }
sam_grove 2:b3107e463974 110 } while(0 == done);
sam_grove 1:514f321aa528 111
sam_grove 1:514f321aa528 112 _com->printf("\n");
sam_grove 0:618e98bf18ce 113 }
sam_grove 0:618e98bf18ce 114
sam_grove 1:514f321aa528 115 char *SDShell::split(char *dst, char *src, int max, char delim)
sam_grove 0:618e98bf18ce 116 {
sam_grove 1:514f321aa528 117 int i = 0;
sam_grove 1:514f321aa528 118 char *v;
sam_grove 1:514f321aa528 119
sam_grove 1:514f321aa528 120 // make sure pointers are valid (could validate RAM but that should be the caller responsibility)
sam_grove 2:b3107e463974 121 if ((dst == 0) || (src == 0))
sam_grove 1:514f321aa528 122 {
sam_grove 1:514f321aa528 123 return 0;
sam_grove 1:514f321aa528 124 }
sam_grove 2:b3107e463974 125 // break up the string until delim is found
sam_grove 1:514f321aa528 126 while((*src != 0) && (*src != delim) && (i < max))
sam_grove 0:618e98bf18ce 127 {
sam_grove 1:514f321aa528 128 *(dst++) = *(src++);
sam_grove 1:514f321aa528 129 i++;
sam_grove 1:514f321aa528 130 }
sam_grove 2:b3107e463974 131 // return what comes after the delimiter - dst has before the delimiter
sam_grove 2:b3107e463974 132 *dst = 0;
sam_grove 2:b3107e463974 133 v = (*src == '\0') ? dst : (src+1);
sam_grove 1:514f321aa528 134
sam_grove 1:514f321aa528 135 return v;
sam_grove 1:514f321aa528 136 }
sam_grove 1:514f321aa528 137
sam_grove 1:514f321aa528 138 void SDShell::resolveDirectory(char *newpath, char *path)
sam_grove 1:514f321aa528 139 {
sam_grove 1:514f321aa528 140 char basename[64], dirname[64];
sam_grove 1:514f321aa528 141
sam_grove 1:514f321aa528 142 // absolute path
sam_grove 1:514f321aa528 143 if (path[0] == '/')
sam_grove 1:514f321aa528 144 {
sam_grove 1:514f321aa528 145 strcpy(newpath, path);
sam_grove 1:514f321aa528 146 }
sam_grove 1:514f321aa528 147 // relative path
sam_grove 1:514f321aa528 148 else
sam_grove 1:514f321aa528 149 {
sam_grove 1:514f321aa528 150 strcpy(newpath, _cwd);
sam_grove 1:514f321aa528 151 // make sure something was passed
sam_grove 1:514f321aa528 152 if(path[0] != 0)
sam_grove 0:618e98bf18ce 153 {
sam_grove 1:514f321aa528 154 // add the backslash if the user didnt
sam_grove 1:514f321aa528 155 if(newpath[strlen(newpath)-1] != '/')
sam_grove 1:514f321aa528 156 {
sam_grove 1:514f321aa528 157 strcat(newpath, "/");
sam_grove 1:514f321aa528 158 }
sam_grove 1:514f321aa528 159 strcat(newpath, path);
sam_grove 0:618e98bf18ce 160 }
sam_grove 1:514f321aa528 161 // Resolve .. references
sam_grove 1:514f321aa528 162 splitName(newpath, dirname, basename);
sam_grove 1:514f321aa528 163 if (0 == strcmp(basename, ".."))
sam_grove 1:514f321aa528 164 {
sam_grove 1:514f321aa528 165 splitName(dirname, newpath, basename);
sam_grove 1:514f321aa528 166 }
sam_grove 0:618e98bf18ce 167 }
sam_grove 0:618e98bf18ce 168
sam_grove 1:514f321aa528 169 return;
sam_grove 0:618e98bf18ce 170 }
sam_grove 0:618e98bf18ce 171
sam_grove 1:514f321aa528 172 void SDShell::splitName(char *path, char *dirname, char *basename)
sam_grove 1:514f321aa528 173 {
sam_grove 1:514f321aa528 174 int sep = 0;
sam_grove 2:b3107e463974 175 // print the original path
sam_grove 1:514f321aa528 176 if (_debug)
sam_grove 1:514f321aa528 177 {
sam_grove 1:514f321aa528 178 LOG("%d\n", strlen(path));
sam_grove 1:514f321aa528 179 }
sam_grove 2:b3107e463974 180 // find the directory backslash location in the path
sam_grove 1:514f321aa528 181 for (int i=strlen(path)-1; i >= 0; i--)
sam_grove 1:514f321aa528 182 {
sam_grove 2:b3107e463974 183 if (_debug) // print what we found
sam_grove 1:514f321aa528 184 {
sam_grove 1:514f321aa528 185 LOG("- %c\n", path[i]);
sam_grove 1:514f321aa528 186 }
sam_grove 1:514f321aa528 187 sep = i;
sam_grove 1:514f321aa528 188 if (path[i] == '/')
sam_grove 1:514f321aa528 189 {
sam_grove 1:514f321aa528 190 break;
sam_grove 1:514f321aa528 191 }
sam_grove 1:514f321aa528 192 }
sam_grove 2:b3107e463974 193 // extract the directory
sam_grove 2:b3107e463974 194 for (int i=0; i < sep; i++)
sam_grove 1:514f321aa528 195 {
sam_grove 2:b3107e463974 196 if (_debug) // print what we found
sam_grove 1:514f321aa528 197 {
sam_grove 2:b3107e463974 198 LOG("> %c\n", path[i]);
sam_grove 1:514f321aa528 199 }
sam_grove 2:b3107e463974 200 dirname[i] = path[i];
sam_grove 2:b3107e463974 201 dirname[i+1] = 0;
sam_grove 1:514f321aa528 202 }
sam_grove 2:b3107e463974 203 // and then split the file from directory
sam_grove 2:b3107e463974 204 for (int i=sep+1; i < strlen(path); i++)
sam_grove 1:514f321aa528 205 {
sam_grove 2:b3107e463974 206 if (_debug) // print what we found
sam_grove 1:514f321aa528 207 {
sam_grove 2:b3107e463974 208 LOG("* %c\n", path[i]);
sam_grove 1:514f321aa528 209 }
sam_grove 2:b3107e463974 210 basename[i-(sep+1)] = path[i];
sam_grove 2:b3107e463974 211 basename[i-sep] = 0;
sam_grove 1:514f321aa528 212 }
sam_grove 2:b3107e463974 213 if (_debug) // print the the split
sam_grove 1:514f321aa528 214 {
sam_grove 1:514f321aa528 215 LOG("d:<%s> b:<%s>\n", dirname, basename);
sam_grove 1:514f321aa528 216 }
sam_grove 1:514f321aa528 217 }
sam_grove 0:618e98bf18ce 218
sam_grove 2:b3107e463974 219 char *SDShell::ls(char *cmd)
sam_grove 1:514f321aa528 220 {
sam_grove 2:b3107e463974 221 if (_debug)
sam_grove 2:b3107e463974 222 {
sam_grove 2:b3107e463974 223 LOG("%s\n", _cwd);
sam_grove 2:b3107e463974 224 }
sam_grove 2:b3107e463974 225
sam_grove 2:b3107e463974 226 DIR *d = opendir(_newpath);
sam_grove 2:b3107e463974 227 if (NULL != d)
sam_grove 2:b3107e463974 228 {
sam_grove 2:b3107e463974 229 struct dirent *p;
sam_grove 2:b3107e463974 230 while ((p = readdir(d)) != NULL)
sam_grove 2:b3107e463974 231 {
sam_grove 2:b3107e463974 232 _com->printf(" %s\n", p->d_name);
sam_grove 2:b3107e463974 233 }
sam_grove 2:b3107e463974 234 closedir(d);
sam_grove 2:b3107e463974 235 }
sam_grove 2:b3107e463974 236 else
sam_grove 2:b3107e463974 237 {
sam_grove 2:b3107e463974 238 _com->printf("%s: No such directory\n", _newpath);
sam_grove 2:b3107e463974 239 }
sam_grove 2:b3107e463974 240
sam_grove 2:b3107e463974 241 return (char *)OK;
sam_grove 1:514f321aa528 242 }
sam_grove 1:514f321aa528 243
sam_grove 2:b3107e463974 244 char *SDShell::cd(char *cmd)
sam_grove 1:514f321aa528 245 {
sam_grove 2:b3107e463974 246 strcpy(_cwd, _newpath);
sam_grove 2:b3107e463974 247
sam_grove 2:b3107e463974 248 return (char *)OK;
sam_grove 2:b3107e463974 249 }
sam_grove 0:618e98bf18ce 250
sam_grove 2:b3107e463974 251 char *SDShell::pwd(char *path)
sam_grove 2:b3107e463974 252 {
sam_grove 2:b3107e463974 253 _com->printf("%s\n", _cwd);
sam_grove 2:b3107e463974 254
sam_grove 2:b3107e463974 255 return (char *)OK;
sam_grove 1:514f321aa528 256 }
sam_grove 1:514f321aa528 257
sam_grove 2:b3107e463974 258 char *SDShell::head(char *cmd)
sam_grove 1:514f321aa528 259 {
sam_grove 2:b3107e463974 260 FILE *fp = fopen(_newpath, "r");
sam_grove 2:b3107e463974 261 if (fp != NULL)
sam_grove 2:b3107e463974 262 {
sam_grove 2:b3107e463974 263 uint32_t line = 0;
sam_grove 2:b3107e463974 264 while ((0 == feof(fp)) && ((line++) < 10))
sam_grove 2:b3107e463974 265 {
sam_grove 2:b3107e463974 266 fgets(_buf, 512, fp);
sam_grove 2:b3107e463974 267 _com->printf("%s", _buf);
sam_grove 2:b3107e463974 268 }
sam_grove 2:b3107e463974 269 fclose(fp);
sam_grove 2:b3107e463974 270 }
sam_grove 2:b3107e463974 271 else
sam_grove 2:b3107e463974 272 {
sam_grove 2:b3107e463974 273 _com->printf("%s: No such file\n", _newpath);
sam_grove 2:b3107e463974 274 }
sam_grove 2:b3107e463974 275
sam_grove 2:b3107e463974 276 return (char *)OK;
sam_grove 1:514f321aa528 277 }
sam_grove 1:514f321aa528 278
sam_grove 2:b3107e463974 279 char *SDShell::cat(char *cmd)
sam_grove 1:514f321aa528 280 {
sam_grove 2:b3107e463974 281 FILE *fp= fopen(_newpath, "r");
sam_grove 2:b3107e463974 282 if (fp != NULL)
sam_grove 2:b3107e463974 283 {
sam_grove 2:b3107e463974 284 while (!feof(fp))
sam_grove 2:b3107e463974 285 {
sam_grove 2:b3107e463974 286 fread(_buf, 1, 512, fp);
sam_grove 2:b3107e463974 287 _com->printf("%s", _buf);
sam_grove 1:514f321aa528 288 }
sam_grove 1:514f321aa528 289 fclose(fp);
sam_grove 1:514f321aa528 290 }
sam_grove 2:b3107e463974 291 else
sam_grove 2:b3107e463974 292 {
sam_grove 2:b3107e463974 293 _com->printf("%s: No such file\n", _newpath);
sam_grove 2:b3107e463974 294 }
sam_grove 2:b3107e463974 295
sam_grove 2:b3107e463974 296 return (char *)OK;
sam_grove 1:514f321aa528 297 }
sam_grove 0:618e98bf18ce 298
sam_grove 5:3417ba8cb1e4 299 char *SDShell::bcat(char *cmd)
jekain314 4:6ff0a3d92778 300 {
sam_grove 5:3417ba8cb1e4 301 char buf[2] = {NULL};
jekain314 4:6ff0a3d92778 302 FILE *fp= fopen(_newpath, "rb");
jekain314 4:6ff0a3d92778 303 if (fp != NULL)
jekain314 4:6ff0a3d92778 304 {
jekain314 4:6ff0a3d92778 305 while (!feof(fp))
jekain314 4:6ff0a3d92778 306 {
sam_grove 6:743600852c66 307 uint32_t size = fread(_buf, 1, 16, fp);
sam_grove 6:743600852c66 308 _com->putc('{');
sam_grove 6:743600852c66 309 for(int i=0; i<size; i++)
sam_grove 6:743600852c66 310 {
sam_grove 6:743600852c66 311 buf[1] = btoa(_buf[i]);
sam_grove 6:743600852c66 312 buf[0] = btoa(_buf[i]>>4);
sam_grove 6:743600852c66 313 //_com->printf("%c%c", buf[0], buf[1]);
sam_grove 6:743600852c66 314 _com->putc(buf[0]);
sam_grove 6:743600852c66 315 _com->putc(buf[1]);
sam_grove 6:743600852c66 316 }
sam_grove 6:743600852c66 317 _com->putc('}');
sam_grove 6:743600852c66 318 _com->putc('\n');
jekain314 4:6ff0a3d92778 319 }
jekain314 4:6ff0a3d92778 320 fclose(fp);
jekain314 4:6ff0a3d92778 321 }
jekain314 4:6ff0a3d92778 322 else
jekain314 4:6ff0a3d92778 323 {
jekain314 4:6ff0a3d92778 324 _com->printf("%s: No such file\n", _newpath);
jekain314 4:6ff0a3d92778 325 }
jekain314 4:6ff0a3d92778 326 return (char *)OK;
jekain314 4:6ff0a3d92778 327 }
jekain314 4:6ff0a3d92778 328
sam_grove 2:b3107e463974 329 char *SDShell::touch(char *cmd)
sam_grove 1:514f321aa528 330 {
sam_grove 2:b3107e463974 331 FILE *fp = fopen(_newpath, "w");
sam_grove 2:b3107e463974 332 if (fp != NULL)
sam_grove 2:b3107e463974 333 {
sam_grove 2:b3107e463974 334 _com->printf("%s: File created\n", _newpath);
sam_grove 2:b3107e463974 335 fclose(fp);
sam_grove 2:b3107e463974 336 }
sam_grove 2:b3107e463974 337 else
sam_grove 2:b3107e463974 338 {
sam_grove 2:b3107e463974 339 _com->printf("%s: No such file\n", _newpath);
sam_grove 2:b3107e463974 340 }
sam_grove 2:b3107e463974 341
sam_grove 2:b3107e463974 342 return (char *)OK;
sam_grove 2:b3107e463974 343 }
sam_grove 0:618e98bf18ce 344
sam_grove 2:b3107e463974 345 char *SDShell::create(char *cmd)
sam_grove 2:b3107e463974 346 {
sam_grove 2:b3107e463974 347 mkdir(_newpath, 1023);
sam_grove 2:b3107e463974 348
sam_grove 2:b3107e463974 349 return (char *)OK;
sam_grove 1:514f321aa528 350 }
sam_grove 1:514f321aa528 351
sam_grove 2:b3107e463974 352 char *SDShell::rm(char *cmd)
sam_grove 1:514f321aa528 353 {
sam_grove 2:b3107e463974 354 remove(_newpath);
sam_grove 2:b3107e463974 355
sam_grove 2:b3107e463974 356 return (char *)OK;
sam_grove 1:514f321aa528 357 }
sam_grove 1:514f321aa528 358
sam_grove 2:b3107e463974 359 char *SDShell::exit(char *cmd)
sam_grove 2:b3107e463974 360 {
sam_grove 2:b3107e463974 361 return (char *)EXIT;
sam_grove 2:b3107e463974 362 }
sam_grove 2:b3107e463974 363
sam_grove 2:b3107e463974 364 char *SDShell::debug(char *cmd)
sam_grove 2:b3107e463974 365 {
sam_grove 2:b3107e463974 366 _debug = !_debug;
sam_grove 2:b3107e463974 367
sam_grove 2:b3107e463974 368 return (char *)OK;
sam_grove 2:b3107e463974 369 }
sam_grove 2:b3107e463974 370
sam_grove 5:3417ba8cb1e4 371 char SDShell::btoa(uint8_t b)
sam_grove 5:3417ba8cb1e4 372 {
sam_grove 5:3417ba8cb1e4 373 return ((b&0xf) < 0xa) ? ((b&0xf)+0x30) : ((b&0xf)+0x37);
sam_grove 5:3417ba8cb1e4 374 }
sam_grove 2:b3107e463974 375
sam_grove 2:b3107e463974 376
sam_grove 2:b3107e463974 377
sam_grove 5:3417ba8cb1e4 378