This fork captures the mbed lib v125 for ease of integration into older projects.

Fork of mbed-dev by mbed official

Committer:
apluscw
Date:
Fri Jul 20 21:24:42 2018 +0000
Revision:
187:92cbb9eec47b
Mbed library with source code from mbed lib v125. Posted to ease integration with some older projects.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
apluscw 187:92cbb9eec47b 1 /* mbed Microcontroller Library
apluscw 187:92cbb9eec47b 2 * Copyright (c) 2006-2013 ARM Limited
apluscw 187:92cbb9eec47b 3 *
apluscw 187:92cbb9eec47b 4 * Licensed under the Apache License, Version 2.0 (the "License");
apluscw 187:92cbb9eec47b 5 * you may not use this file except in compliance with the License.
apluscw 187:92cbb9eec47b 6 * You may obtain a copy of the License at
apluscw 187:92cbb9eec47b 7 *
apluscw 187:92cbb9eec47b 8 * http://www.apache.org/licenses/LICENSE-2.0
apluscw 187:92cbb9eec47b 9 *
apluscw 187:92cbb9eec47b 10 * Unless required by applicable law or agreed to in writing, software
apluscw 187:92cbb9eec47b 11 * distributed under the License is distributed on an "AS IS" BASIS,
apluscw 187:92cbb9eec47b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
apluscw 187:92cbb9eec47b 13 * See the License for the specific language governing permissions and
apluscw 187:92cbb9eec47b 14 * limitations under the License.
apluscw 187:92cbb9eec47b 15 */
apluscw 187:92cbb9eec47b 16 #include "LocalFileSystem.h"
apluscw 187:92cbb9eec47b 17
apluscw 187:92cbb9eec47b 18 #if DEVICE_LOCALFILESYSTEM
apluscw 187:92cbb9eec47b 19
apluscw 187:92cbb9eec47b 20 #include "semihost_api.h"
apluscw 187:92cbb9eec47b 21 #include <string.h>
apluscw 187:92cbb9eec47b 22 #include <stdio.h>
apluscw 187:92cbb9eec47b 23
apluscw 187:92cbb9eec47b 24 namespace mbed {
apluscw 187:92cbb9eec47b 25
apluscw 187:92cbb9eec47b 26 /* Extension to FINFO type defined in RTL.h (in Keil RL) - adds 'create time'. */
apluscw 187:92cbb9eec47b 27 typedef struct {
apluscw 187:92cbb9eec47b 28 unsigned char hr; /* Hours [0..23] */
apluscw 187:92cbb9eec47b 29 unsigned char min; /* Minutes [0..59] */
apluscw 187:92cbb9eec47b 30 unsigned char sec; /* Seconds [0..59] */
apluscw 187:92cbb9eec47b 31 unsigned char day; /* Day [1..31] */
apluscw 187:92cbb9eec47b 32 unsigned char mon; /* Month [1..12] */
apluscw 187:92cbb9eec47b 33 unsigned short year; /* Year [1980..2107] */
apluscw 187:92cbb9eec47b 34 } FTIME;
apluscw 187:92cbb9eec47b 35
apluscw 187:92cbb9eec47b 36 typedef struct { /* File Search info record */
apluscw 187:92cbb9eec47b 37 char name[32]; /* File name */
apluscw 187:92cbb9eec47b 38 long size; /* File size in bytes */
apluscw 187:92cbb9eec47b 39 int fileID; /* System File Identification */
apluscw 187:92cbb9eec47b 40 FTIME create_time; /* Date & time file was created */
apluscw 187:92cbb9eec47b 41 FTIME write_time; /* Date & time of last write */
apluscw 187:92cbb9eec47b 42 } XFINFO;
apluscw 187:92cbb9eec47b 43
apluscw 187:92cbb9eec47b 44 #define RESERVED_FOR_USER_APPLICATIONS (0x100) /* 0x100 - 0x1ff */
apluscw 187:92cbb9eec47b 45 #define USR_XFFIND (RESERVED_FOR_USER_APPLICATIONS + 0)
apluscw 187:92cbb9eec47b 46
apluscw 187:92cbb9eec47b 47 static int xffind (const char *pattern, XFINFO *info) {
apluscw 187:92cbb9eec47b 48 unsigned param[4];
apluscw 187:92cbb9eec47b 49
apluscw 187:92cbb9eec47b 50 param[0] = (unsigned long)pattern;
apluscw 187:92cbb9eec47b 51 param[1] = (unsigned long)strlen(pattern);
apluscw 187:92cbb9eec47b 52 param[2] = (unsigned long)info;
apluscw 187:92cbb9eec47b 53 param[3] = (unsigned long)sizeof(XFINFO);
apluscw 187:92cbb9eec47b 54
apluscw 187:92cbb9eec47b 55 return __semihost(USR_XFFIND, param);
apluscw 187:92cbb9eec47b 56 }
apluscw 187:92cbb9eec47b 57
apluscw 187:92cbb9eec47b 58 #define OPEN_R 0
apluscw 187:92cbb9eec47b 59 #define OPEN_B 1
apluscw 187:92cbb9eec47b 60 #define OPEN_PLUS 2
apluscw 187:92cbb9eec47b 61 #define OPEN_W 4
apluscw 187:92cbb9eec47b 62 #define OPEN_A 8
apluscw 187:92cbb9eec47b 63 #define OPEN_INVALID -1
apluscw 187:92cbb9eec47b 64
apluscw 187:92cbb9eec47b 65 int posix_to_semihost_open_flags(int flags) {
apluscw 187:92cbb9eec47b 66 /* POSIX flags -> semihosting open mode */
apluscw 187:92cbb9eec47b 67 int openmode;
apluscw 187:92cbb9eec47b 68 if (flags & O_RDWR) {
apluscw 187:92cbb9eec47b 69 /* a plus mode */
apluscw 187:92cbb9eec47b 70 openmode = OPEN_PLUS;
apluscw 187:92cbb9eec47b 71 if (flags & O_APPEND) {
apluscw 187:92cbb9eec47b 72 openmode |= OPEN_A;
apluscw 187:92cbb9eec47b 73 } else if (flags & O_TRUNC) {
apluscw 187:92cbb9eec47b 74 openmode |= OPEN_W;
apluscw 187:92cbb9eec47b 75 } else {
apluscw 187:92cbb9eec47b 76 openmode |= OPEN_R;
apluscw 187:92cbb9eec47b 77 }
apluscw 187:92cbb9eec47b 78 } else if (flags & O_WRONLY) {
apluscw 187:92cbb9eec47b 79 /* write or append */
apluscw 187:92cbb9eec47b 80 if (flags & O_APPEND) {
apluscw 187:92cbb9eec47b 81 openmode = OPEN_A;
apluscw 187:92cbb9eec47b 82 } else {
apluscw 187:92cbb9eec47b 83 openmode = OPEN_W;
apluscw 187:92cbb9eec47b 84 }
apluscw 187:92cbb9eec47b 85 } else if (flags == O_RDONLY) {
apluscw 187:92cbb9eec47b 86 /* read mode */
apluscw 187:92cbb9eec47b 87 openmode = OPEN_R;
apluscw 187:92cbb9eec47b 88 } else {
apluscw 187:92cbb9eec47b 89 /* invalid flags */
apluscw 187:92cbb9eec47b 90 openmode = OPEN_INVALID;
apluscw 187:92cbb9eec47b 91 }
apluscw 187:92cbb9eec47b 92
apluscw 187:92cbb9eec47b 93 return openmode;
apluscw 187:92cbb9eec47b 94 }
apluscw 187:92cbb9eec47b 95
apluscw 187:92cbb9eec47b 96 FILEHANDLE local_file_open(const char* name, int flags) {
apluscw 187:92cbb9eec47b 97 int openmode = posix_to_semihost_open_flags(flags);
apluscw 187:92cbb9eec47b 98 if (openmode == OPEN_INVALID) {
apluscw 187:92cbb9eec47b 99 return (FILEHANDLE)NULL;
apluscw 187:92cbb9eec47b 100 }
apluscw 187:92cbb9eec47b 101
apluscw 187:92cbb9eec47b 102 FILEHANDLE fh = semihost_open(name, openmode);
apluscw 187:92cbb9eec47b 103 if (fh == -1) {
apluscw 187:92cbb9eec47b 104 return (FILEHANDLE)NULL;
apluscw 187:92cbb9eec47b 105 }
apluscw 187:92cbb9eec47b 106
apluscw 187:92cbb9eec47b 107 return fh;
apluscw 187:92cbb9eec47b 108 }
apluscw 187:92cbb9eec47b 109
apluscw 187:92cbb9eec47b 110 LocalFileHandle::LocalFileHandle(FILEHANDLE fh) : _fh(fh), pos(0) {
apluscw 187:92cbb9eec47b 111 // No lock needed in constructor
apluscw 187:92cbb9eec47b 112 }
apluscw 187:92cbb9eec47b 113
apluscw 187:92cbb9eec47b 114 int LocalFileHandle::close() {
apluscw 187:92cbb9eec47b 115 int retval = semihost_close(_fh);
apluscw 187:92cbb9eec47b 116 delete this;
apluscw 187:92cbb9eec47b 117 return retval;
apluscw 187:92cbb9eec47b 118 }
apluscw 187:92cbb9eec47b 119
apluscw 187:92cbb9eec47b 120 ssize_t LocalFileHandle::write(const void *buffer, size_t length) {
apluscw 187:92cbb9eec47b 121 lock();
apluscw 187:92cbb9eec47b 122 ssize_t n = semihost_write(_fh, (const unsigned char*)buffer, length, 0); // number of characters not written
apluscw 187:92cbb9eec47b 123 n = length - n; // number of characters written
apluscw 187:92cbb9eec47b 124 pos += n;
apluscw 187:92cbb9eec47b 125 unlock();
apluscw 187:92cbb9eec47b 126 return n;
apluscw 187:92cbb9eec47b 127 }
apluscw 187:92cbb9eec47b 128
apluscw 187:92cbb9eec47b 129 ssize_t LocalFileHandle::read(void *buffer, size_t length) {
apluscw 187:92cbb9eec47b 130 lock();
apluscw 187:92cbb9eec47b 131 ssize_t n = semihost_read(_fh, (unsigned char*)buffer, length, 0); // number of characters not read
apluscw 187:92cbb9eec47b 132 n = length - n; // number of characters read
apluscw 187:92cbb9eec47b 133 pos += n;
apluscw 187:92cbb9eec47b 134 unlock();
apluscw 187:92cbb9eec47b 135 return n;
apluscw 187:92cbb9eec47b 136 }
apluscw 187:92cbb9eec47b 137
apluscw 187:92cbb9eec47b 138 int LocalFileHandle::isatty() {
apluscw 187:92cbb9eec47b 139 lock();
apluscw 187:92cbb9eec47b 140 int ret = semihost_istty(_fh);
apluscw 187:92cbb9eec47b 141 unlock();
apluscw 187:92cbb9eec47b 142 return ret;
apluscw 187:92cbb9eec47b 143 }
apluscw 187:92cbb9eec47b 144
apluscw 187:92cbb9eec47b 145 off_t LocalFileHandle::lseek(off_t position, int whence) {
apluscw 187:92cbb9eec47b 146 lock();
apluscw 187:92cbb9eec47b 147 if (whence == SEEK_CUR) {
apluscw 187:92cbb9eec47b 148 position += pos;
apluscw 187:92cbb9eec47b 149 } else if (whence == SEEK_END) {
apluscw 187:92cbb9eec47b 150 position += semihost_flen(_fh);
apluscw 187:92cbb9eec47b 151 } /* otherwise SEEK_SET, so position is fine */
apluscw 187:92cbb9eec47b 152
apluscw 187:92cbb9eec47b 153 /* Always seems to return -1, so just ignore for now. */
apluscw 187:92cbb9eec47b 154 semihost_seek(_fh, position);
apluscw 187:92cbb9eec47b 155 pos = position;
apluscw 187:92cbb9eec47b 156 unlock();
apluscw 187:92cbb9eec47b 157 return position;
apluscw 187:92cbb9eec47b 158 }
apluscw 187:92cbb9eec47b 159
apluscw 187:92cbb9eec47b 160 int LocalFileHandle::fsync() {
apluscw 187:92cbb9eec47b 161 lock();
apluscw 187:92cbb9eec47b 162 int ret = semihost_ensure(_fh);
apluscw 187:92cbb9eec47b 163 unlock();
apluscw 187:92cbb9eec47b 164 return ret;
apluscw 187:92cbb9eec47b 165 }
apluscw 187:92cbb9eec47b 166
apluscw 187:92cbb9eec47b 167 off_t LocalFileHandle::flen() {
apluscw 187:92cbb9eec47b 168 lock();
apluscw 187:92cbb9eec47b 169 off_t off = semihost_flen(_fh);
apluscw 187:92cbb9eec47b 170 unlock();
apluscw 187:92cbb9eec47b 171 return off;
apluscw 187:92cbb9eec47b 172 }
apluscw 187:92cbb9eec47b 173
apluscw 187:92cbb9eec47b 174 void LocalFileHandle::lock() {
apluscw 187:92cbb9eec47b 175 _mutex.lock();
apluscw 187:92cbb9eec47b 176 }
apluscw 187:92cbb9eec47b 177
apluscw 187:92cbb9eec47b 178 void LocalFileHandle::unlock() {
apluscw 187:92cbb9eec47b 179 _mutex.unlock();
apluscw 187:92cbb9eec47b 180 }
apluscw 187:92cbb9eec47b 181
apluscw 187:92cbb9eec47b 182 class LocalDirHandle : public DirHandle {
apluscw 187:92cbb9eec47b 183
apluscw 187:92cbb9eec47b 184 public:
apluscw 187:92cbb9eec47b 185 struct dirent cur_entry;
apluscw 187:92cbb9eec47b 186 XFINFO info;
apluscw 187:92cbb9eec47b 187
apluscw 187:92cbb9eec47b 188 LocalDirHandle() : cur_entry(), info() {
apluscw 187:92cbb9eec47b 189 }
apluscw 187:92cbb9eec47b 190
apluscw 187:92cbb9eec47b 191 virtual int closedir() {
apluscw 187:92cbb9eec47b 192 // No lock can be used in destructor
apluscw 187:92cbb9eec47b 193 delete this;
apluscw 187:92cbb9eec47b 194 return 0;
apluscw 187:92cbb9eec47b 195 }
apluscw 187:92cbb9eec47b 196
apluscw 187:92cbb9eec47b 197 virtual struct dirent *readdir() {
apluscw 187:92cbb9eec47b 198 lock();
apluscw 187:92cbb9eec47b 199 if (xffind("*", &info)!=0) {
apluscw 187:92cbb9eec47b 200 unlock();
apluscw 187:92cbb9eec47b 201 return NULL;
apluscw 187:92cbb9eec47b 202 }
apluscw 187:92cbb9eec47b 203 memcpy(cur_entry.d_name, info.name, sizeof(info.name));
apluscw 187:92cbb9eec47b 204 unlock();
apluscw 187:92cbb9eec47b 205 return &cur_entry;
apluscw 187:92cbb9eec47b 206 }
apluscw 187:92cbb9eec47b 207
apluscw 187:92cbb9eec47b 208 virtual void rewinddir() {
apluscw 187:92cbb9eec47b 209 lock();
apluscw 187:92cbb9eec47b 210 info.fileID = 0;
apluscw 187:92cbb9eec47b 211 unlock();
apluscw 187:92cbb9eec47b 212 }
apluscw 187:92cbb9eec47b 213
apluscw 187:92cbb9eec47b 214 virtual off_t telldir() {
apluscw 187:92cbb9eec47b 215 lock();
apluscw 187:92cbb9eec47b 216 int fileId = info.fileID;
apluscw 187:92cbb9eec47b 217 unlock();
apluscw 187:92cbb9eec47b 218 return fileId;
apluscw 187:92cbb9eec47b 219 }
apluscw 187:92cbb9eec47b 220
apluscw 187:92cbb9eec47b 221 virtual void seekdir(off_t offset) {
apluscw 187:92cbb9eec47b 222 lock();
apluscw 187:92cbb9eec47b 223 info.fileID = offset;
apluscw 187:92cbb9eec47b 224 unlock();
apluscw 187:92cbb9eec47b 225 }
apluscw 187:92cbb9eec47b 226
apluscw 187:92cbb9eec47b 227 protected:
apluscw 187:92cbb9eec47b 228 PlatformMutex _mutex;
apluscw 187:92cbb9eec47b 229
apluscw 187:92cbb9eec47b 230 virtual void lock() {
apluscw 187:92cbb9eec47b 231 _mutex.lock();
apluscw 187:92cbb9eec47b 232 }
apluscw 187:92cbb9eec47b 233
apluscw 187:92cbb9eec47b 234 virtual void unlock() {
apluscw 187:92cbb9eec47b 235 _mutex.unlock();
apluscw 187:92cbb9eec47b 236 }
apluscw 187:92cbb9eec47b 237 };
apluscw 187:92cbb9eec47b 238
apluscw 187:92cbb9eec47b 239 FileHandle *LocalFileSystem::open(const char* name, int flags) {
apluscw 187:92cbb9eec47b 240 // No global state modified so function is thread safe
apluscw 187:92cbb9eec47b 241
apluscw 187:92cbb9eec47b 242 /* reject filenames with / in them */
apluscw 187:92cbb9eec47b 243 for (const char *tmp = name; *tmp; tmp++) {
apluscw 187:92cbb9eec47b 244 if (*tmp == '/') {
apluscw 187:92cbb9eec47b 245 return NULL;
apluscw 187:92cbb9eec47b 246 }
apluscw 187:92cbb9eec47b 247 }
apluscw 187:92cbb9eec47b 248
apluscw 187:92cbb9eec47b 249 int openmode = posix_to_semihost_open_flags(flags);
apluscw 187:92cbb9eec47b 250 if (openmode == OPEN_INVALID) {
apluscw 187:92cbb9eec47b 251 return NULL;
apluscw 187:92cbb9eec47b 252 }
apluscw 187:92cbb9eec47b 253
apluscw 187:92cbb9eec47b 254 FILEHANDLE fh = semihost_open(name, openmode);
apluscw 187:92cbb9eec47b 255 if (fh == -1) {
apluscw 187:92cbb9eec47b 256 return NULL;
apluscw 187:92cbb9eec47b 257 }
apluscw 187:92cbb9eec47b 258 return new LocalFileHandle(fh);
apluscw 187:92cbb9eec47b 259 }
apluscw 187:92cbb9eec47b 260
apluscw 187:92cbb9eec47b 261 int LocalFileSystem::remove(const char *filename) {
apluscw 187:92cbb9eec47b 262 // No global state modified so function is thread safe
apluscw 187:92cbb9eec47b 263
apluscw 187:92cbb9eec47b 264 return semihost_remove(filename);
apluscw 187:92cbb9eec47b 265 }
apluscw 187:92cbb9eec47b 266
apluscw 187:92cbb9eec47b 267 DirHandle *LocalFileSystem::opendir(const char *name) {
apluscw 187:92cbb9eec47b 268 // No global state modified so function is thread safe
apluscw 187:92cbb9eec47b 269
apluscw 187:92cbb9eec47b 270 return new LocalDirHandle();
apluscw 187:92cbb9eec47b 271 }
apluscw 187:92cbb9eec47b 272
apluscw 187:92cbb9eec47b 273 } // namespace mbed
apluscw 187:92cbb9eec47b 274
apluscw 187:92cbb9eec47b 275 #endif