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