the do / gr-peach-opencv-project

Fork of gr-peach-opencv-project by the do

Committer:
thedo
Date:
Thu Jun 29 11:00:41 2017 +0000
Revision:
166:3a9487d57a5c
This is Opencv 3.1 project on GR-PEACH board

Who changed what in which revision?

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