inport from local

Dependents:   Hobbyking_Cheetah_0511

Committer:
NYX
Date:
Mon Mar 16 06:35:48 2020 +0000
Revision:
0:85b3fd62ea1a
reinport to mbed;

Who changed what in which revision?

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