takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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 {
00050     unsigned param[4];
00051 
00052     param[0] = (unsigned long)pattern;
00053     param[1] = (unsigned long)strlen(pattern);
00054     param[2] = (unsigned long)info;
00055     param[3] = (unsigned long)sizeof(XFINFO);
00056 
00057     return __semihost(USR_XFFIND, param);
00058 }
00059 
00060 #define OPEN_R          0
00061 #define OPEN_B          1
00062 #define OPEN_PLUS       2
00063 #define OPEN_W          4
00064 #define OPEN_A          8
00065 #define OPEN_INVALID   -1
00066 
00067 int posix_to_semihost_open_flags(int flags)
00068 {
00069     /* POSIX flags -> semihosting open mode */
00070     int openmode;
00071     if (flags & O_RDWR) {
00072         /* a plus mode */
00073         openmode = OPEN_PLUS;
00074         if (flags & O_APPEND) {
00075             openmode |= OPEN_A;
00076         } else if (flags & O_TRUNC) {
00077             openmode |= OPEN_W;
00078         } else {
00079             openmode |= OPEN_R;
00080         }
00081     } else if (flags & O_WRONLY) {
00082         /* write or append */
00083         if (flags & O_APPEND) {
00084             openmode = OPEN_A;
00085         } else {
00086             openmode = OPEN_W;
00087         }
00088     } else if (flags == O_RDONLY) {
00089         /* read mode */
00090         openmode = OPEN_R;
00091     } else {
00092         /* invalid flags */
00093         openmode = OPEN_INVALID;
00094     }
00095 
00096     return openmode;
00097 }
00098 
00099 FILEHANDLE local_file_open(const char *name, int flags)
00100 {
00101     int openmode = posix_to_semihost_open_flags(flags);
00102     if (openmode == OPEN_INVALID) {
00103         return (FILEHANDLE)NULL;
00104     }
00105 
00106     FILEHANDLE fh = semihost_open(name, openmode);
00107     if (fh == -1) {
00108         return (FILEHANDLE)NULL;
00109     }
00110 
00111     return fh;
00112 }
00113 
00114 LocalFileHandle::LocalFileHandle(FILEHANDLE fh) : _fh(fh), pos(0)
00115 {
00116     // No lock needed in constructor
00117 }
00118 
00119 int LocalFileHandle::close()
00120 {
00121     int retval = semihost_close(_fh);
00122     delete this;
00123     return retval;
00124 }
00125 
00126 ssize_t LocalFileHandle::write(const void *buffer, size_t length)
00127 {
00128     lock();
00129     ssize_t n = semihost_write(_fh, (const unsigned char *)buffer, length, 0); // number of characters not written
00130     n = length - n; // number of characters written
00131     pos += n;
00132     unlock();
00133     return n;
00134 }
00135 
00136 ssize_t LocalFileHandle::read(void *buffer, size_t length)
00137 {
00138     lock();
00139     ssize_t n = semihost_read(_fh, (unsigned char *)buffer, length, 0); // number of characters not read
00140     n = length - n; // number of characters read
00141     pos += n;
00142     unlock();
00143     return n;
00144 }
00145 
00146 int LocalFileHandle::isatty()
00147 {
00148     lock();
00149     int ret = semihost_istty(_fh);
00150     unlock();
00151     return ret;
00152 }
00153 
00154 off_t LocalFileHandle::seek(off_t position, int whence)
00155 {
00156     lock();
00157     if (whence == SEEK_CUR) {
00158         position += pos;
00159     } else if (whence == SEEK_END) {
00160         position += semihost_flen(_fh);
00161     } /* otherwise SEEK_SET, so position is fine */
00162 
00163     /* Always seems to return -1, so just ignore for now. */
00164     semihost_seek(_fh, position);
00165     pos = position;
00166     unlock();
00167     return position;
00168 }
00169 
00170 int LocalFileHandle::sync()
00171 {
00172     lock();
00173     int ret = semihost_ensure(_fh);
00174     unlock();
00175     return ret;
00176 }
00177 
00178 off_t LocalFileHandle::size()
00179 {
00180     lock();
00181     off_t off = semihost_flen(_fh);
00182     unlock();
00183     return off;
00184 }
00185 
00186 void LocalFileHandle::lock()
00187 {
00188     _mutex.lock();
00189 }
00190 
00191 void LocalFileHandle::unlock()
00192 {
00193     _mutex.unlock();
00194 }
00195 
00196 class LocalDirHandle : public DirHandle {
00197 
00198 public:
00199     XFINFO info;
00200 
00201     LocalDirHandle() : info()
00202     {
00203     }
00204 
00205     virtual int close()
00206     {
00207         // No lock can be used in destructor
00208         delete this;
00209         return 0;
00210     }
00211 
00212     virtual int read(struct dirent *ent)
00213     {
00214         lock();
00215         if (xffind("*", &info) != 0) {
00216             unlock();
00217             return 0;
00218         }
00219         memcpy(ent->d_name, info.name, sizeof(info.name));
00220         unlock();
00221         return 1;
00222     }
00223 
00224     virtual void rewind()
00225     {
00226         lock();
00227         info.fileID = 0;
00228         unlock();
00229     }
00230 
00231     virtual off_t tell()
00232     {
00233         lock();
00234         int fileId = info.fileID;
00235         unlock();
00236         return fileId;
00237     }
00238 
00239     virtual void seek(off_t offset)
00240     {
00241         lock();
00242         info.fileID = offset;
00243         unlock();
00244     }
00245 
00246 protected:
00247     PlatformMutex _mutex;
00248 
00249     virtual void lock()
00250     {
00251         _mutex.lock();
00252     }
00253 
00254     virtual void unlock()
00255     {
00256         _mutex.unlock();
00257     }
00258 };
00259 
00260 int LocalFileSystem::open(FileHandle **file, const char *name, int flags)
00261 {
00262     // No global state modified so function is thread safe
00263 
00264     /* reject filenames with / in them */
00265     for (const char *tmp = name; *tmp; tmp++) {
00266         if (*tmp == '/') {
00267             return -EINVAL;
00268         }
00269     }
00270 
00271     int openmode = posix_to_semihost_open_flags(flags);
00272     if (openmode == OPEN_INVALID) {
00273         return -EINVAL;
00274     }
00275 
00276     FILEHANDLE fh = semihost_open(name, openmode);
00277     if (fh == -1) {
00278         return -EIO;
00279     }
00280 
00281     *file = new LocalFileHandle(fh);
00282     return 0;
00283 }
00284 
00285 int LocalFileSystem::remove(const char *filename)
00286 {
00287     // No global state modified so function is thread safe
00288 
00289     return semihost_remove(filename);
00290 }
00291 
00292 int LocalFileSystem::open(DirHandle **dir, const char *name)
00293 {
00294     // No global state modified so function is thread safe
00295 
00296     *dir = new LocalDirHandle();
00297     return 0;
00298 }
00299 
00300 } // namespace mbed
00301 
00302 #endif