mbed library with additional peripherals for ST F401 board

Fork of mbed-src by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LocalFileSystem.cpp Source File

LocalFileSystem.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "LocalFileSystem.h"
00017 
00018 #if DEVICE_LOCALFILESYSTEM
00019 
00020 #include "semihost_api.h"
00021 #include <string.h>
00022 #include <stdio.h>
00023 
00024 namespace mbed {
00025 
00026 /* Extension to FINFO type defined in RTL.h (in Keil RL) - adds 'create time'. */
00027 typedef struct {
00028     unsigned char  hr;   /* Hours    [0..23]                  */
00029     unsigned char  min;  /* Minutes  [0..59]                  */
00030     unsigned char  sec;  /* Seconds  [0..59]                  */
00031     unsigned char  day;  /* Day      [1..31]                  */
00032     unsigned char  mon;  /* Month    [1..12]                  */
00033     unsigned short year; /* Year     [1980..2107]             */
00034 } FTIME;
00035 
00036 typedef struct {         /* File Search info record           */
00037     char  name[32];      /* File name                         */
00038     long  size;          /* File size in bytes                */
00039     int   fileID;        /* System File Identification        */
00040     FTIME create_time;   /* Date & time file was created      */
00041     FTIME write_time;    /* Date & time of last write         */
00042 } XFINFO;
00043 
00044 #define RESERVED_FOR_USER_APPLICATIONS (0x100) /* 0x100 - 0x1ff */
00045 #define USR_XFFIND (RESERVED_FOR_USER_APPLICATIONS + 0)
00046 
00047 static int xffind (const char *pattern, XFINFO *info) {
00048     unsigned param[4];
00049 
00050     param[0] = (unsigned long)pattern;
00051     param[1] = (unsigned long)strlen(pattern);
00052     param[2] = (unsigned long)info;
00053     param[3] = (unsigned long)sizeof(XFINFO);
00054 
00055     return __semihost(USR_XFFIND, param);
00056 }
00057 
00058 #define OPEN_R          0
00059 #define OPEN_B          1
00060 #define OPEN_PLUS       2
00061 #define OPEN_W          4
00062 #define OPEN_A          8
00063 #define OPEN_INVALID   -1
00064 
00065 int posix_to_semihost_open_flags(int flags) {
00066     /* POSIX flags -> semihosting open mode */
00067     int openmode;
00068     if (flags & O_RDWR) {
00069         /* a plus mode */
00070         openmode = OPEN_PLUS;
00071         if (flags & O_APPEND) {
00072             openmode |= OPEN_A;
00073         } else if (flags & O_TRUNC) {
00074             openmode |= OPEN_W;
00075         } else {
00076             openmode |= OPEN_R;
00077         }
00078     } else if (flags & O_WRONLY) {
00079         /* write or append */
00080         if (flags & O_APPEND) {
00081             openmode = OPEN_A;
00082         } else {
00083             openmode = OPEN_W;
00084         }
00085     } else if (flags == O_RDONLY) {
00086         /* read mode */
00087         openmode = OPEN_R;
00088     } else {
00089         /* invalid flags */
00090         openmode = OPEN_INVALID;
00091     }
00092 
00093     return openmode;
00094 }
00095 
00096 FILEHANDLE local_file_open(const char* name, int flags) {
00097     int openmode = posix_to_semihost_open_flags(flags);
00098     if (openmode == OPEN_INVALID) {
00099         return (FILEHANDLE)NULL;
00100     }
00101 
00102     FILEHANDLE fh = semihost_open(name, openmode);
00103     if (fh == -1) {
00104         return (FILEHANDLE)NULL;
00105     }
00106 
00107     return fh;
00108 }
00109 
00110 LocalFileHandle::LocalFileHandle(FILEHANDLE fh) {
00111     _fh = fh;
00112     pos = 0;
00113 }
00114 
00115 int LocalFileHandle::close() {
00116     int retval = semihost_close(_fh);
00117     delete this;
00118     return retval;
00119 }
00120 
00121 ssize_t LocalFileHandle::write(const void *buffer, size_t length) {
00122     ssize_t n = semihost_write(_fh, (const unsigned char*)buffer, length, 0); // number of characters not written
00123     n = length - n; // number of characters written
00124     pos += n;
00125     return n;
00126 }
00127 
00128 ssize_t LocalFileHandle::read(void *buffer, size_t length) {
00129     ssize_t n = semihost_read(_fh, (unsigned char*)buffer, length, 0); // number of characters not read
00130     n = length - n; // number of characters read
00131     pos += n;
00132     return n;
00133 }
00134 
00135 int LocalFileHandle::isatty() {
00136     return semihost_istty(_fh);
00137 }
00138 
00139 off_t LocalFileHandle::lseek(off_t position, int whence) {
00140     if (whence == SEEK_CUR) {
00141         position += pos;
00142     } else if (whence == SEEK_END) {
00143         position += semihost_flen(_fh);
00144     } /* otherwise SEEK_SET, so position is fine */
00145 
00146     /* Always seems to return -1, so just ignore for now. */
00147     semihost_seek(_fh, position);
00148     pos = position;
00149     return position;
00150 }
00151 
00152 int LocalFileHandle::fsync() {
00153     return semihost_ensure(_fh);
00154 }
00155 
00156 off_t LocalFileHandle::flen() {
00157     return semihost_flen(_fh);
00158 }
00159 
00160 class LocalDirHandle : public DirHandle {
00161 
00162 public:
00163     struct dirent cur_entry;
00164     XFINFO info;
00165 
00166     LocalDirHandle() {
00167         info.fileID = 0;
00168     }
00169 
00170     virtual int closedir() {
00171         delete this;
00172         return 0;
00173     }
00174 
00175     virtual struct dirent *readdir() {
00176         if (xffind("*", &info)!=0) {
00177             return NULL;
00178         }
00179         memcpy(cur_entry.d_name, info.name, sizeof(info.name));
00180         return &cur_entry;
00181     }
00182 
00183     virtual void rewinddir() {
00184         info.fileID = 0;
00185     }
00186 
00187     virtual off_t telldir() {
00188         return info.fileID;
00189     }
00190 
00191     virtual void seekdir(off_t offset) {
00192         info.fileID = offset;
00193     }
00194 };
00195 
00196 FileHandle *LocalFileSystem::open(const char* name, int flags) {
00197     /* reject filenames with / in them */
00198     for (const char *tmp = name; *tmp; tmp++) {
00199         if (*tmp == '/') {
00200             return NULL;
00201         }
00202     }
00203 
00204     int openmode = posix_to_semihost_open_flags(flags);
00205     if (openmode == OPEN_INVALID) {
00206         return NULL;
00207     }
00208 
00209     FILEHANDLE fh = semihost_open(name, openmode);
00210     if (fh == -1) {
00211         return NULL;
00212     }
00213     return new LocalFileHandle(fh);
00214 }
00215 
00216 int LocalFileSystem::remove(const char *filename) {
00217     return semihost_remove(filename);
00218 }
00219 
00220 DirHandle *LocalFileSystem::opendir(const char *name) {
00221     return new LocalDirHandle();
00222 }
00223 
00224 } // namespace mbed
00225 
00226 #endif