Knight KE / Mbed OS Game_Master
Committer:
WFKnight
Date:
Thu Jun 21 13:51:43 2018 +0000
Revision:
0:9b3d4731edbb
UART, RTOS, LED

Who changed what in which revision?

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