Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

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 "drivers/LocalFileSystem.h"
00017 
00018 #if DEVICE_LOCALFILESYSTEM
00019 
00020 #include "platform/mbed_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) : _fh(fh), pos(0) {
00111     // No lock needed in constructor
00112 }
00113 
00114 int LocalFileHandle::close() {
00115     int retval = semihost_close(_fh);
00116     delete this;
00117     return retval;
00118 }
00119 
00120 ssize_t LocalFileHandle::write(const void *buffer, size_t length) {
00121     lock();
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     unlock();
00126     return n;
00127 }
00128 
00129 ssize_t LocalFileHandle::read(void *buffer, size_t length) {
00130     lock();
00131     ssize_t n = semihost_read(_fh, (unsigned char*)buffer, length, 0); // number of characters not read
00132     n = length - n; // number of characters read
00133     pos += n;
00134     unlock();
00135     return n;
00136 }
00137 
00138 int LocalFileHandle::isatty() {
00139     lock();
00140     int ret = semihost_istty(_fh);
00141     unlock();
00142     return ret;
00143 }
00144 
00145 off_t LocalFileHandle::lseek(off_t position, int whence) {
00146     lock();
00147     if (whence == SEEK_CUR) {
00148         position += pos;
00149     } else if (whence == SEEK_END) {
00150         position += semihost_flen(_fh);
00151     } /* otherwise SEEK_SET, so position is fine */
00152 
00153     /* Always seems to return -1, so just ignore for now. */
00154     semihost_seek(_fh, position);
00155     pos = position;
00156     unlock();
00157     return position;
00158 }
00159 
00160 int LocalFileHandle::fsync() {
00161     lock();
00162     int ret = semihost_ensure(_fh);
00163     unlock();
00164     return ret;
00165 }
00166 
00167 off_t LocalFileHandle::flen() {
00168     lock();
00169     off_t off = semihost_flen(_fh);
00170     unlock();
00171     return off;
00172 }
00173 
00174 void LocalFileHandle::lock() {
00175     _mutex.lock();
00176 }
00177 
00178 void LocalFileHandle::unlock() {
00179     _mutex.unlock();
00180 }
00181 
00182 class LocalDirHandle : public DirHandle {
00183 
00184 public:
00185     struct dirent cur_entry;
00186     XFINFO info;
00187 
00188     LocalDirHandle() : cur_entry(), info() {
00189     }
00190 
00191     virtual int closedir() {
00192         // No lock can be used in destructor
00193         delete this;
00194         return 0;
00195     }
00196 
00197     virtual struct dirent *readdir() {
00198         lock();
00199         if (xffind("*", &info)!=0) {
00200             unlock();
00201             return NULL;
00202         }
00203         memcpy(cur_entry.d_name, info.name, sizeof(info.name));
00204         unlock();
00205         return &cur_entry;
00206     }
00207 
00208     virtual void rewinddir() {
00209         lock();
00210         info.fileID = 0;
00211         unlock();
00212     }
00213 
00214     virtual off_t telldir() {
00215         lock();
00216         int fileId = info.fileID;
00217         unlock();
00218         return fileId;
00219     }
00220 
00221     virtual void seekdir(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 FileHandle *LocalFileSystem::open(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 NULL;
00246         }
00247     }
00248 
00249     int openmode = posix_to_semihost_open_flags(flags);
00250     if (openmode == OPEN_INVALID) {
00251         return NULL;
00252     }
00253 
00254     FILEHANDLE fh = semihost_open(name, openmode);
00255     if (fh == -1) {
00256         return NULL;
00257     }
00258     return new LocalFileHandle(fh);
00259 }
00260 
00261 int LocalFileSystem::remove(const char *filename) {
00262     // No global state modified so function is thread safe
00263 
00264     return semihost_remove(filename);
00265 }
00266 
00267 DirHandle *LocalFileSystem::opendir(const char *name) {
00268     // No global state modified so function is thread safe
00269 
00270     return new LocalDirHandle();
00271 }
00272 
00273 } // namespace mbed
00274 
00275 #endif