mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
Child:
1:9db0e321a9f4
mbed-os5 only for TYBLE16

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-2012 ARM Limited
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
kenjiArai 0:5b88d5760320 5 * of this software and associated documentation files (the "Software"), to deal
kenjiArai 0:5b88d5760320 6 * in the Software without restriction, including without limitation the rights
kenjiArai 0:5b88d5760320 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
kenjiArai 0:5b88d5760320 8 * copies of the Software, and to permit persons to whom the Software is
kenjiArai 0:5b88d5760320 9 * furnished to do so, subject to the following conditions:
kenjiArai 0:5b88d5760320 10 *
kenjiArai 0:5b88d5760320 11 * The above copyright notice and this permission notice shall be included in
kenjiArai 0:5b88d5760320 12 * all copies or substantial portions of the Software.
kenjiArai 0:5b88d5760320 13 *
kenjiArai 0:5b88d5760320 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
kenjiArai 0:5b88d5760320 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
kenjiArai 0:5b88d5760320 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
kenjiArai 0:5b88d5760320 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
kenjiArai 0:5b88d5760320 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
kenjiArai 0:5b88d5760320 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
kenjiArai 0:5b88d5760320 20 * SOFTWARE.
kenjiArai 0:5b88d5760320 21 */
kenjiArai 0:5b88d5760320 22 #include "diskio.h"
kenjiArai 0:5b88d5760320 23 #include "ffconf.h"
kenjiArai 0:5b88d5760320 24 #include "platform/mbed_debug.h"
kenjiArai 0:5b88d5760320 25 #include "platform/mbed_critical.h"
kenjiArai 0:5b88d5760320 26 #include "filesystem/mbed_filesystem.h"
kenjiArai 0:5b88d5760320 27 #include "FATFileSystem.h"
kenjiArai 0:5b88d5760320 28
kenjiArai 0:5b88d5760320 29 #include <errno.h>
kenjiArai 0:5b88d5760320 30 #include <stdlib.h>
kenjiArai 0:5b88d5760320 31
kenjiArai 0:5b88d5760320 32 namespace mbed {
kenjiArai 0:5b88d5760320 33
kenjiArai 0:5b88d5760320 34 using namespace mbed;
kenjiArai 0:5b88d5760320 35
kenjiArai 0:5b88d5760320 36 static int fat_error_remap(FRESULT res)
kenjiArai 0:5b88d5760320 37 {
kenjiArai 0:5b88d5760320 38 switch (res) {
kenjiArai 0:5b88d5760320 39 case FR_OK: // (0) Succeeded
kenjiArai 0:5b88d5760320 40 return 0;
kenjiArai 0:5b88d5760320 41 case FR_DISK_ERR: // (1) A hard error occurred in the low level disk I/O layer
kenjiArai 0:5b88d5760320 42 return -EIO;
kenjiArai 0:5b88d5760320 43 case FR_INT_ERR: // (2) Assertion failed
kenjiArai 0:5b88d5760320 44 return -1;
kenjiArai 0:5b88d5760320 45 case FR_NOT_READY: // (3) The physical drive cannot work
kenjiArai 0:5b88d5760320 46 return -EIO;
kenjiArai 0:5b88d5760320 47 case FR_NO_FILE: // (4) Could not find the file
kenjiArai 0:5b88d5760320 48 return -ENOENT;
kenjiArai 0:5b88d5760320 49 case FR_NO_PATH: // (5) Could not find the path
kenjiArai 0:5b88d5760320 50 return -ENOTDIR;
kenjiArai 0:5b88d5760320 51 case FR_INVALID_NAME: // (6) The path name format is invalid
kenjiArai 0:5b88d5760320 52 return -EINVAL;
kenjiArai 0:5b88d5760320 53 case FR_DENIED: // (7) Access denied due to prohibited access or directory full
kenjiArai 0:5b88d5760320 54 return -EACCES;
kenjiArai 0:5b88d5760320 55 case FR_EXIST: // (8) Access denied due to prohibited access
kenjiArai 0:5b88d5760320 56 return -EEXIST;
kenjiArai 0:5b88d5760320 57 case FR_INVALID_OBJECT: // (9) The file/directory object is invalid
kenjiArai 0:5b88d5760320 58 return -EBADF;
kenjiArai 0:5b88d5760320 59 case FR_WRITE_PROTECTED: // (10) The physical drive is write protected
kenjiArai 0:5b88d5760320 60 return -EACCES;
kenjiArai 0:5b88d5760320 61 case FR_INVALID_DRIVE: // (11) The logical drive number is invalid
kenjiArai 0:5b88d5760320 62 return -ENODEV;
kenjiArai 0:5b88d5760320 63 case FR_NOT_ENABLED: // (12) The volume has no work area
kenjiArai 0:5b88d5760320 64 return -ENODEV;
kenjiArai 0:5b88d5760320 65 case FR_NO_FILESYSTEM: // (13) There is no valid FAT volume
kenjiArai 0:5b88d5760320 66 return -EINVAL;
kenjiArai 0:5b88d5760320 67 case FR_MKFS_ABORTED: // (14) The f_mkfs() aborted due to any problem
kenjiArai 0:5b88d5760320 68 return -EIO;
kenjiArai 0:5b88d5760320 69 case FR_TIMEOUT: // (15) Could not get a grant to access the volume within defined period
kenjiArai 0:5b88d5760320 70 return -ETIMEDOUT;
kenjiArai 0:5b88d5760320 71 case FR_LOCKED: // (16) The operation is rejected according to the file sharing policy
kenjiArai 0:5b88d5760320 72 return -EBUSY;
kenjiArai 0:5b88d5760320 73 case FR_NOT_ENOUGH_CORE: // (17) LFN working buffer could not be allocated
kenjiArai 0:5b88d5760320 74 return -ENOMEM;
kenjiArai 0:5b88d5760320 75 case FR_TOO_MANY_OPEN_FILES: // (18) Number of open files > FF_FS_LOCK
kenjiArai 0:5b88d5760320 76 return -ENFILE;
kenjiArai 0:5b88d5760320 77 case FR_INVALID_PARAMETER: // (19) Given parameter is invalid
kenjiArai 0:5b88d5760320 78 return -EINVAL;
kenjiArai 0:5b88d5760320 79 default:
kenjiArai 0:5b88d5760320 80 return -res;
kenjiArai 0:5b88d5760320 81 }
kenjiArai 0:5b88d5760320 82 }
kenjiArai 0:5b88d5760320 83
kenjiArai 0:5b88d5760320 84 // Helper class for deferring operations when variable falls out of scope
kenjiArai 0:5b88d5760320 85 template <typename T>
kenjiArai 0:5b88d5760320 86 class Deferred {
kenjiArai 0:5b88d5760320 87 public:
kenjiArai 0:5b88d5760320 88 T _t;
kenjiArai 0:5b88d5760320 89 Callback<void(T)> _ondefer;
kenjiArai 0:5b88d5760320 90
kenjiArai 0:5b88d5760320 91 Deferred(const Deferred &);
kenjiArai 0:5b88d5760320 92 Deferred &operator=(const Deferred &);
kenjiArai 0:5b88d5760320 93
kenjiArai 0:5b88d5760320 94 public:
kenjiArai 0:5b88d5760320 95 Deferred(T t, Callback<void(T)> ondefer = NULL)
kenjiArai 0:5b88d5760320 96 : _t(t), _ondefer(ondefer)
kenjiArai 0:5b88d5760320 97 {
kenjiArai 0:5b88d5760320 98 }
kenjiArai 0:5b88d5760320 99
kenjiArai 0:5b88d5760320 100 operator T()
kenjiArai 0:5b88d5760320 101 {
kenjiArai 0:5b88d5760320 102 return _t;
kenjiArai 0:5b88d5760320 103 }
kenjiArai 0:5b88d5760320 104
kenjiArai 0:5b88d5760320 105 ~Deferred()
kenjiArai 0:5b88d5760320 106 {
kenjiArai 0:5b88d5760320 107 if (_ondefer) {
kenjiArai 0:5b88d5760320 108 _ondefer(_t);
kenjiArai 0:5b88d5760320 109 }
kenjiArai 0:5b88d5760320 110 }
kenjiArai 0:5b88d5760320 111 };
kenjiArai 0:5b88d5760320 112
kenjiArai 0:5b88d5760320 113 static void dodelete(const char *data)
kenjiArai 0:5b88d5760320 114 {
kenjiArai 0:5b88d5760320 115 delete[] data;
kenjiArai 0:5b88d5760320 116 }
kenjiArai 0:5b88d5760320 117
kenjiArai 0:5b88d5760320 118 // Adds prefix needed internally by fatfs, this can be avoided for the first fatfs
kenjiArai 0:5b88d5760320 119 // (id 0) otherwise a prefix of "id:/" is inserted in front of the string.
kenjiArai 0:5b88d5760320 120 static Deferred<const char *> fat_path_prefix(int id, const char *path)
kenjiArai 0:5b88d5760320 121 {
kenjiArai 0:5b88d5760320 122 // We can avoid dynamic allocation when only on fatfs is in use
kenjiArai 0:5b88d5760320 123 if (id == 0) {
kenjiArai 0:5b88d5760320 124 return path;
kenjiArai 0:5b88d5760320 125 }
kenjiArai 0:5b88d5760320 126
kenjiArai 0:5b88d5760320 127 // Prefix path with id, will look something like 2:/hi/hello/filehere.txt
kenjiArai 0:5b88d5760320 128 char *buffer = new char[strlen("0:/") + strlen(path) + 1];
kenjiArai 0:5b88d5760320 129 if (!buffer) {
kenjiArai 0:5b88d5760320 130 return NULL;
kenjiArai 0:5b88d5760320 131 }
kenjiArai 0:5b88d5760320 132
kenjiArai 0:5b88d5760320 133 buffer[0] = '0' + id;
kenjiArai 0:5b88d5760320 134 buffer[1] = ':';
kenjiArai 0:5b88d5760320 135 buffer[2] = '/';
kenjiArai 0:5b88d5760320 136 strcpy(buffer + strlen("0:/"), path);
kenjiArai 0:5b88d5760320 137 return Deferred<const char *>(buffer, dodelete);
kenjiArai 0:5b88d5760320 138 }
kenjiArai 0:5b88d5760320 139
kenjiArai 0:5b88d5760320 140 ////// Disk operations //////
kenjiArai 0:5b88d5760320 141
kenjiArai 0:5b88d5760320 142 // Global access to block device from FAT driver
kenjiArai 0:5b88d5760320 143 static mbed::BlockDevice *_ffs[FF_VOLUMES] = {0};
kenjiArai 0:5b88d5760320 144 static SingletonPtr<PlatformMutex> _ffs_mutex;
kenjiArai 0:5b88d5760320 145
kenjiArai 0:5b88d5760320 146 // FAT driver functions
kenjiArai 0:5b88d5760320 147 extern "C" DWORD get_fattime(void)
kenjiArai 0:5b88d5760320 148 {
kenjiArai 0:5b88d5760320 149 time_t rawtime;
kenjiArai 0:5b88d5760320 150 time(&rawtime);
kenjiArai 0:5b88d5760320 151 struct tm *ptm = localtime(&rawtime);
kenjiArai 0:5b88d5760320 152 return (DWORD)(ptm->tm_year - 80) << 25
kenjiArai 0:5b88d5760320 153 | (DWORD)(ptm->tm_mon + 1) << 21
kenjiArai 0:5b88d5760320 154 | (DWORD)(ptm->tm_mday) << 16
kenjiArai 0:5b88d5760320 155 | (DWORD)(ptm->tm_hour) << 11
kenjiArai 0:5b88d5760320 156 | (DWORD)(ptm->tm_min) << 5
kenjiArai 0:5b88d5760320 157 | (DWORD)(ptm->tm_sec / 2);
kenjiArai 0:5b88d5760320 158 }
kenjiArai 0:5b88d5760320 159
kenjiArai 0:5b88d5760320 160 extern "C" void *ff_memalloc(UINT size)
kenjiArai 0:5b88d5760320 161 {
kenjiArai 0:5b88d5760320 162 return malloc(size);
kenjiArai 0:5b88d5760320 163 }
kenjiArai 0:5b88d5760320 164
kenjiArai 0:5b88d5760320 165 extern "C" void ff_memfree(void *p)
kenjiArai 0:5b88d5760320 166 {
kenjiArai 0:5b88d5760320 167 free(p);
kenjiArai 0:5b88d5760320 168 }
kenjiArai 0:5b88d5760320 169
kenjiArai 0:5b88d5760320 170 // Implementation of diskio functions (see ChaN/diskio.h)
kenjiArai 0:5b88d5760320 171 static WORD disk_get_sector_size(BYTE pdrv)
kenjiArai 0:5b88d5760320 172 {
kenjiArai 0:5b88d5760320 173 bd_size_t sector_size = _ffs[pdrv]->get_erase_size();
kenjiArai 0:5b88d5760320 174 MBED_ASSERT(sector_size <= WORD(-1));
kenjiArai 0:5b88d5760320 175
kenjiArai 0:5b88d5760320 176 WORD ssize = sector_size;
kenjiArai 0:5b88d5760320 177 if (ssize < 512) {
kenjiArai 0:5b88d5760320 178 ssize = 512;
kenjiArai 0:5b88d5760320 179 }
kenjiArai 0:5b88d5760320 180
kenjiArai 0:5b88d5760320 181 MBED_ASSERT(ssize >= FF_MIN_SS && ssize <= FF_MAX_SS);
kenjiArai 0:5b88d5760320 182 MBED_ASSERT(_ffs[pdrv]->get_read_size() <= _ffs[pdrv]->get_erase_size());
kenjiArai 0:5b88d5760320 183 MBED_ASSERT(_ffs[pdrv]->get_program_size() <= _ffs[pdrv]->get_erase_size());
kenjiArai 0:5b88d5760320 184 return ssize;
kenjiArai 0:5b88d5760320 185 }
kenjiArai 0:5b88d5760320 186
kenjiArai 0:5b88d5760320 187 static DWORD disk_get_sector_count(BYTE pdrv)
kenjiArai 0:5b88d5760320 188 {
kenjiArai 0:5b88d5760320 189 DWORD scount = _ffs[pdrv]->size() / disk_get_sector_size(pdrv);
kenjiArai 0:5b88d5760320 190 MBED_ASSERT(scount >= 64);
kenjiArai 0:5b88d5760320 191 return scount;
kenjiArai 0:5b88d5760320 192 }
kenjiArai 0:5b88d5760320 193
kenjiArai 0:5b88d5760320 194 extern "C" DSTATUS disk_status(BYTE pdrv)
kenjiArai 0:5b88d5760320 195 {
kenjiArai 0:5b88d5760320 196 debug_if(FFS_DBG, "disk_status on pdrv [%d]\n", pdrv);
kenjiArai 0:5b88d5760320 197 return RES_OK;
kenjiArai 0:5b88d5760320 198 }
kenjiArai 0:5b88d5760320 199
kenjiArai 0:5b88d5760320 200 extern "C" DSTATUS disk_initialize(BYTE pdrv)
kenjiArai 0:5b88d5760320 201 {
kenjiArai 0:5b88d5760320 202 debug_if(FFS_DBG, "disk_initialize on pdrv [%d]\n", pdrv);
kenjiArai 0:5b88d5760320 203 return (DSTATUS)_ffs[pdrv]->init();
kenjiArai 0:5b88d5760320 204 }
kenjiArai 0:5b88d5760320 205
kenjiArai 0:5b88d5760320 206 extern "C" DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
kenjiArai 0:5b88d5760320 207 {
kenjiArai 0:5b88d5760320 208 debug_if(FFS_DBG, "disk_read(sector %lu, count %u) on pdrv [%d]\n", sector, count, pdrv);
kenjiArai 0:5b88d5760320 209 DWORD ssize = disk_get_sector_size(pdrv);
kenjiArai 0:5b88d5760320 210 mbed::bd_addr_t addr = (mbed::bd_addr_t)sector * ssize;
kenjiArai 0:5b88d5760320 211 mbed::bd_size_t size = (mbed::bd_size_t)count * ssize;
kenjiArai 0:5b88d5760320 212 int err = _ffs[pdrv]->read(buff, addr, size);
kenjiArai 0:5b88d5760320 213 return err ? RES_PARERR : RES_OK;
kenjiArai 0:5b88d5760320 214 }
kenjiArai 0:5b88d5760320 215
kenjiArai 0:5b88d5760320 216 extern "C" DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
kenjiArai 0:5b88d5760320 217 {
kenjiArai 0:5b88d5760320 218 debug_if(FFS_DBG, "disk_write(sector %lu, count %u) on pdrv [%d]\n", sector, count, pdrv);
kenjiArai 0:5b88d5760320 219 DWORD ssize = disk_get_sector_size(pdrv);
kenjiArai 0:5b88d5760320 220 mbed::bd_addr_t addr = (mbed::bd_addr_t)sector * ssize;
kenjiArai 0:5b88d5760320 221 mbed::bd_size_t size = (mbed::bd_size_t)count * ssize;
kenjiArai 0:5b88d5760320 222
kenjiArai 0:5b88d5760320 223 int err = _ffs[pdrv]->erase(addr, size);
kenjiArai 0:5b88d5760320 224 if (err) {
kenjiArai 0:5b88d5760320 225 return RES_PARERR;
kenjiArai 0:5b88d5760320 226 }
kenjiArai 0:5b88d5760320 227
kenjiArai 0:5b88d5760320 228 err = _ffs[pdrv]->program(buff, addr, size);
kenjiArai 0:5b88d5760320 229 if (err) {
kenjiArai 0:5b88d5760320 230 return RES_PARERR;
kenjiArai 0:5b88d5760320 231 }
kenjiArai 0:5b88d5760320 232
kenjiArai 0:5b88d5760320 233 return RES_OK;
kenjiArai 0:5b88d5760320 234 }
kenjiArai 0:5b88d5760320 235
kenjiArai 0:5b88d5760320 236 extern "C" DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
kenjiArai 0:5b88d5760320 237 {
kenjiArai 0:5b88d5760320 238 debug_if(FFS_DBG, "disk_ioctl(%d)\n", cmd);
kenjiArai 0:5b88d5760320 239 switch (cmd) {
kenjiArai 0:5b88d5760320 240 case CTRL_SYNC:
kenjiArai 0:5b88d5760320 241 if (_ffs[pdrv] == NULL) {
kenjiArai 0:5b88d5760320 242 return RES_NOTRDY;
kenjiArai 0:5b88d5760320 243 } else {
kenjiArai 0:5b88d5760320 244 return RES_OK;
kenjiArai 0:5b88d5760320 245 }
kenjiArai 0:5b88d5760320 246 case GET_SECTOR_COUNT:
kenjiArai 0:5b88d5760320 247 if (_ffs[pdrv] == NULL) {
kenjiArai 0:5b88d5760320 248 return RES_NOTRDY;
kenjiArai 0:5b88d5760320 249 } else {
kenjiArai 0:5b88d5760320 250 *((DWORD *)buff) = disk_get_sector_count(pdrv);
kenjiArai 0:5b88d5760320 251 return RES_OK;
kenjiArai 0:5b88d5760320 252 }
kenjiArai 0:5b88d5760320 253 case GET_SECTOR_SIZE:
kenjiArai 0:5b88d5760320 254 if (_ffs[pdrv] == NULL) {
kenjiArai 0:5b88d5760320 255 return RES_NOTRDY;
kenjiArai 0:5b88d5760320 256 } else {
kenjiArai 0:5b88d5760320 257 *((WORD *)buff) = disk_get_sector_size(pdrv);
kenjiArai 0:5b88d5760320 258 return RES_OK;
kenjiArai 0:5b88d5760320 259 }
kenjiArai 0:5b88d5760320 260 case GET_BLOCK_SIZE:
kenjiArai 0:5b88d5760320 261 *((DWORD *)buff) = 1; // default when not known
kenjiArai 0:5b88d5760320 262 return RES_OK;
kenjiArai 0:5b88d5760320 263 case CTRL_TRIM:
kenjiArai 0:5b88d5760320 264 if (_ffs[pdrv] == NULL) {
kenjiArai 0:5b88d5760320 265 return RES_NOTRDY;
kenjiArai 0:5b88d5760320 266 } else {
kenjiArai 0:5b88d5760320 267 DWORD *sectors = (DWORD *)buff;
kenjiArai 0:5b88d5760320 268 DWORD ssize = disk_get_sector_size(pdrv);
kenjiArai 0:5b88d5760320 269 mbed::bd_addr_t addr = (mbed::bd_addr_t)sectors[0] * ssize;
kenjiArai 0:5b88d5760320 270 mbed::bd_size_t size = (mbed::bd_size_t)(sectors[1] - sectors[0] + 1) * ssize;
kenjiArai 0:5b88d5760320 271 int err = _ffs[pdrv]->trim(addr, size);
kenjiArai 0:5b88d5760320 272 return err ? RES_PARERR : RES_OK;
kenjiArai 0:5b88d5760320 273 }
kenjiArai 0:5b88d5760320 274 }
kenjiArai 0:5b88d5760320 275
kenjiArai 0:5b88d5760320 276 return RES_PARERR;
kenjiArai 0:5b88d5760320 277 }
kenjiArai 0:5b88d5760320 278
kenjiArai 0:5b88d5760320 279 ////// Generic filesystem operations //////
kenjiArai 0:5b88d5760320 280
kenjiArai 0:5b88d5760320 281 // Filesystem implementation (See FATFilySystem.h)
kenjiArai 0:5b88d5760320 282 FATFileSystem::FATFileSystem(const char *name, BlockDevice *bd)
kenjiArai 0:5b88d5760320 283 : FileSystem(name), _id(-1)
kenjiArai 0:5b88d5760320 284 {
kenjiArai 0:5b88d5760320 285 if (bd) {
kenjiArai 0:5b88d5760320 286 mount(bd);
kenjiArai 0:5b88d5760320 287 }
kenjiArai 0:5b88d5760320 288 }
kenjiArai 0:5b88d5760320 289
kenjiArai 0:5b88d5760320 290 FATFileSystem::~FATFileSystem()
kenjiArai 0:5b88d5760320 291 {
kenjiArai 0:5b88d5760320 292 // nop if unmounted
kenjiArai 0:5b88d5760320 293 unmount();
kenjiArai 0:5b88d5760320 294 }
kenjiArai 0:5b88d5760320 295
kenjiArai 0:5b88d5760320 296 int FATFileSystem::mount(BlockDevice *bd)
kenjiArai 0:5b88d5760320 297 {
kenjiArai 0:5b88d5760320 298 // requires duplicate definition to allow virtual overload to work
kenjiArai 0:5b88d5760320 299 return mount(bd, true);
kenjiArai 0:5b88d5760320 300 }
kenjiArai 0:5b88d5760320 301
kenjiArai 0:5b88d5760320 302 int FATFileSystem::mount(BlockDevice *bd, bool mount)
kenjiArai 0:5b88d5760320 303 {
kenjiArai 0:5b88d5760320 304 lock();
kenjiArai 0:5b88d5760320 305 if (_id != -1) {
kenjiArai 0:5b88d5760320 306 unlock();
kenjiArai 0:5b88d5760320 307 return -EINVAL;
kenjiArai 0:5b88d5760320 308 }
kenjiArai 0:5b88d5760320 309
kenjiArai 0:5b88d5760320 310 for (int i = 0; i < FF_VOLUMES; i++) {
kenjiArai 0:5b88d5760320 311 if (!_ffs[i]) {
kenjiArai 0:5b88d5760320 312 _id = i;
kenjiArai 0:5b88d5760320 313 _ffs[_id] = bd;
kenjiArai 0:5b88d5760320 314 _fsid[0] = '0' + _id;
kenjiArai 0:5b88d5760320 315 _fsid[1] = ':';
kenjiArai 0:5b88d5760320 316 _fsid[2] = '\0';
kenjiArai 0:5b88d5760320 317 debug_if(FFS_DBG, "Mounting [%s] on ffs drive [%s]\n", getName(), _fsid);
kenjiArai 0:5b88d5760320 318 FRESULT res = f_mount(&_fs, _fsid, mount);
kenjiArai 0:5b88d5760320 319 unlock();
kenjiArai 0:5b88d5760320 320 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 321 }
kenjiArai 0:5b88d5760320 322 }
kenjiArai 0:5b88d5760320 323
kenjiArai 0:5b88d5760320 324 unlock();
kenjiArai 0:5b88d5760320 325 return -ENOMEM;
kenjiArai 0:5b88d5760320 326 }
kenjiArai 0:5b88d5760320 327
kenjiArai 0:5b88d5760320 328 int FATFileSystem::unmount()
kenjiArai 0:5b88d5760320 329 {
kenjiArai 0:5b88d5760320 330 lock();
kenjiArai 0:5b88d5760320 331 if (_id == -1) {
kenjiArai 0:5b88d5760320 332 unlock();
kenjiArai 0:5b88d5760320 333 return -EINVAL;
kenjiArai 0:5b88d5760320 334 }
kenjiArai 0:5b88d5760320 335
kenjiArai 0:5b88d5760320 336 FRESULT res = f_mount(NULL, _fsid, 0);
kenjiArai 0:5b88d5760320 337 _ffs[_id] = NULL;
kenjiArai 0:5b88d5760320 338 _id = -1;
kenjiArai 0:5b88d5760320 339 unlock();
kenjiArai 0:5b88d5760320 340 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 341 }
kenjiArai 0:5b88d5760320 342
kenjiArai 0:5b88d5760320 343 /* See http://elm-chan.org/fsw/ff/en/mkfs.html for details of f_mkfs() and
kenjiArai 0:5b88d5760320 344 * associated arguments. */
kenjiArai 0:5b88d5760320 345 int FATFileSystem::format(BlockDevice *bd, bd_size_t cluster_size)
kenjiArai 0:5b88d5760320 346 {
kenjiArai 0:5b88d5760320 347 FATFileSystem fs;
kenjiArai 0:5b88d5760320 348 fs.lock();
kenjiArai 0:5b88d5760320 349
kenjiArai 0:5b88d5760320 350 int err = bd->init();
kenjiArai 0:5b88d5760320 351 if (err) {
kenjiArai 0:5b88d5760320 352 fs.unlock();
kenjiArai 0:5b88d5760320 353 return err;
kenjiArai 0:5b88d5760320 354 }
kenjiArai 0:5b88d5760320 355
kenjiArai 0:5b88d5760320 356 // erase first handful of blocks
kenjiArai 0:5b88d5760320 357 bd_size_t header = 2 * bd->get_erase_size();
kenjiArai 0:5b88d5760320 358 err = bd->erase(0, header);
kenjiArai 0:5b88d5760320 359 if (err) {
kenjiArai 0:5b88d5760320 360 bd->deinit();
kenjiArai 0:5b88d5760320 361 fs.unlock();
kenjiArai 0:5b88d5760320 362 return err;
kenjiArai 0:5b88d5760320 363 }
kenjiArai 0:5b88d5760320 364
kenjiArai 0:5b88d5760320 365 if (bd->get_erase_value() < 0) {
kenjiArai 0:5b88d5760320 366 // erase is unknown, need to write 1s
kenjiArai 0:5b88d5760320 367 bd_size_t program_size = bd->get_program_size();
kenjiArai 0:5b88d5760320 368 void *buf = malloc(program_size);
kenjiArai 0:5b88d5760320 369 if (!buf) {
kenjiArai 0:5b88d5760320 370 bd->deinit();
kenjiArai 0:5b88d5760320 371 fs.unlock();
kenjiArai 0:5b88d5760320 372 return -ENOMEM;
kenjiArai 0:5b88d5760320 373 }
kenjiArai 0:5b88d5760320 374
kenjiArai 0:5b88d5760320 375 memset(buf, 0xff, program_size);
kenjiArai 0:5b88d5760320 376
kenjiArai 0:5b88d5760320 377 for (bd_addr_t i = 0; i < header; i += program_size) {
kenjiArai 0:5b88d5760320 378 err = bd->program(buf, i, program_size);
kenjiArai 0:5b88d5760320 379 if (err) {
kenjiArai 0:5b88d5760320 380 free(buf);
kenjiArai 0:5b88d5760320 381 bd->deinit();
kenjiArai 0:5b88d5760320 382 fs.unlock();
kenjiArai 0:5b88d5760320 383 return err;
kenjiArai 0:5b88d5760320 384 }
kenjiArai 0:5b88d5760320 385 }
kenjiArai 0:5b88d5760320 386
kenjiArai 0:5b88d5760320 387 free(buf);
kenjiArai 0:5b88d5760320 388 }
kenjiArai 0:5b88d5760320 389
kenjiArai 0:5b88d5760320 390 // trim entire device to indicate it is unneeded
kenjiArai 0:5b88d5760320 391 err = bd->trim(0, bd->size());
kenjiArai 0:5b88d5760320 392 if (err) {
kenjiArai 0:5b88d5760320 393 bd->deinit();
kenjiArai 0:5b88d5760320 394 fs.unlock();
kenjiArai 0:5b88d5760320 395 return err;
kenjiArai 0:5b88d5760320 396 }
kenjiArai 0:5b88d5760320 397
kenjiArai 0:5b88d5760320 398 err = bd->deinit();
kenjiArai 0:5b88d5760320 399 if (err) {
kenjiArai 0:5b88d5760320 400 fs.unlock();
kenjiArai 0:5b88d5760320 401 return err;
kenjiArai 0:5b88d5760320 402 }
kenjiArai 0:5b88d5760320 403
kenjiArai 0:5b88d5760320 404 err = fs.mount(bd, false);
kenjiArai 0:5b88d5760320 405 if (err) {
kenjiArai 0:5b88d5760320 406 fs.unlock();
kenjiArai 0:5b88d5760320 407 return err;
kenjiArai 0:5b88d5760320 408 }
kenjiArai 0:5b88d5760320 409
kenjiArai 0:5b88d5760320 410 // Logical drive number, Partitioning rule, Allocation unit size (bytes per cluster)
kenjiArai 0:5b88d5760320 411 FRESULT res = f_mkfs(fs._fsid, FM_ANY | FM_SFD, cluster_size, NULL, 0);
kenjiArai 0:5b88d5760320 412 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 413 fs.unmount();
kenjiArai 0:5b88d5760320 414 fs.unlock();
kenjiArai 0:5b88d5760320 415 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 416 }
kenjiArai 0:5b88d5760320 417
kenjiArai 0:5b88d5760320 418 err = fs.unmount();
kenjiArai 0:5b88d5760320 419 if (err) {
kenjiArai 0:5b88d5760320 420 fs.unlock();
kenjiArai 0:5b88d5760320 421 return err;
kenjiArai 0:5b88d5760320 422 }
kenjiArai 0:5b88d5760320 423
kenjiArai 0:5b88d5760320 424 fs.unlock();
kenjiArai 0:5b88d5760320 425 return 0;
kenjiArai 0:5b88d5760320 426 }
kenjiArai 0:5b88d5760320 427
kenjiArai 0:5b88d5760320 428 int FATFileSystem::reformat(BlockDevice *bd, int allocation_unit)
kenjiArai 0:5b88d5760320 429 {
kenjiArai 0:5b88d5760320 430 lock();
kenjiArai 0:5b88d5760320 431 if (_id != -1) {
kenjiArai 0:5b88d5760320 432 if (!bd) {
kenjiArai 0:5b88d5760320 433 bd = _ffs[_id];
kenjiArai 0:5b88d5760320 434 }
kenjiArai 0:5b88d5760320 435
kenjiArai 0:5b88d5760320 436 int err = unmount();
kenjiArai 0:5b88d5760320 437 if (err) {
kenjiArai 0:5b88d5760320 438 unlock();
kenjiArai 0:5b88d5760320 439 return err;
kenjiArai 0:5b88d5760320 440 }
kenjiArai 0:5b88d5760320 441 }
kenjiArai 0:5b88d5760320 442
kenjiArai 0:5b88d5760320 443 if (!bd) {
kenjiArai 0:5b88d5760320 444 unlock();
kenjiArai 0:5b88d5760320 445 return -ENODEV;
kenjiArai 0:5b88d5760320 446 }
kenjiArai 0:5b88d5760320 447
kenjiArai 0:5b88d5760320 448 int err = FATFileSystem::format(bd, allocation_unit);
kenjiArai 0:5b88d5760320 449 if (err) {
kenjiArai 0:5b88d5760320 450 unlock();
kenjiArai 0:5b88d5760320 451 return err;
kenjiArai 0:5b88d5760320 452 }
kenjiArai 0:5b88d5760320 453
kenjiArai 0:5b88d5760320 454 err = mount(bd);
kenjiArai 0:5b88d5760320 455 unlock();
kenjiArai 0:5b88d5760320 456 return err;
kenjiArai 0:5b88d5760320 457 }
kenjiArai 0:5b88d5760320 458
kenjiArai 0:5b88d5760320 459 int FATFileSystem::remove(const char *path)
kenjiArai 0:5b88d5760320 460 {
kenjiArai 0:5b88d5760320 461 Deferred<const char *> fpath = fat_path_prefix(_id, path);
kenjiArai 0:5b88d5760320 462
kenjiArai 0:5b88d5760320 463 lock();
kenjiArai 0:5b88d5760320 464 FRESULT res = f_unlink(fpath);
kenjiArai 0:5b88d5760320 465 unlock();
kenjiArai 0:5b88d5760320 466
kenjiArai 0:5b88d5760320 467 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 468 debug_if(FFS_DBG, "f_unlink() failed: %d\n", res);
kenjiArai 0:5b88d5760320 469 if (res == FR_DENIED) {
kenjiArai 0:5b88d5760320 470 return -ENOTEMPTY;
kenjiArai 0:5b88d5760320 471 }
kenjiArai 0:5b88d5760320 472 }
kenjiArai 0:5b88d5760320 473 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 474 }
kenjiArai 0:5b88d5760320 475
kenjiArai 0:5b88d5760320 476 int FATFileSystem::rename(const char *oldpath, const char *newpath)
kenjiArai 0:5b88d5760320 477 {
kenjiArai 0:5b88d5760320 478 Deferred<const char *> oldfpath = fat_path_prefix(_id, oldpath);
kenjiArai 0:5b88d5760320 479 Deferred<const char *> newfpath = fat_path_prefix(_id, newpath);
kenjiArai 0:5b88d5760320 480
kenjiArai 0:5b88d5760320 481 lock();
kenjiArai 0:5b88d5760320 482 FRESULT res = f_rename(oldfpath, newfpath);
kenjiArai 0:5b88d5760320 483 unlock();
kenjiArai 0:5b88d5760320 484
kenjiArai 0:5b88d5760320 485 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 486 debug_if(FFS_DBG, "f_rename() failed: %d\n", res);
kenjiArai 0:5b88d5760320 487 }
kenjiArai 0:5b88d5760320 488 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 489 }
kenjiArai 0:5b88d5760320 490
kenjiArai 0:5b88d5760320 491 int FATFileSystem::mkdir(const char *path, mode_t mode)
kenjiArai 0:5b88d5760320 492 {
kenjiArai 0:5b88d5760320 493 Deferred<const char *> fpath = fat_path_prefix(_id, path);
kenjiArai 0:5b88d5760320 494
kenjiArai 0:5b88d5760320 495 lock();
kenjiArai 0:5b88d5760320 496 FRESULT res = f_mkdir(fpath);
kenjiArai 0:5b88d5760320 497 unlock();
kenjiArai 0:5b88d5760320 498
kenjiArai 0:5b88d5760320 499 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 500 debug_if(FFS_DBG, "f_mkdir() failed: %d\n", res);
kenjiArai 0:5b88d5760320 501 }
kenjiArai 0:5b88d5760320 502 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 503 }
kenjiArai 0:5b88d5760320 504
kenjiArai 0:5b88d5760320 505 int FATFileSystem::stat(const char *path, struct stat *st)
kenjiArai 0:5b88d5760320 506 {
kenjiArai 0:5b88d5760320 507 Deferred<const char *> fpath = fat_path_prefix(_id, path);
kenjiArai 0:5b88d5760320 508
kenjiArai 0:5b88d5760320 509 lock();
kenjiArai 0:5b88d5760320 510 FILINFO f;
kenjiArai 0:5b88d5760320 511 memset(&f, 0, sizeof(f));
kenjiArai 0:5b88d5760320 512
kenjiArai 0:5b88d5760320 513 FRESULT res = f_stat(fpath, &f);
kenjiArai 0:5b88d5760320 514 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 515 unlock();
kenjiArai 0:5b88d5760320 516 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 517 }
kenjiArai 0:5b88d5760320 518
kenjiArai 0:5b88d5760320 519 /* ARMCC doesnt support stat(), and these symbols are not defined by the toolchain. */
kenjiArai 0:5b88d5760320 520 #ifdef TOOLCHAIN_GCC
kenjiArai 0:5b88d5760320 521 st->st_size = f.fsize;
kenjiArai 0:5b88d5760320 522 st->st_mode = 0;
kenjiArai 0:5b88d5760320 523 st->st_mode |= (f.fattrib & AM_DIR) ? S_IFDIR : S_IFREG;
kenjiArai 0:5b88d5760320 524 st->st_mode |= (f.fattrib & AM_RDO) ?
kenjiArai 0:5b88d5760320 525 (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) :
kenjiArai 0:5b88d5760320 526 (S_IRWXU | S_IRWXG | S_IRWXO);
kenjiArai 0:5b88d5760320 527 #endif /* TOOLCHAIN_GCC */
kenjiArai 0:5b88d5760320 528 unlock();
kenjiArai 0:5b88d5760320 529
kenjiArai 0:5b88d5760320 530 return 0;
kenjiArai 0:5b88d5760320 531 }
kenjiArai 0:5b88d5760320 532
kenjiArai 0:5b88d5760320 533 int FATFileSystem::statvfs(const char *path, struct statvfs *buf)
kenjiArai 0:5b88d5760320 534 {
kenjiArai 0:5b88d5760320 535
kenjiArai 0:5b88d5760320 536 memset(buf, 0, sizeof(struct statvfs));
kenjiArai 0:5b88d5760320 537 FATFS *fs;
kenjiArai 0:5b88d5760320 538 DWORD fre_clust;
kenjiArai 0:5b88d5760320 539
kenjiArai 0:5b88d5760320 540 lock();
kenjiArai 0:5b88d5760320 541 FRESULT res = f_getfree(_fsid, &fre_clust, &fs);
kenjiArai 0:5b88d5760320 542 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 543 unlock();
kenjiArai 0:5b88d5760320 544 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 545 }
kenjiArai 0:5b88d5760320 546
kenjiArai 0:5b88d5760320 547 buf->f_bsize = fs->ssize;
kenjiArai 0:5b88d5760320 548 buf->f_frsize = fs->ssize;
kenjiArai 0:5b88d5760320 549 buf->f_blocks = (fs->n_fatent - 2) * fs->csize;
kenjiArai 0:5b88d5760320 550 buf->f_bfree = fre_clust * fs->csize;
kenjiArai 0:5b88d5760320 551 buf->f_bavail = buf->f_bfree;
kenjiArai 0:5b88d5760320 552 #if FF_USE_LFN
kenjiArai 0:5b88d5760320 553 buf->f_namemax = FF_LFN_BUF;
kenjiArai 0:5b88d5760320 554 #else
kenjiArai 0:5b88d5760320 555 buf->f_namemax = FF_SFN_BUF;
kenjiArai 0:5b88d5760320 556 #endif
kenjiArai 0:5b88d5760320 557
kenjiArai 0:5b88d5760320 558 unlock();
kenjiArai 0:5b88d5760320 559 return 0;
kenjiArai 0:5b88d5760320 560 }
kenjiArai 0:5b88d5760320 561
kenjiArai 0:5b88d5760320 562 void FATFileSystem::lock()
kenjiArai 0:5b88d5760320 563 {
kenjiArai 0:5b88d5760320 564 _ffs_mutex->lock();
kenjiArai 0:5b88d5760320 565 }
kenjiArai 0:5b88d5760320 566
kenjiArai 0:5b88d5760320 567 void FATFileSystem::unlock()
kenjiArai 0:5b88d5760320 568 {
kenjiArai 0:5b88d5760320 569 _ffs_mutex->unlock();
kenjiArai 0:5b88d5760320 570 }
kenjiArai 0:5b88d5760320 571
kenjiArai 0:5b88d5760320 572
kenjiArai 0:5b88d5760320 573 ////// File operations //////
kenjiArai 0:5b88d5760320 574 int FATFileSystem::file_open(fs_file_t *file, const char *path, int flags)
kenjiArai 0:5b88d5760320 575 {
kenjiArai 0:5b88d5760320 576 debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%d]\n", path, getName(), _id);
kenjiArai 0:5b88d5760320 577
kenjiArai 0:5b88d5760320 578 FIL *fh = new FIL;
kenjiArai 0:5b88d5760320 579 Deferred<const char *> fpath = fat_path_prefix(_id, path);
kenjiArai 0:5b88d5760320 580
kenjiArai 0:5b88d5760320 581 /* POSIX flags -> FatFS open mode */
kenjiArai 0:5b88d5760320 582 BYTE openmode;
kenjiArai 0:5b88d5760320 583 if (flags & O_RDWR) {
kenjiArai 0:5b88d5760320 584 openmode = FA_READ | FA_WRITE;
kenjiArai 0:5b88d5760320 585 } else if (flags & O_WRONLY) {
kenjiArai 0:5b88d5760320 586 openmode = FA_WRITE;
kenjiArai 0:5b88d5760320 587 } else {
kenjiArai 0:5b88d5760320 588 openmode = FA_READ;
kenjiArai 0:5b88d5760320 589 }
kenjiArai 0:5b88d5760320 590
kenjiArai 0:5b88d5760320 591 if (flags & O_CREAT) {
kenjiArai 0:5b88d5760320 592 if (flags & O_TRUNC) {
kenjiArai 0:5b88d5760320 593 openmode |= FA_CREATE_ALWAYS;
kenjiArai 0:5b88d5760320 594 } else {
kenjiArai 0:5b88d5760320 595 openmode |= FA_OPEN_ALWAYS;
kenjiArai 0:5b88d5760320 596 }
kenjiArai 0:5b88d5760320 597 }
kenjiArai 0:5b88d5760320 598
kenjiArai 0:5b88d5760320 599 if (flags & O_APPEND) {
kenjiArai 0:5b88d5760320 600 openmode |= FA_OPEN_APPEND;
kenjiArai 0:5b88d5760320 601 }
kenjiArai 0:5b88d5760320 602
kenjiArai 0:5b88d5760320 603 lock();
kenjiArai 0:5b88d5760320 604 FRESULT res = f_open(fh, fpath, openmode);
kenjiArai 0:5b88d5760320 605
kenjiArai 0:5b88d5760320 606 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 607 unlock();
kenjiArai 0:5b88d5760320 608 debug_if(FFS_DBG, "f_open('w') failed: %d\n", res);
kenjiArai 0:5b88d5760320 609 delete fh;
kenjiArai 0:5b88d5760320 610 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 611 }
kenjiArai 0:5b88d5760320 612
kenjiArai 0:5b88d5760320 613 unlock();
kenjiArai 0:5b88d5760320 614
kenjiArai 0:5b88d5760320 615 *file = fh;
kenjiArai 0:5b88d5760320 616 return 0;
kenjiArai 0:5b88d5760320 617 }
kenjiArai 0:5b88d5760320 618
kenjiArai 0:5b88d5760320 619 int FATFileSystem::file_close(fs_file_t file)
kenjiArai 0:5b88d5760320 620 {
kenjiArai 0:5b88d5760320 621 FIL *fh = static_cast<FIL *>(file);
kenjiArai 0:5b88d5760320 622
kenjiArai 0:5b88d5760320 623 lock();
kenjiArai 0:5b88d5760320 624 FRESULT res = f_close(fh);
kenjiArai 0:5b88d5760320 625 unlock();
kenjiArai 0:5b88d5760320 626
kenjiArai 0:5b88d5760320 627 delete fh;
kenjiArai 0:5b88d5760320 628 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 629 }
kenjiArai 0:5b88d5760320 630
kenjiArai 0:5b88d5760320 631 ssize_t FATFileSystem::file_read(fs_file_t file, void *buffer, size_t len)
kenjiArai 0:5b88d5760320 632 {
kenjiArai 0:5b88d5760320 633 FIL *fh = static_cast<FIL *>(file);
kenjiArai 0:5b88d5760320 634
kenjiArai 0:5b88d5760320 635 lock();
kenjiArai 0:5b88d5760320 636 UINT n;
kenjiArai 0:5b88d5760320 637 FRESULT res = f_read(fh, buffer, len, &n);
kenjiArai 0:5b88d5760320 638 unlock();
kenjiArai 0:5b88d5760320 639
kenjiArai 0:5b88d5760320 640 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 641 debug_if(FFS_DBG, "f_read() failed: %d\n", res);
kenjiArai 0:5b88d5760320 642 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 643 } else {
kenjiArai 0:5b88d5760320 644 return n;
kenjiArai 0:5b88d5760320 645 }
kenjiArai 0:5b88d5760320 646 }
kenjiArai 0:5b88d5760320 647
kenjiArai 0:5b88d5760320 648 ssize_t FATFileSystem::file_write(fs_file_t file, const void *buffer, size_t len)
kenjiArai 0:5b88d5760320 649 {
kenjiArai 0:5b88d5760320 650 FIL *fh = static_cast<FIL *>(file);
kenjiArai 0:5b88d5760320 651
kenjiArai 0:5b88d5760320 652 lock();
kenjiArai 0:5b88d5760320 653 UINT n;
kenjiArai 0:5b88d5760320 654 FRESULT res = f_write(fh, buffer, len, &n);
kenjiArai 0:5b88d5760320 655 unlock();
kenjiArai 0:5b88d5760320 656
kenjiArai 0:5b88d5760320 657 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 658 debug_if(FFS_DBG, "f_write() failed: %d", res);
kenjiArai 0:5b88d5760320 659 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 660 } else {
kenjiArai 0:5b88d5760320 661 return n;
kenjiArai 0:5b88d5760320 662 }
kenjiArai 0:5b88d5760320 663 }
kenjiArai 0:5b88d5760320 664
kenjiArai 0:5b88d5760320 665 int FATFileSystem::file_sync(fs_file_t file)
kenjiArai 0:5b88d5760320 666 {
kenjiArai 0:5b88d5760320 667 FIL *fh = static_cast<FIL *>(file);
kenjiArai 0:5b88d5760320 668
kenjiArai 0:5b88d5760320 669 lock();
kenjiArai 0:5b88d5760320 670 FRESULT res = f_sync(fh);
kenjiArai 0:5b88d5760320 671 unlock();
kenjiArai 0:5b88d5760320 672
kenjiArai 0:5b88d5760320 673 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 674 debug_if(FFS_DBG, "f_sync() failed: %d\n", res);
kenjiArai 0:5b88d5760320 675 }
kenjiArai 0:5b88d5760320 676 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 677 }
kenjiArai 0:5b88d5760320 678
kenjiArai 0:5b88d5760320 679 off_t FATFileSystem::file_seek(fs_file_t file, off_t offset, int whence)
kenjiArai 0:5b88d5760320 680 {
kenjiArai 0:5b88d5760320 681 FIL *fh = static_cast<FIL *>(file);
kenjiArai 0:5b88d5760320 682
kenjiArai 0:5b88d5760320 683 lock();
kenjiArai 0:5b88d5760320 684 if (whence == SEEK_END) {
kenjiArai 0:5b88d5760320 685 offset += f_size(fh);
kenjiArai 0:5b88d5760320 686 } else if (whence == SEEK_CUR) {
kenjiArai 0:5b88d5760320 687 offset += f_tell(fh);
kenjiArai 0:5b88d5760320 688 }
kenjiArai 0:5b88d5760320 689
kenjiArai 0:5b88d5760320 690 FRESULT res = f_lseek(fh, offset);
kenjiArai 0:5b88d5760320 691 off_t noffset = fh->fptr;
kenjiArai 0:5b88d5760320 692 unlock();
kenjiArai 0:5b88d5760320 693
kenjiArai 0:5b88d5760320 694 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 695 debug_if(FFS_DBG, "lseek failed: %d\n", res);
kenjiArai 0:5b88d5760320 696 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 697 } else {
kenjiArai 0:5b88d5760320 698 return noffset;
kenjiArai 0:5b88d5760320 699 }
kenjiArai 0:5b88d5760320 700 }
kenjiArai 0:5b88d5760320 701
kenjiArai 0:5b88d5760320 702 off_t FATFileSystem::file_tell(fs_file_t file)
kenjiArai 0:5b88d5760320 703 {
kenjiArai 0:5b88d5760320 704 FIL *fh = static_cast<FIL *>(file);
kenjiArai 0:5b88d5760320 705
kenjiArai 0:5b88d5760320 706 lock();
kenjiArai 0:5b88d5760320 707 off_t res = f_tell(fh);
kenjiArai 0:5b88d5760320 708 unlock();
kenjiArai 0:5b88d5760320 709
kenjiArai 0:5b88d5760320 710 return res;
kenjiArai 0:5b88d5760320 711 }
kenjiArai 0:5b88d5760320 712
kenjiArai 0:5b88d5760320 713 off_t FATFileSystem::file_size(fs_file_t file)
kenjiArai 0:5b88d5760320 714 {
kenjiArai 0:5b88d5760320 715 FIL *fh = static_cast<FIL *>(file);
kenjiArai 0:5b88d5760320 716
kenjiArai 0:5b88d5760320 717 lock();
kenjiArai 0:5b88d5760320 718 off_t res = f_size(fh);
kenjiArai 0:5b88d5760320 719 unlock();
kenjiArai 0:5b88d5760320 720
kenjiArai 0:5b88d5760320 721 return res;
kenjiArai 0:5b88d5760320 722 }
kenjiArai 0:5b88d5760320 723
kenjiArai 0:5b88d5760320 724 int FATFileSystem::file_truncate(fs_file_t file, off_t length)
kenjiArai 0:5b88d5760320 725 {
kenjiArai 0:5b88d5760320 726 FIL *fh = static_cast<FIL *>(file);
kenjiArai 0:5b88d5760320 727
kenjiArai 0:5b88d5760320 728 lock();
kenjiArai 0:5b88d5760320 729 // save current position
kenjiArai 0:5b88d5760320 730 FSIZE_t oldoff = f_tell(fh);
kenjiArai 0:5b88d5760320 731
kenjiArai 0:5b88d5760320 732 // seek to new file size and truncate
kenjiArai 0:5b88d5760320 733 FRESULT res = f_lseek(fh, length);
kenjiArai 0:5b88d5760320 734 if (res) {
kenjiArai 0:5b88d5760320 735 unlock();
kenjiArai 0:5b88d5760320 736 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 737 }
kenjiArai 0:5b88d5760320 738
kenjiArai 0:5b88d5760320 739 res = f_truncate(fh);
kenjiArai 0:5b88d5760320 740 if (res) {
kenjiArai 0:5b88d5760320 741 unlock();
kenjiArai 0:5b88d5760320 742 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 743 }
kenjiArai 0:5b88d5760320 744
kenjiArai 0:5b88d5760320 745 // restore old position
kenjiArai 0:5b88d5760320 746 res = f_lseek(fh, oldoff);
kenjiArai 0:5b88d5760320 747 if (res) {
kenjiArai 0:5b88d5760320 748 unlock();
kenjiArai 0:5b88d5760320 749 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 750 }
kenjiArai 0:5b88d5760320 751
kenjiArai 0:5b88d5760320 752 return 0;
kenjiArai 0:5b88d5760320 753 }
kenjiArai 0:5b88d5760320 754
kenjiArai 0:5b88d5760320 755
kenjiArai 0:5b88d5760320 756 ////// Dir operations //////
kenjiArai 0:5b88d5760320 757 int FATFileSystem::dir_open(fs_dir_t *dir, const char *path)
kenjiArai 0:5b88d5760320 758 {
kenjiArai 0:5b88d5760320 759 FATFS_DIR *dh = new FATFS_DIR;
kenjiArai 0:5b88d5760320 760 Deferred<const char *> fpath = fat_path_prefix(_id, path);
kenjiArai 0:5b88d5760320 761
kenjiArai 0:5b88d5760320 762 lock();
kenjiArai 0:5b88d5760320 763 FRESULT res = f_opendir(dh, fpath);
kenjiArai 0:5b88d5760320 764 unlock();
kenjiArai 0:5b88d5760320 765
kenjiArai 0:5b88d5760320 766 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 767 debug_if(FFS_DBG, "f_opendir() failed: %d\n", res);
kenjiArai 0:5b88d5760320 768 delete dh;
kenjiArai 0:5b88d5760320 769 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 770 }
kenjiArai 0:5b88d5760320 771
kenjiArai 0:5b88d5760320 772 *dir = dh;
kenjiArai 0:5b88d5760320 773 return 0;
kenjiArai 0:5b88d5760320 774 }
kenjiArai 0:5b88d5760320 775
kenjiArai 0:5b88d5760320 776 int FATFileSystem::dir_close(fs_dir_t dir)
kenjiArai 0:5b88d5760320 777 {
kenjiArai 0:5b88d5760320 778 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir);
kenjiArai 0:5b88d5760320 779
kenjiArai 0:5b88d5760320 780 lock();
kenjiArai 0:5b88d5760320 781 FRESULT res = f_closedir(dh);
kenjiArai 0:5b88d5760320 782 unlock();
kenjiArai 0:5b88d5760320 783
kenjiArai 0:5b88d5760320 784 delete dh;
kenjiArai 0:5b88d5760320 785 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 786 }
kenjiArai 0:5b88d5760320 787
kenjiArai 0:5b88d5760320 788 ssize_t FATFileSystem::dir_read(fs_dir_t dir, struct dirent *ent)
kenjiArai 0:5b88d5760320 789 {
kenjiArai 0:5b88d5760320 790 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir);
kenjiArai 0:5b88d5760320 791 FILINFO finfo;
kenjiArai 0:5b88d5760320 792
kenjiArai 0:5b88d5760320 793 lock();
kenjiArai 0:5b88d5760320 794 FRESULT res = f_readdir(dh, &finfo);
kenjiArai 0:5b88d5760320 795 unlock();
kenjiArai 0:5b88d5760320 796
kenjiArai 0:5b88d5760320 797 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 798 return fat_error_remap(res);
kenjiArai 0:5b88d5760320 799 } else if (finfo.fname[0] == 0) {
kenjiArai 0:5b88d5760320 800 return 0;
kenjiArai 0:5b88d5760320 801 }
kenjiArai 0:5b88d5760320 802
kenjiArai 0:5b88d5760320 803 ent->d_type = (finfo.fattrib & AM_DIR) ? DT_DIR : DT_REG;
kenjiArai 0:5b88d5760320 804
kenjiArai 0:5b88d5760320 805 #if FF_USE_LFN
kenjiArai 0:5b88d5760320 806 if (ent->d_name[0] == 0) {
kenjiArai 0:5b88d5760320 807 // No long filename so use short filename.
kenjiArai 0:5b88d5760320 808 strncpy(ent->d_name, finfo.fname, FF_LFN_BUF);
kenjiArai 0:5b88d5760320 809 }
kenjiArai 0:5b88d5760320 810 #else
kenjiArai 0:5b88d5760320 811 strncpy(ent->d_name, finfo.fname, FF_SFN_BUF);
kenjiArai 0:5b88d5760320 812 #endif
kenjiArai 0:5b88d5760320 813
kenjiArai 0:5b88d5760320 814 return 1;
kenjiArai 0:5b88d5760320 815 }
kenjiArai 0:5b88d5760320 816
kenjiArai 0:5b88d5760320 817 void FATFileSystem::dir_seek(fs_dir_t dir, off_t offset)
kenjiArai 0:5b88d5760320 818 {
kenjiArai 0:5b88d5760320 819 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir);
kenjiArai 0:5b88d5760320 820 off_t dptr = static_cast<off_t>(dh->dptr);
kenjiArai 0:5b88d5760320 821
kenjiArai 0:5b88d5760320 822 lock();
kenjiArai 0:5b88d5760320 823
kenjiArai 0:5b88d5760320 824 if (offset < dptr) {
kenjiArai 0:5b88d5760320 825 f_rewinddir(dh);
kenjiArai 0:5b88d5760320 826 }
kenjiArai 0:5b88d5760320 827 while (dptr < offset) {
kenjiArai 0:5b88d5760320 828 FILINFO finfo;
kenjiArai 0:5b88d5760320 829 FRESULT res;
kenjiArai 0:5b88d5760320 830
kenjiArai 0:5b88d5760320 831 res = f_readdir(dh, &finfo);
kenjiArai 0:5b88d5760320 832 dptr = dh->dptr;
kenjiArai 0:5b88d5760320 833 if (res != FR_OK) {
kenjiArai 0:5b88d5760320 834 break;
kenjiArai 0:5b88d5760320 835 } else if (finfo.fname[0] == 0) {
kenjiArai 0:5b88d5760320 836 break;
kenjiArai 0:5b88d5760320 837 }
kenjiArai 0:5b88d5760320 838 }
kenjiArai 0:5b88d5760320 839 unlock();
kenjiArai 0:5b88d5760320 840 }
kenjiArai 0:5b88d5760320 841
kenjiArai 0:5b88d5760320 842 off_t FATFileSystem::dir_tell(fs_dir_t dir)
kenjiArai 0:5b88d5760320 843 {
kenjiArai 0:5b88d5760320 844 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir);
kenjiArai 0:5b88d5760320 845
kenjiArai 0:5b88d5760320 846 lock();
kenjiArai 0:5b88d5760320 847 off_t offset = dh->dptr;
kenjiArai 0:5b88d5760320 848 unlock();
kenjiArai 0:5b88d5760320 849
kenjiArai 0:5b88d5760320 850 return offset;
kenjiArai 0:5b88d5760320 851 }
kenjiArai 0:5b88d5760320 852
kenjiArai 0:5b88d5760320 853 void FATFileSystem::dir_rewind(fs_dir_t dir)
kenjiArai 0:5b88d5760320 854 {
kenjiArai 0:5b88d5760320 855 FATFS_DIR *dh = static_cast<FATFS_DIR *>(dir);
kenjiArai 0:5b88d5760320 856
kenjiArai 0:5b88d5760320 857 lock();
kenjiArai 0:5b88d5760320 858 f_rewinddir(dh);
kenjiArai 0:5b88d5760320 859 unlock();
kenjiArai 0:5b88d5760320 860 }
kenjiArai 0:5b88d5760320 861
kenjiArai 0:5b88d5760320 862 } // namespace mbed