TUKS MCU Introductory course / TUKS-COURSE-2-LED
Committer:
elmot
Date:
Fri Feb 24 21:13:56 2017 +0000
Revision:
1:d0dfbce63a89
Ready-to-copy

Who changed what in which revision?

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