Rtos API example

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 "platform/LocalFileSystem.h"
00017 
00018 #if DEVICE_LOCALFILESYSTEM
00019 
00020 #include "platform/mbed_semihost_api.h"
00021 #include <string.h>
00022 #include <stdio.h>
00023 #include <errno.h>
00024 
00025 namespace mbed {
00026 
00027 /* Extension to FINFO type defined in RTL.h (in Keil RL) - adds 'create time'. */
00028 typedef struct {
00029     unsigned char  hr;   /* Hours    [0..23]                  */
00030     unsigned char  min;  /* Minutes  [0..59]                  */
00031     unsigned char  sec;  /* Seconds  [0..59]                  */
00032     unsigned char  day;  /* Day      [1..31]                  */
00033     unsigned char  mon;  /* Month    [1..12]                  */
00034     unsigned short year; /* Year     [1980..2107]             */
00035 } FTIME;
00036 
00037 typedef struct {         /* File Search info record           */
00038     char  name[32];      /* File name                         */
00039     long  size;          /* File size in bytes                */
00040     int   fileID;        /* System File Identification        */
00041     FTIME create_time;   /* Date & time file was created      */
00042     FTIME write_time;    /* Date & time of last write         */
00043 } XFINFO;
00044 
00045 #define RESERVED_FOR_USER_APPLICATIONS (0x100) /* 0x100 - 0x1ff */
00046 #define USR_XFFIND (RESERVED_FOR_USER_APPLICATIONS + 0)
00047 
00048 static int xffind (const char *pattern, XFINFO *info) {
00049     unsigned param[4];
00050 
00051     param[0] = (unsigned long)pattern;
00052     param[1] = (unsigned long)strlen(pattern);
00053     param[2] = (unsigned long)info;
00054     param[3] = (unsigned long)sizeof(XFINFO);
00055 
00056     return __semihost(USR_XFFIND, param);
00057 }
00058 
00059 #define OPEN_R          0
00060 #define OPEN_B          1
00061 #define OPEN_PLUS       2
00062 #define OPEN_W          4
00063 #define OPEN_A          8
00064 #define OPEN_INVALID   -1
00065 
00066 int posix_to_semihost_open_flags(int flags) {
00067     /* POSIX flags -> semihosting open mode */
00068     int openmode;
00069     if (flags & O_RDWR) {
00070         /* a plus mode */
00071         openmode = OPEN_PLUS;
00072         if (flags & O_APPEND) {
00073             openmode |= OPEN_A;
00074         } else if (flags & O_TRUNC) {
00075             openmode |= OPEN_W;
00076         } else {
00077             openmode |= OPEN_R;
00078         }
00079     } else if (flags & O_WRONLY) {
00080         /* write or append */
00081         if (flags & O_APPEND) {
00082             openmode = OPEN_A;
00083         } else {
00084             openmode = OPEN_W;
00085         }
00086     } else if (flags == O_RDONLY) {
00087         /* read mode */
00088         openmode = OPEN_R;
00089     } else {
00090         /* invalid flags */
00091         openmode = OPEN_INVALID;
00092     }
00093 
00094     return openmode;
00095 }
00096 
00097 FILEHANDLE local_file_open(const char* name, int flags) {
00098     int openmode = posix_to_semihost_open_flags(flags);
00099     if (openmode == OPEN_INVALID) {
00100         return (FILEHANDLE)NULL;
00101     }
00102 
00103     FILEHANDLE fh = semihost_open(name, openmode);
00104     if (fh == -1) {
00105         return (FILEHANDLE)NULL;
00106     }
00107 
00108     return fh;
00109 }
00110 
00111 LocalFileHandle::LocalFileHandle(FILEHANDLE fh) : _fh(fh), pos(0) {
00112     // No lock needed in constructor
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     lock();
00123     ssize_t n = semihost_write(_fh, (const unsigned char*)buffer, length, 0); // number of characters not written
00124     n = length - n; // number of characters written
00125     pos += n;
00126     unlock();
00127     return n;
00128 }
00129 
00130 ssize_t LocalFileHandle::read(void *buffer, size_t length) {
00131     lock();
00132     ssize_t n = semihost_read(_fh, (unsigned char*)buffer, length, 0); // number of characters not read
00133     n = length - n; // number of characters read
00134     pos += n;
00135     unlock();
00136     return n;
00137 }
00138 
00139 int LocalFileHandle::isatty() {
00140     lock();
00141     int ret = semihost_istty(_fh);
00142     unlock();
00143     return ret;
00144 }
00145 
00146 off_t LocalFileHandle::seek(off_t position, int whence) {
00147     lock();
00148     if (whence == SEEK_CUR) {
00149         position += pos;
00150     } else if (whence == SEEK_END) {
00151         position += semihost_flen(_fh);
00152     } /* otherwise SEEK_SET, so position is fine */
00153 
00154     /* Always seems to return -1, so just ignore for now. */
00155     semihost_seek(_fh, position);
00156     pos = position;
00157     unlock();
00158     return position;
00159 }
00160 
00161 int LocalFileHandle::sync() {
00162     lock();
00163     int ret = semihost_ensure(_fh);
00164     unlock();
00165     return ret;
00166 }
00167 
00168 off_t LocalFileHandle::size() {
00169     lock();
00170     off_t off = semihost_flen(_fh);
00171     unlock();
00172     return off;
00173 }
00174 
00175 void LocalFileHandle::lock() {
00176     _mutex.lock();
00177 }
00178 
00179 void LocalFileHandle::unlock() {
00180     _mutex.unlock();
00181 }
00182 
00183 class LocalDirHandle : public DirHandle {
00184 
00185 public:
00186     XFINFO info;
00187 
00188     LocalDirHandle() : info() {
00189     }
00190 
00191     virtual int close() {
00192         // No lock can be used in destructor
00193         delete this;
00194         return 0;
00195     }
00196 
00197     virtual int read(struct dirent *ent) {
00198         lock();
00199         if (xffind("*", &info)!=0) {
00200             unlock();
00201             return 0;
00202         }
00203         memcpy(ent->d_name, info.name, sizeof(info.name));
00204         unlock();
00205         return 1;
00206     }
00207 
00208     virtual void rewind() {
00209         lock();
00210         info.fileID = 0;
00211         unlock();
00212     }
00213 
00214     virtual off_t tell() {
00215         lock();
00216         int fileId = info.fileID;
00217         unlock();
00218         return fileId;
00219     }
00220 
00221     virtual void seek(off_t offset) {
00222         lock();
00223         info.fileID = offset;
00224         unlock();
00225     }
00226 
00227 protected:
00228     PlatformMutex _mutex;
00229 
00230     virtual void lock() {
00231         _mutex.lock();
00232     }
00233 
00234     virtual void unlock() {
00235         _mutex.unlock();
00236     }
00237 };
00238 
00239 int LocalFileSystem::open(FileHandle **file, const char* name, int flags) {
00240     // No global state modified so function is thread safe
00241 
00242     /* reject filenames with / in them */
00243     for (const char *tmp = name; *tmp; tmp++) {
00244         if (*tmp == '/') {
00245             return -EINVAL;
00246         }
00247     }
00248 
00249     int openmode = posix_to_semihost_open_flags(flags);
00250     if (openmode == OPEN_INVALID) {
00251         return -EINVAL;
00252     }
00253 
00254     FILEHANDLE fh = semihost_open(name, openmode);
00255     if (fh == -1) {
00256         return -EIO;
00257     }
00258 
00259     *file = new LocalFileHandle(fh);
00260     return 0;
00261 }
00262 
00263 int LocalFileSystem::remove(const char *filename) {
00264     // No global state modified so function is thread safe
00265 
00266     return semihost_remove(filename);
00267 }
00268 
00269 int LocalFileSystem::open(DirHandle **dir, const char *name) {
00270     // No global state modified so function is thread safe
00271 
00272     *dir = new LocalDirHandle();
00273     return 0;
00274 }
00275 
00276 } // namespace mbed
00277 
00278 #endif