mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
187:0387e8f68319
mbed library release version 165

Who changed what in which revision?

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