mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
Parent:
platform/LocalFileSystem.cpp@0:5b88d5760320
updated based on mbed-os5.15.0

Who changed what in which revision?

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