FRESULT pf_read ( void* dest, /* Pointer to the destination object */ WORD btr, /* Number of bytes to read (bit15:destination) */ WORD* br /* Pointer to number of bytes read */ ) { DRESULT dr; CLUST clst; DWORD sect, remain; WORD rcnt; BYTE *rbuff = dest; FATFS *fs = FatFs; *br = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_READ)) return FR_INVALID_OBJECT; remain = fs->fsize - fs->fptr; if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ for ( ; btr; /* Repeat until all data transferred */ rbuff += rcnt, fs->fptr += rcnt, *br += rcnt, btr -= rcnt) { if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ if ((fs->fptr / 512 % fs->csize) == 0) { /* On the cluster boundary? */ clst = (fs->fptr == 0) ? /* On the top of the file? */ fs->org_clust : get_fat(fs->curr_clust); if (clst <= 1) { fs->flag = 0; return FR_DISK_ERR; } fs->curr_clust = clst; /* Update current cluster */ fs->csect = 0; /* Reset sector offset in the cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) { fs->flag = 0; return FR_DISK_ERR; } sect += fs->csect; fs->dsect = sect; fs->csect++; /* Next sector address in the cluster */ } rcnt = 512 - ((WORD)fs->fptr % 512); /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; if (fs->flag & FA_STREAM) { dr = disk_readp(dest, fs->dsect, (WORD)(fs->fptr % 512), (WORD)(rcnt | 0x8000)); } else { dr = disk_readp(rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt); } if (dr) { fs->flag = 0; return (dr == RES_STRERR) ? FR_STREAM_ERR : FR_DISK_ERR; } } return FR_OK; }
static FRESULT dir_read ( DIR *dj, /* Pointer to the directory object to store read object name */ BYTE *dir /* 32-byte working buffer */ ) { FRESULT res; BYTE a, c; res = FR_NO_FILE; while (dj->sect) { res = disk_readp(dir, dj->sect, (dj->index % 16) * 32, 32) /* Read an entry */ ? FR_DISK_ERR : FR_OK; if (res != FR_OK) break; c = dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ a = dir[DIR_Attr] & AM_MASK; if (c != 0xE5 && c != '.' && !(a & AM_VOL)) /* Is it a valid entry? */ break; res = dir_next(dj); /* Next entry */ if (res != FR_OK) break; } if (res != FR_OK) dj->sect = 0; return res; }
static FRESULT dir_find ( DIR *dj, /* Pointer to the directory object linked to the file name */ BYTE *dir /* 32-byte working buffer */ ) { FRESULT res; BYTE c; res = dir_rewind(dj); /* Rewind directory object */ if (res != FR_OK) return res; do { res = disk_readp(dir, dj->sect, (dj->index % 16) * 32, 32) /* Read an entry */ ? FR_DISK_ERR : FR_OK; if (res != FR_OK) break; c = dir[DIR_Name]; /* First character */ if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ break; res = dir_next(dj); /* Next entry */ } while (res == FR_OK); return res; }
static BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */ BYTE *buf, /* Working buffer */ DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ ) { if (disk_readp(buf, sect, 510, 2)) /* Read the boot sector */ return 3; if (LD_WORD(buf) != 0xAA55) /* Check record signature */ return 2; if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146) /* Check FAT12/16 */ return 0; if (_FS_FAT32 && !disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146) /* Check FAT32 */ return 0; return 1; }
static FRESULT dir_find ( DIR *dj, /* Pointer to the directory object linked to the file name */ BYTE *dir /* 32-byte working buffer */ ) { FRESULT res; BYTE c; res = dir_rewind(dj); /* Rewind directory object */ if (res != FR_OK) return res; do { if ( (dj->index & 7) == 0 ) { // Need to read data res = disk_readp( Abuff.DirBuffer, dj->sect, (WORD)((dj->index & 8) * 32), 256) /* Read half a sector */ ? FR_DISK_ERR : FR_OK; } else { res = FR_OK ; } if (res != FR_OK) break; memcpy( dir, &Abuff.DirBuffer[((dj->index % 8) * 32)], 32 ) ; c = dir[DIR_Name]; /* First character */ if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ break; res = dir_next(dj); /* Next entry */ } while (res == FR_OK); return res; }
static FRESULT dir_read ( DIR *dj, /* Pointer to the directory object to store read object name */ BYTE *dir, /* 32-byte working buffer */ char *lfn_buffer /* 256-byte lfn buffer */ ) { FRESULT res; BYTE a, c; int lfn = 0; char *lfn_pos = &lfn_buffer[255]; lfn_buffer[255] = '\0'; res = FR_NO_FILE; while (dj->sect) { res = disk_readp(dir, dj->sect, (dj->index % 16) * 32, 32) /* Read an entry */ ? FR_DISK_ERR : FR_OK; if (res != FR_OK) break; c = dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ a = dir[DIR_Attr] & AM_MASK; // printf("LFN2:%x:%x:%x:%x\n",a&AM_LFN==AM_LFN,dir[0],dir[0x1a],dir[0x1c]); if (a&AM_LFN == AM_LFN && ((dir[0]&0xbf) < 16) && dir[0x1a]==0) // && dir[0x1c]!=0) { lfn_pos-=13; char * ptr = lfn_pos; int i; for (i=1;i!=32;i+=2) { if (i==0xb) i=0xe; if (i==0x1a) i=0x1c; char b1 = dir[i]; char b2 = dir[i+1]; if (b2==0) *ptr++ = b1; else *ptr++ = '_'; } //printf("LFN seq:%d %c%c%c%c%c%c%c%c%c%c%c%c%c \n",dir[0],dir[1],dir[3],dir[5],dir[7],dir[9],dir[14],dir[16],dir[18],dir[20],dir[22],dir[24],dir[28],dir[30]); lfn = 1; } if (c != 0xE5 && c != '.' && !(a & AM_VOL)) /* Is it a valid entry? */ break; res = dir_next2(dj); /* Next entry */ if (res != FR_OK) break; } lfn_buffer[0] = '\0'; if (lfn) { strcpy(&lfn_buffer[0],lfn_pos); } if (res != FR_OK) dj->sect = 0; return res; }
static CLUST get_fat ( /* 1:IO error, Else:Cluster status */ CLUST clst /* Cluster# to get the link information */ ) { BYTE buf[4]; FATFS *fs = FatFs; if (clst < 2 || clst >= fs->n_fatent) /* Range check */ return 1; switch (fs->fs_type) { #if _FS_FAT12 case FS_FAT12 : { UINT wc, bc, ofs; bc = (UINT)clst; bc += bc / 2; ofs = bc % 512; bc /= 512; if (ofs != 511) { if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break; } else { if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break; if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break; } wc = LD_WORD(buf); return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); } #endif #if _FS_FAT16 case FS_FAT16 : if (disk_readp(buf, fs->fatbase + clst / 256, ((UINT)clst % 256) * 2, 2)) break; return LD_WORD(buf); #endif #if _FS_FAT32 case FS_FAT32 : if (disk_readp(buf, fs->fatbase + clst / 128, ((UINT)clst % 128) * 4, 4)) break; return LD_DWORD(buf) & 0x0FFFFFFF; #endif } return 1; /* An error occured at the disk I/O layer */ }
FRESULT pf_read ( void* buff, /* Pointer to the read buffer (NULL:Forward data to the stream)*/ WORD btr, /* Number of bytes to read */ WORD* br /* Pointer to number of bytes read */ ) { DRESULT dr; CLUST clst; DWORD sect, remain; WORD rcnt; BYTE cs, *rbuff = buff; FATFS *fs = FatFs; *br = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; remain = fs->fsize - fs->fptr; if (btr > remain) btr = (WORD)remain; /* Truncate btr by remaining bytes */ while (btr) { /* Repeat until all data transferred */ if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ if (!cs) { /* On the cluster boundary? */ clst = (fs->fptr == 0) ? /* On the top of the file? */ fs->org_clust : get_fat(fs->curr_clust); if (clst <= 1) goto fr_abort; fs->curr_clust = clst; /* Update current cluster */ } sect = clust2sect(fs->curr_clust); /* Get current sector */ if (!sect) goto fr_abort; fs->dsect = sect + cs; } rcnt = (WORD)(512 - (fs->fptr % 512)); /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt); if (dr) goto fr_abort; fs->fptr += rcnt; rbuff += rcnt; /* Update pointers and counters */ btr -= rcnt; *br += rcnt; } return FR_OK; fr_abort: fs->flag = 0; return FR_DISK_ERR; }
FRESULT pf_read ( FATFS* fs, /* Filesystem descriptor */ void* buff, /* Pointer to the read buffer (NULL:Forward data to the stream)*/ UINT btr, /* Number of bytes to read */ UINT* br /* Pointer to number of bytes read */ ) { DRESULT dr; CLUST clst; DWORD sect, remain; UINT rcnt; BYTE cs, *rbuff = buff; *br = 0; if (!fs) return FR_NOT_ENABLED; /* Check file system */ if (!(fs->flag & FA_OPENED)) /* Check if opened */ return FR_NOT_OPENED; remain = fs->fsize - fs->fptr; if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ while (btr) { /* Repeat until all data transferred */ if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ if (!cs) { /* On the cluster boundary? */ if (fs->fptr == 0) /* On the top of the file? */ clst = fs->org_clust; else clst = get_fat(fs, fs->curr_clust); if (clst <= 1) ABORT(FR_DISK_ERR); fs->curr_clust = clst; /* Update current cluster */ } sect = clust2sect(fs, fs->curr_clust); /* Get current sector */ if (!sect) ABORT(FR_DISK_ERR); fs->dsect = sect + cs; } rcnt = 512 - (UINT)fs->fptr % 512; /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; dr = disk_readp(&fs->disk, !buff ? 0 : rbuff, fs->dsect, (UINT)fs->fptr % 512, rcnt); if (dr) ABORT(FR_DISK_ERR); fs->fptr += rcnt; rbuff += rcnt; /* Update pointers and counters */ btr -= rcnt; *br += rcnt; } return FR_OK; }
static FRESULT dir_read(DIR *dj) { FRESULT res; u8 adir,c,*dir; res = FR_NO_FILE; dir = FatFs->buf; while (dj->sect) { res = disk_readp(dir, dj->sect, (u16)((dj->index % 16) * 32), 32) /* Read an entry */ ? FR_DISK_ERR : FR_OK; if (res != FR_OK) break; c = dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ adir = dir[DIR_Attr] & AM_MASK; if (c != 0xE5 && c != '.' && !(adir & AM_VOL)) /* Is it a valid entry? */ break; res = dir_next(dj); /* Next entry */ if (res != FR_OK) break; } if (res != FR_OK) dj->sect = 0; return res; }
FRESULT pf_mount ( FATFS *fs /* Pointer to new file system object */ ) { BYTE fmt, buf[36] = {0}; DWORD bsect, fsize, tsect, mclst; FatFs = 0; if (disk_initialize() & STA_NOINIT) /* Check if the drive is ready or not */ return FR_NOT_READY; /* Search FAT partition on the drive */ bsect = 0; fmt = check_fs(buf, bsect); /* Check sector 0 as an SFD format */ if (fmt == 1) { /* Not an FAT boot record, it may be FDISK format */ /* Check a partition listed in top of the partition table */ if (disk_readp(buf, bsect, MBR_Table, 16)) { /* 1st partition entry */ fmt = 3; } else { if (buf[4]) { /* Is the partition existing? */ bsect = LD_DWORD(&buf[8]); /* Partition offset in LBA */ fmt = check_fs(buf, bsect); /* Check the partition */ } } } if (fmt == 3) return FR_DISK_ERR; if (fmt) return FR_NO_FILESYSTEM; /* No valid FAT patition is found */ /* Initialize the file system object */ if (disk_readp(buf, bsect, 13, sizeof (buf))) return FR_DISK_ERR; fsize = LD_WORD(buf+BPB_FATSz16-13); /* Number of sectors per FAT */ if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13); fsize *= buf[BPB_NumFATs-13]; /* Number of sectors in FAT area */ fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */ fs->csize = buf[BPB_SecPerClus-13]; /* Number of sectors per cluster */ fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13); /* Nmuber of root directory entries */ tsect = LD_WORD(buf+BPB_TotSec16-13); /* Number of sectors on the file system */ if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13); mclst = (tsect /* Last cluster# + 1 */ - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16 ) / fs->csize + 2; fs->n_fatent = (CLUST)mclst; fmt = 0; /* Determine the FAT sub type */ if (_FS_FAT12 && mclst < 0xFF7) fmt = FS_FAT12; if (_FS_FAT16 && mclst >= 0xFF8 && mclst < 0xFFF7) fmt = FS_FAT16; if (_FS_FAT32 && mclst >= 0xFFF7) fmt = FS_FAT32; if (!fmt) return FR_NO_FILESYSTEM; fs->fs_type = fmt; if (_FS_32ONLY || (_FS_FAT32 && fmt == FS_FAT32)) fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13)); /* Root directory start cluster */ else fs->dirbase = fs->fatbase + fsize; /* Root directory start sector (lba) */ fs->database = fs->fatbase + fsize + fs->n_rootdir / 16; /* Data start sector (lba) */ fs->flag = 0; FatFs = fs; return FR_OK; }