BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:55:34 2018 +0000
Revision:
2:798925c9e4a8
Parent:
1:9c5af431a1f1
bluetooth

Who changed what in which revision?

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