Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pff.cpp
00001 /*----------------------------------------------------------------------------/ 00002 / Petit FatFs - FAT file system module R0.02 (C)ChaN, 2009 00003 /-----------------------------------------------------------------------------/ 00004 / Petit FatFs module is an open source software to implement FAT file system to 00005 / small embedded systems. This is a free software and is opened for education, 00006 / research and commercial developments under license policy of following trems. 00007 / 00008 / Copyright (C) 2009, ChaN, all right reserved. 00009 / 00010 / * The Petit FatFs module is a free software and there is NO WARRANTY. 00011 / * No restriction on use. You can use, modify and redistribute it for 00012 / personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY. 00013 / * Redistributions of source code must retain the above copyright notice. 00014 / 00015 /-----------------------------------------------------------------------------/ 00016 / Jun 15,'09 R0.01a First release. (Branched from FatFs R0.07b.) 00017 / 00018 / Dec 14,'09 R0.02 Added multiple code page support. 00019 / Added write funciton. 00020 / Changed stream read mode interface. 00021 /----------------------------------------------------------------------------*/ 00022 00023 00024 #include "pff.h" /* Petit FatFs configurations and declarations */ 00025 #include "diskio.h" /* Declarations of low level disk I/O functions */ 00026 00027 namespace PFFS { 00028 00029 /*-------------------------------------------------------------------------- 00030 00031 Private Functions 00032 00033 ---------------------------------------------------------------------------*/ 00034 00035 static 00036 FATFS *FatFs; /* Pointer to the file system object (logical drive) */ 00037 00038 00039 00040 /*-----------------------------------------------------------------------*/ 00041 /* String functions */ 00042 /*-----------------------------------------------------------------------*/ 00043 00044 /* Fill memory */ 00045 static 00046 void mem_set (void* dst, int val, int cnt) { 00047 char *d = (char*)dst; 00048 while (cnt--) *d++ = (char)val; 00049 } 00050 00051 /* Compare memory to memory */ 00052 static 00053 int mem_cmp (const void* dst, const void* src, int cnt) { 00054 const char *d = (const char *)dst, *s = (const char *)src; 00055 int r = 0; 00056 while (cnt-- && (r = *d++ - *s++) == 0) ; 00057 return r; 00058 } 00059 00060 00061 00062 /*-----------------------------------------------------------------------*/ 00063 /* FAT access - Read value of a FAT entry */ 00064 /*-----------------------------------------------------------------------*/ 00065 00066 static 00067 CLUST get_fat ( /* 1:IO error, Else:Cluster status */ 00068 CLUST clst /* Cluster# to get the link information */ 00069 ) { 00070 WORD wc, bc, ofs; 00071 BYTE buf[4]; 00072 FATFS *fs = FatFs; 00073 00074 00075 if (clst < 2 || clst >= fs->max_clust) /* Range check */ 00076 return 1; 00077 00078 switch (fs->fs_type) { 00079 case FS_FAT12 : 00080 bc = (WORD)clst; 00081 bc += bc / 2; 00082 ofs = bc % 512; 00083 bc /= 512; 00084 if (ofs != 511) { 00085 if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break; 00086 } else { 00087 if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break; 00088 if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break; 00089 } 00090 wc = LD_WORD(buf); 00091 return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); 00092 00093 case FS_FAT16 : 00094 if (disk_readp(buf, fs->fatbase + clst / 256, (WORD)(((WORD)clst % 256) * 2), 2)) break; 00095 return LD_WORD(buf); 00096 #if _FS_FAT32 00097 case FS_FAT32 : 00098 if (disk_readp(buf, fs->fatbase + clst / 128, (WORD)(((WORD)clst % 128) * 4), 4)) break; 00099 return ((WORD)(((WORD)*(BYTE*)((buf)+1)<<8)|(WORD)*(BYTE*)(buf))) & 0x0FFFFFFF; //return LD_DWORD(buf) & 0x0FFFFFFF; //get rid of out of bounds warning in online IDE 00100 #endif 00101 } 00102 00103 return 1; /* An error occured at the disk I/O layer */ 00104 } 00105 00106 00107 00108 00109 /*-----------------------------------------------------------------------*/ 00110 /* Get sector# from cluster# */ 00111 /*-----------------------------------------------------------------------*/ 00112 00113 static 00114 DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ 00115 CLUST clst /* Cluster# to be converted */ 00116 ) { 00117 FATFS *fs = FatFs; 00118 00119 00120 clst -= 2; 00121 if (clst >= (fs->max_clust - 2)) return 0; /* Invalid cluster# */ 00122 return (DWORD)clst * fs->csize + fs->database; 00123 } 00124 00125 00126 00127 00128 /*-----------------------------------------------------------------------*/ 00129 /* Directory handling - Rewind directory index */ 00130 /*-----------------------------------------------------------------------*/ 00131 00132 static 00133 FRESULT dir_rewind ( 00134 FATDIR *dj /* Pointer to directory object */ 00135 ) { 00136 CLUST clst; 00137 FATFS *fs = FatFs; 00138 00139 00140 dj->index = 0; 00141 clst = dj->sclust; 00142 if (clst == 1 || clst >= fs->max_clust) /* Check start cluster range */ 00143 return FR_DISK_ERR; 00144 #if _FS_FAT32 00145 if (!clst && fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ 00146 clst = fs->dirbase; 00147 #endif 00148 dj->clust = clst; /* Current cluster */ 00149 dj->sect = clst ? clust2sect(clst) : fs->dirbase; /* Current sector */ 00150 00151 return FR_OK; /* Seek succeeded */ 00152 } 00153 00154 00155 00156 00157 /*-----------------------------------------------------------------------*/ 00158 /* Directory handling - Move directory index next */ 00159 /*-----------------------------------------------------------------------*/ 00160 00161 static 00162 FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table */ 00163 FATDIR *dj /* Pointer to directory object */ 00164 ) { 00165 CLUST clst; 00166 WORD i; 00167 FATFS *fs = FatFs; 00168 00169 00170 i = dj->index + 1; 00171 if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ 00172 return FR_NO_FILE; 00173 00174 if (!(i & (16-1))) { /* Sector changed? */ 00175 dj->sect++; /* Next sector */ 00176 00177 if (dj->clust == 0) { /* Static table */ 00178 if (i >= fs->n_rootdir) /* Report EOT when end of table */ 00179 return FR_NO_FILE; 00180 } else { /* Dynamic table */ 00181 if (((i / 16) & (fs->csize-1)) == 0) { /* Cluster changed? */ 00182 clst = get_fat(dj->clust); /* Get next cluster */ 00183 if (clst <= 1) return FR_DISK_ERR; 00184 if (clst >= fs->max_clust) /* When it reached end of dynamic table */ 00185 return FR_NO_FILE; /* Report EOT */ 00186 dj->clust = clst; /* Initialize data for new cluster */ 00187 dj->sect = clust2sect(clst); 00188 } 00189 } 00190 } 00191 00192 dj->index = i; 00193 00194 return FR_OK; 00195 } 00196 00197 00198 00199 00200 /*-----------------------------------------------------------------------*/ 00201 /* Directory handling - Find an object in the directory */ 00202 /*-----------------------------------------------------------------------*/ 00203 00204 static 00205 FRESULT dir_find ( 00206 FATDIR *dj /* Pointer to the directory object linked to the file name */ 00207 ) { 00208 FRESULT res; 00209 BYTE c, *dir; 00210 00211 00212 res = dir_rewind(dj); /* Rewind directory object */ 00213 if (res != FR_OK) return res; 00214 00215 dir = FatFs->buf; 00216 do { 00217 res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32) /* Read an entry */ 00218 ? FR_DISK_ERR : FR_OK; 00219 if (res != FR_OK) break; 00220 c = dir[DIR_Name]; /* First character */ 00221 if (c == 0) { 00222 res = FR_NO_FILE; /* Reached to end of table */ 00223 break; 00224 } 00225 if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ 00226 break; 00227 res = dir_next(dj); /* Next entry */ 00228 } while (res == FR_OK); 00229 00230 return res; 00231 } 00232 00233 00234 00235 00236 /*-----------------------------------------------------------------------*/ 00237 /* Read an object from the directory */ 00238 /*-----------------------------------------------------------------------*/ 00239 #if _USE_DIR 00240 static 00241 FRESULT dir_read ( 00242 FATDIR *dj /* Pointer to the directory object to store read object name */ 00243 ) { 00244 FRESULT res; 00245 BYTE a, c, *dir; 00246 00247 00248 res = FR_NO_FILE; 00249 dir = FatFs->buf; 00250 while (dj->sect) { 00251 res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32) /* Read an entry */ 00252 ? FR_DISK_ERR : FR_OK; 00253 if (res != FR_OK) break; 00254 c = dir[DIR_Name]; 00255 if (c == 0) { 00256 res = FR_NO_FILE; /* Reached to end of table */ 00257 break; 00258 } 00259 a = dir[DIR_Attr] & AM_MASK; 00260 if (c != 0xE5 && c != '.' && !(a & AM_VOL)) /* Is it a valid entry? */ 00261 break; 00262 res = dir_next(dj); /* Next entry */ 00263 if (res != FR_OK) break; 00264 } 00265 00266 if (res != FR_OK) dj->sect = 0; 00267 00268 return res; 00269 } 00270 #endif 00271 00272 00273 00274 /*-----------------------------------------------------------------------*/ 00275 /* Pick a segment and create the object name in directory form */ 00276 /*-----------------------------------------------------------------------*/ 00277 00278 #ifdef _EXCVT 00279 static const BYTE cvt[] = _EXCVT; 00280 #endif 00281 00282 static 00283 FRESULT create_name ( 00284 FATDIR *dj, /* Pointer to the directory object */ 00285 const char **path /* Pointer to pointer to the segment in the path string */ 00286 ) { 00287 BYTE c, d, ni, si, i, *sfn; 00288 const char *p; 00289 00290 /* Create file name in directory form */ 00291 sfn = dj->fn; 00292 mem_set(sfn, ' ', 11); 00293 si = i = 0; 00294 ni = 8; 00295 p = *path; 00296 for (;;) { 00297 c = p[si++]; 00298 if (c <= ' ' || c == '/') break; /* Break on end of segment */ 00299 if (c == '.' || i >= ni) { 00300 if (ni != 8 || c != '.') break; 00301 i = 8; 00302 ni = 11; 00303 continue; 00304 } 00305 #ifdef _EXCVT 00306 if (c >= 0x80) /* To upper extended char (SBCS) */ 00307 c = cvt[c - 0x80]; 00308 #endif 00309 if (IsDBCS1(c) && i >= ni - 1) { /* DBC 1st byte? */ 00310 d = p[si++]; /* Get 2nd byte */ 00311 sfn[i++] = c; 00312 sfn[i++] = d; 00313 } else { /* Single byte code */ 00314 if (IsLower(c)) c -= 0x20; /* toupper */ 00315 sfn[i++] = c; 00316 } 00317 } 00318 *path = &p[si]; /* Rerurn pointer to the next segment */ 00319 00320 sfn[11] = (c <= ' ') ? 1 : 0; /* Set last segment flag if end of path */ 00321 00322 return FR_OK; 00323 } 00324 00325 00326 00327 00328 /*-----------------------------------------------------------------------*/ 00329 /* Get file information from directory entry */ 00330 /*-----------------------------------------------------------------------*/ 00331 #if _USE_DIR 00332 static 00333 void get_fileinfo ( /* No return code */ 00334 FATDIR *dj, /* Pointer to the directory object */ 00335 FILINFO *fno /* Pointer to store the file information */ 00336 ) { 00337 BYTE i, c, *dir; 00338 char *p; 00339 00340 00341 p = fno->fname; 00342 if (dj->sect) { 00343 dir = FatFs->buf; 00344 for (i = 0; i < 8; i++) { /* Copy file name body */ 00345 c = dir[i]; 00346 if (c == ' ') break; 00347 if (c == 0x05) c = 0xE5; 00348 *p++ = c; 00349 } 00350 if (dir[8] != ' ') { /* Copy file name extension */ 00351 *p++ = '.'; 00352 for (i = 8; i < 11; i++) { 00353 c = dir[i]; 00354 if (c == ' ') break; 00355 *p++ = c; 00356 } 00357 } 00358 fno->fattrib = dir[DIR_Attr]; /* Attribute */ 00359 fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ 00360 fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ 00361 fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ 00362 } 00363 *p = 0; 00364 } 00365 #endif /* _USE_DIR */ 00366 00367 00368 00369 /*-----------------------------------------------------------------------*/ 00370 /* Follow a file path */ 00371 /*-----------------------------------------------------------------------*/ 00372 00373 static 00374 FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ 00375 FATDIR *dj, /* Directory object to return last directory and found object */ 00376 const char *path /* Full-path string to find a file or directory */ 00377 ) { 00378 FRESULT res; 00379 BYTE *dir; 00380 00381 00382 while (*path == ' ') path++; /* Skip leading spaces */ 00383 if (*path == '/') path++; /* Strip heading separator */ 00384 dj->sclust = 0; /* Set start directory (always root dir) */ 00385 00386 if ((BYTE)*path <= ' ') { /* Null path means the root directory */ 00387 res = dir_rewind(dj); 00388 FatFs->buf[0] = 0; 00389 00390 } else { /* Follow path */ 00391 for (;;) { 00392 res = create_name(dj, &path); /* Get a segment */ 00393 if (res != FR_OK) break; 00394 res = dir_find(dj); /* Find it */ 00395 if (res != FR_OK) { /* Could not find the object */ 00396 if (res == FR_NO_FILE && !*(dj->fn+11)) 00397 res = FR_NO_PATH; 00398 break; 00399 } 00400 if (*(dj->fn+11)) break; /* Last segment match. Function completed. */ 00401 dir = FatFs->buf; /* There is next segment. Follow the sub directory */ 00402 if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ 00403 res = FR_NO_PATH; 00404 break; 00405 } 00406 dj->sclust = 00407 #if _FS_FAT32 00408 ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | 00409 #endif 00410 LD_WORD(dir+DIR_FstClusLO); 00411 } 00412 } 00413 00414 return res; 00415 } 00416 00417 00418 00419 00420 /*-----------------------------------------------------------------------*/ 00421 /* Check a sector if it is an FAT boot record */ 00422 /*-----------------------------------------------------------------------*/ 00423 00424 static 00425 __attribute__((section(".SD_Code"))) BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */ 00426 BYTE *buf, /* Working buffer */ 00427 DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ 00428 ) { 00429 if (disk_readp(buf, sect, 510, 2)) /* Read the boot sector */ 00430 return 3; 00431 if (LD_WORD(buf) != 0xAA55) /* Check record signature */ 00432 return 2; 00433 00434 if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146) /* Check FAT12/16 */ 00435 return 0; 00436 #if _FS_FAT32 00437 if (!disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146) /* Check FAT32 */ 00438 return 0; 00439 #endif 00440 return 1; 00441 } 00442 00443 00444 00445 00446 /*-------------------------------------------------------------------------- 00447 00448 Public Functions 00449 00450 --------------------------------------------------------------------------*/ 00451 00452 00453 00454 /*-----------------------------------------------------------------------*/ 00455 /* Mount/Unmount a Locical Drive */ 00456 /*-----------------------------------------------------------------------*/ 00457 00458 __attribute__((section(".SD_Code"))) FRESULT pf_mount ( 00459 FATFS *fs /* Pointer to new file system object (NULL: Unmount) */ 00460 ) { 00461 BYTE fmt, buf[36]; 00462 DWORD bsect, fsize, tsect, mclst; 00463 00464 00465 FatFs = 0; 00466 if (!fs) return FR_OK; /* Unregister fs object */ 00467 00468 if (disk_initialize() & STA_NOINIT) /* Check if the drive is ready or not */ 00469 return FR_NOT_READY; 00470 00471 /* Search FAT partition on the drive */ 00472 bsect = 0; 00473 fmt = check_fs(buf, bsect); /* Check sector 0 as an SFD format */ 00474 if (fmt == 1) { /* Not an FAT boot record, it may be FDISK format */ 00475 /* Check a partition listed in top of the partition table */ 00476 if (disk_readp(buf, bsect, MBR_Table, 16)) { /* 1st partition entry */ 00477 fmt = 3; 00478 } else { 00479 if (buf[4]) { /* Is the partition existing? */ 00480 bsect = LD_DWORD(&buf[8]); /* Partition offset in LBA */ 00481 fmt = check_fs(buf, bsect); /* Check the partition */ 00482 } 00483 } 00484 } 00485 if (fmt == 3) return FR_DISK_ERR; 00486 if (fmt) return FR_NO_FILESYSTEM; /* No valid FAT patition is found */ 00487 00488 /* Initialize the file system object */ 00489 if (disk_readp(buf, bsect, 13, sizeof(buf))) return FR_DISK_ERR; 00490 00491 fsize = LD_WORD(buf+BPB_FATSz16-13); /* Number of sectors per FAT */ 00492 if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13); 00493 00494 fsize *= buf[BPB_NumFATs-13]; /* Number of sectors in FAT area */ 00495 fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */ 00496 fs->csize = buf[BPB_SecPerClus-13]; /* Number of sectors per cluster */ 00497 fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13); /* Nmuber of root directory entries */ 00498 tsect = LD_WORD(buf+BPB_TotSec16-13); /* Number of sectors on the file system */ 00499 if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13); 00500 mclst = (tsect /* Last cluster# + 1 */ 00501 - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16 00502 ) / fs->csize + 2; 00503 fs->max_clust = (CLUST)mclst; 00504 00505 fmt = FS_FAT12; /* Determine the FAT sub type */ 00506 if (mclst >= 0xFF7) fmt = FS_FAT16; /* Number of clusters >= 0xFF5 */ 00507 if (mclst >= 0xFFF7) /* Number of clusters >= 0xFFF5 */ 00508 #if _FS_FAT32 00509 fmt = FS_FAT32; 00510 #else 00511 return FR_NO_FILESYSTEM; 00512 #endif 00513 00514 fs->fs_type = fmt; /* FAT sub-type */ 00515 #if _FS_FAT32 00516 if (fmt == FS_FAT32) 00517 fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13)); /* Root directory start cluster */ 00518 else 00519 #endif 00520 fs->dirbase = fs->fatbase + fsize; /* Root directory start sector (lba) */ 00521 fs->database = fs->fatbase + fsize + fs->n_rootdir / 16; /* Data start sector (lba) */ 00522 00523 fs->flag = 0; 00524 FatFs = fs; 00525 00526 return FR_OK; 00527 } 00528 00529 00530 00531 00532 /*-----------------------------------------------------------------------*/ 00533 /* Open or Create a File */ 00534 /*-----------------------------------------------------------------------*/ 00535 00536 FRESULT pf_open ( 00537 const char *path /* Pointer to the file name */ 00538 ) { 00539 FRESULT res; 00540 FATDIR dj; 00541 BYTE sp[12], dir[32]; 00542 FATFS *fs = FatFs; 00543 00544 00545 if (!fs) /* Check file system */ 00546 return FR_NOT_ENABLED; 00547 00548 fs->flag = 0; 00549 fs->buf = dir; 00550 dj.fn = sp; 00551 res = follow_path(&dj, path); /* Follow the file path */ 00552 if (res != FR_OK) return res; /* Follow failed */ 00553 if (!dir[0] || (dir[DIR_Attr] & AM_DIR)) /* It is a directory */ 00554 return FR_NO_FILE; 00555 00556 fs->org_clust = /* File start cluster */ 00557 #if _FS_FAT32 00558 ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | 00559 #endif 00560 LD_WORD(dir+DIR_FstClusLO); 00561 fs->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ 00562 fs->fptr = 0; /* File pointer */ 00563 fs->flag = FA_OPENED; 00564 00565 return FR_OK; 00566 } 00567 00568 00569 00570 00571 /*-----------------------------------------------------------------------*/ 00572 /* Read File */ 00573 /*-----------------------------------------------------------------------*/ 00574 #if _USE_READ 00575 00576 FRESULT pf_read ( 00577 void* buff, /* Pointer to the read buffer (NULL:Forward data to the stream)*/ 00578 WORD btr, /* Number of bytes to read */ 00579 WORD* br /* Pointer to number of bytes read */ 00580 ) { 00581 DRESULT dr; 00582 CLUST clst; 00583 DWORD sect, remain; 00584 BYTE *rbuff = (BYTE *)buff; 00585 WORD rcnt; 00586 FATFS *fs = FatFs; 00587 00588 00589 *br = 0; 00590 if (!fs) return FR_NOT_ENABLED; /* Check file system */ 00591 if (!(fs->flag & FA_OPENED)) /* Check if opened */ 00592 return FR_NOT_OPENED; 00593 00594 remain = fs->fsize - fs->fptr; 00595 if (btr > remain) btr = (WORD)remain; /* Truncate btr by remaining bytes */ 00596 00597 while (btr) { /* Repeat until all data transferred */ 00598 if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ 00599 if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */ 00600 clst = (fs->fptr == 0) ? /* On the top of the file? */ 00601 fs->org_clust : get_fat(fs->curr_clust); 00602 if (clst <= 1) goto fr_abort; 00603 fs->curr_clust = clst; /* Update current cluster */ 00604 fs->csect = 0; /* Reset sector offset in the cluster */ 00605 } 00606 sect = clust2sect(fs->curr_clust); /* Get current sector */ 00607 if (!sect) goto fr_abort; 00608 fs->dsect = sect + fs->csect++; 00609 } 00610 rcnt = 512 - ((WORD)fs->fptr % 512); /* Get partial sector data from sector buffer */ 00611 if (rcnt > btr) rcnt = btr; 00612 dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt); 00613 if (dr) goto fr_abort; 00614 fs->fptr += rcnt; 00615 rbuff += rcnt; /* Update pointers and counters */ 00616 btr -= rcnt; 00617 *br += rcnt; 00618 } 00619 00620 return FR_OK; 00621 00622 fr_abort: 00623 fs->flag = 0; 00624 return FR_DISK_ERR; 00625 } 00626 #endif 00627 00628 00629 00630 /*-----------------------------------------------------------------------*/ 00631 /* Write File */ 00632 /*-----------------------------------------------------------------------*/ 00633 #if _USE_WRITE 00634 00635 FRESULT pf_write ( 00636 const void* buff, /* Pointer to the data to be written */ 00637 WORD btw, /* Number of bytes to write (0:Finalize the current write operation) */ 00638 WORD* bw /* Pointer to number of bytes written */ 00639 ) { 00640 CLUST clst; 00641 DWORD sect, remain; 00642 const BYTE *p = (const BYTE *)buff; 00643 WORD wcnt; 00644 FATFS *fs = FatFs; 00645 00646 00647 *bw = 0; 00648 if (!fs) return FR_NOT_ENABLED; /* Check file system */ 00649 if (!(fs->flag & FA_OPENED)) /* Check if opened */ 00650 return FR_NOT_OPENED; 00651 00652 if (!btw) { /* Finalize request */ 00653 if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort; 00654 fs->flag &= ~FA__WIP; 00655 return FR_OK; 00656 } else { /* Write data request */ 00657 if (!(fs->flag & FA__WIP)) /* Round down fptr to the sector boundary */ 00658 fs->fptr &= 0xFFFFFE00; 00659 } 00660 remain = fs->fsize - fs->fptr; 00661 if (btw > remain) btw = (WORD)remain; /* Truncate btw by remaining bytes */ 00662 00663 while (btw) { /* Repeat until all data transferred */ 00664 if (((WORD)fs->fptr % 512) == 0) { /* On the sector boundary? */ 00665 if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */ 00666 clst = (fs->fptr == 0) ? /* On the top of the file? */ 00667 fs->org_clust : get_fat(fs->curr_clust); 00668 if (clst <= 1) goto fw_abort; 00669 fs->curr_clust = clst; /* Update current cluster */ 00670 fs->csect = 0; /* Reset sector offset in the cluster */ 00671 } 00672 sect = clust2sect(fs->curr_clust); /* Get current sector */ 00673 if (!sect) goto fw_abort; 00674 fs->dsect = sect + fs->csect++; 00675 if (disk_writep(0, fs->dsect)) goto fw_abort; /* Initiate a sector write operation */ 00676 fs->flag |= FA__WIP; 00677 } 00678 wcnt = 512 - ((WORD)fs->fptr % 512); /* Number of bytes to write to the sector */ 00679 if (wcnt > btw) wcnt = btw; 00680 if (disk_writep(p, wcnt)) goto fw_abort; /* Send data to the sector */ 00681 fs->fptr += wcnt; 00682 p += wcnt; /* Update pointers and counters */ 00683 btw -= wcnt; 00684 *bw += wcnt; 00685 if (((WORD)fs->fptr % 512) == 0) { 00686 if (disk_writep(0, 0)) goto fw_abort; /* Finalize the currtent secter write operation */ 00687 fs->flag &= ~FA__WIP; 00688 } 00689 } 00690 00691 return FR_OK; 00692 00693 fw_abort: 00694 fs->flag = 0; 00695 return FR_DISK_ERR; 00696 } 00697 #endif 00698 00699 00700 00701 /*-----------------------------------------------------------------------*/ 00702 /* Seek File R/W Pointer */ 00703 /*-----------------------------------------------------------------------*/ 00704 #if _USE_LSEEK 00705 00706 FRESULT pf_lseek ( 00707 DWORD ofs /* File pointer from top of file */ 00708 ) { 00709 CLUST clst; 00710 DWORD bcs, sect, ifptr; 00711 FATFS *fs = FatFs; 00712 00713 00714 if (!fs) return FR_NOT_ENABLED; /* Check file system */ 00715 if (!(fs->flag & FA_OPENED)) /* Check if opened */ 00716 return FR_NOT_OPENED; 00717 00718 if (ofs > fs->fsize) ofs = fs->fsize; /* Clip offset with the file size */ 00719 ifptr = fs->fptr; 00720 fs->fptr = 0; 00721 if (ofs > 0) { 00722 bcs = (DWORD)fs->csize * 512; /* Cluster size (byte) */ 00723 if (ifptr > 0 && 00724 (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ 00725 fs->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ 00726 ofs -= fs->fptr; 00727 clst = fs->curr_clust; 00728 } else { /* When seek to back cluster, */ 00729 clst = fs->org_clust; /* start from the first cluster */ 00730 fs->curr_clust = clst; 00731 } 00732 while (ofs > bcs) { /* Cluster following loop */ 00733 clst = get_fat(clst); /* Follow cluster chain */ 00734 if (clst <= 1 || clst >= fs->max_clust) goto fe_abort; 00735 fs->curr_clust = clst; 00736 fs->fptr += bcs; 00737 ofs -= bcs; 00738 } 00739 fs->fptr += ofs; 00740 sect = clust2sect(clst); /* Current sector */ 00741 if (!sect) goto fe_abort; 00742 fs->csect = (BYTE)(ofs / 512); /* Sector offset in the cluster */ 00743 if (ofs % 512) 00744 fs->dsect = sect + fs->csect++; 00745 } 00746 00747 return FR_OK; 00748 00749 fe_abort: 00750 fs->flag = 0; 00751 return FR_DISK_ERR; 00752 } 00753 #endif 00754 00755 00756 00757 /*-----------------------------------------------------------------------*/ 00758 /* Create a Directroy Object */ 00759 /*-----------------------------------------------------------------------*/ 00760 #if _USE_DIR 00761 00762 FRESULT pf_opendir ( 00763 FATDIR *dj, /* Pointer to directory object to create */ 00764 const char *path /* Pointer to the directory path */ 00765 ) { 00766 FRESULT res; 00767 BYTE sp[12], dir[32]; 00768 FATFS *fs = FatFs; 00769 00770 00771 if (!fs) { /* Check file system */ 00772 res = FR_NOT_ENABLED; 00773 } else { 00774 fs->buf = dir; 00775 dj->fn = sp; 00776 res = follow_path(dj, path); /* Follow the path to the directory */ 00777 if (res == FR_OK) { /* Follow completed */ 00778 if (dir[0]) { /* It is not the root dir */ 00779 if (dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ 00780 dj->sclust = 00781 #if _FS_FAT32 00782 ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | 00783 #endif 00784 LD_WORD(dir+DIR_FstClusLO); 00785 } else { /* The object is not a directory */ 00786 res = FR_NO_PATH; 00787 } 00788 } 00789 if (res == FR_OK) 00790 res = dir_rewind(dj); /* Rewind dir */ 00791 } 00792 if (res == FR_NO_FILE) res = FR_NO_PATH; 00793 } 00794 00795 return res; 00796 } 00797 00798 00799 00800 00801 /*-----------------------------------------------------------------------*/ 00802 /* Read Directory Entry in Sequense */ 00803 /*-----------------------------------------------------------------------*/ 00804 00805 FRESULT pf_readdir ( 00806 FATDIR *dj, /* Pointer to the open directory object */ 00807 FILINFO *fno /* Pointer to file information to return */ 00808 ) { 00809 FRESULT res; 00810 BYTE sp[12], dir[32]; 00811 FATFS *fs = FatFs; 00812 00813 00814 if (!fs) { /* Check file system */ 00815 res = FR_NOT_ENABLED; 00816 } else { 00817 fs->buf = dir; 00818 dj->fn = sp; 00819 if (!fno) { 00820 res = dir_rewind(dj); 00821 } else { 00822 res = dir_read(dj); 00823 if (res == FR_NO_FILE) { 00824 dj->sect = 0; 00825 res = FR_OK; 00826 } 00827 if (res == FR_OK) { /* A valid entry is found */ 00828 get_fileinfo(dj, fno); /* Get the object information */ 00829 res = dir_next(dj); /* Increment index for next */ 00830 if (res == FR_NO_FILE) { 00831 dj->sect = 0; 00832 res = FR_OK; 00833 } 00834 } 00835 } 00836 } 00837 00838 return res; 00839 } 00840 00841 #endif /* _USE_DIR */ 00842 00843 } // namespace PFFS 00844 00845
Generated on Tue Jul 12 2022 21:03:50 by
1.7.2