mbed-os for GR-LYCHEE

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Committer:
dkato
Date:
Fri Feb 02 05:42:23 2018 +0000
Revision:
0:f782d9c66c49
mbed-os for GR-LYCHEE

Who changed what in which revision?

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