3965.11,16733,110,127 | 3965.11,16733,110,127 | ||||
``` | ``` | ||||
The default version of SdFatConfig.h enables support for dedicated SPI and | The default version of SdFatConfig.h enables support for dedicated SPI and | ||||
optimized access to contiguous files. This make SdFat Version 2 slightly | |||||
optimized access to contiguous files. This makes SdFat Version 2 slightly | |||||
larger than Version 1. If these features are disabled, Version 2 is smaller | larger than Version 1. If these features are disabled, Version 2 is smaller | ||||
than Version 1. | than Version 1. | ||||
Ignoring ../src/DigitalIO/readme.txt; not a valid file name (cc, h, cpp, cu, cuh) | |||||
Ignoring ../src/common/CPPLINT.cfg; not a valid file name (cc, h, cpp, cu, cuh) | |||||
Ignoring "../src/common/PrintTemplates.h": file excluded by "C:\Users\bill\Documents\ArduinoSdFat\libraries\SdFat\src\common\CPPLINT.cfg". File path component "PrintTemplates.h" matches pattern "PrintTemplates.h" |
name=SdFat | name=SdFat | ||||
version=2.0.0-beta.1 | |||||
version=2.0.0-beta.2 | |||||
license=MIT | license=MIT | ||||
author=Bill Greiman <fat16lib@sbcglobal.net> | author=Bill Greiman <fat16lib@sbcglobal.net> | ||||
maintainer=Bill Greiman <fat16lib@sbcglobal.net> | maintainer=Bill Greiman <fat16lib@sbcglobal.net> |
bool readSector(uint32_t sector, uint8_t* dst) { | bool readSector(uint32_t sector, uint8_t* dst) { | ||||
return m_blockDev->readSector(sector, dst); | return m_blockDev->readSector(sector, dst); | ||||
} | } | ||||
bool readSectors(uint32_t sector, uint8_t* dst, size_t count) { | |||||
return m_blockDev->readSectors(sector, dst, count); | |||||
} | |||||
bool writeSector(uint32_t sector, const uint8_t* src) { | bool writeSector(uint32_t sector, const uint8_t* src) { | ||||
return m_blockDev->writeSector(sector, src); | return m_blockDev->writeSector(sector, src); | ||||
} | } | ||||
#if USE_MULTI_SECTOR_IO | |||||
bool readSectors(uint32_t sector, uint8_t* dst, size_t count) { | |||||
return m_blockDev->readSectors(sector, dst, count); | |||||
} | |||||
bool writeSectors(uint32_t sector, const uint8_t* src, size_t count) { | bool writeSectors(uint32_t sector, const uint8_t* src, size_t count) { | ||||
return m_blockDev->writeSectors(sector, src, count); | return m_blockDev->writeSectors(sector, src, count); | ||||
} | } | ||||
#endif // USE_MULTI_SECTOR_IO | |||||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||||
static const uint8_t m_bytesPerSectorShift = 9; | static const uint8_t m_bytesPerSectorShift = 9; | ||||
static const uint16_t m_bytesPerSector = 512; | static const uint16_t m_bytesPerSector = 512; |
} | } | ||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
static void printDir(print_t* pr, dir_t* dir) { | |||||
static void printDir(print_t* pr, DirFat_t* dir) { | |||||
if (!dir->name[0] || dir->name[0] == FAT_NAME_DELETED) { | if (!dir->name[0] || dir->name[0] == FAT_NAME_DELETED) { | ||||
pr->println(F("Not Used")); | pr->println(F("Not Used")); | ||||
} else if (isFileOrSubdir(dir)) { | } else if (isFileOrSubdir(dir)) { | ||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
void FatPartition::dmpDirSector(print_t* pr, uint32_t sector) { | void FatPartition::dmpDirSector(print_t* pr, uint32_t sector) { | ||||
dir_t dir[16]; | |||||
DirFat_t dir[16]; | |||||
if (!readSector(sector, reinterpret_cast<uint8_t*>(dir))) { | if (!readSector(sector, reinterpret_cast<uint8_t*>(dir))) { | ||||
pr->println(F("dmpDir failed")); | pr->println(F("dmpDir failed")); | ||||
return; | return; |
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
// cache a file's directory entry | // cache a file's directory entry | ||||
// return pointer to cached entry or null for failure | // return pointer to cached entry or null for failure | ||||
dir_t* FatFile::cacheDirEntry(uint8_t action) { | |||||
DirFat_t* FatFile::cacheDirEntry(uint8_t action) { | |||||
cache_t* pc; | cache_t* pc; | ||||
pc = m_vol->cacheFetchData(m_dirSector, action); | pc = m_vol->cacheFetchData(m_dirSector, action); | ||||
if (!pc) { | if (!pc) { | ||||
return false; | return false; | ||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
bool FatFile::dirEntry(dir_t* dst) { | |||||
dir_t* dir; | |||||
bool FatFile::dirEntry(DirFat_t* dst) { | |||||
DirFat_t* dir; | |||||
// Make sure fields on device are correct. | // Make sure fields on device are correct. | ||||
if (!sync()) { | if (!sync()) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
// copy to caller's struct | // copy to caller's struct | ||||
memcpy(dst, dir, sizeof(dir_t)); | |||||
memcpy(dst, dir, sizeof(DirFat_t)); | |||||
return true; | return true; | ||||
fail: | fail: | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
bool FatFile::mkdir(FatFile* parent, fname_t* fname) { | bool FatFile::mkdir(FatFile* parent, fname_t* fname) { | ||||
uint32_t sector; | uint32_t sector; | ||||
dir_t dot; | |||||
dir_t* dir; | |||||
DirFat_t dot; | |||||
DirFat_t* dir; | |||||
cache_t* pc; | cache_t* pc; | ||||
if (!parent->isDir()) { | if (!parent->isDir()) { | ||||
m_vol = dirFile->m_vol; | m_vol = dirFile->m_vol; | ||||
m_dirIndex = dirIndex; | m_dirIndex = dirIndex; | ||||
m_dirCluster = dirFile->m_firstCluster; | m_dirCluster = dirFile->m_firstCluster; | ||||
dir_t* dir = reinterpret_cast<dir_t*>(m_vol->cacheAddress()); | |||||
DirFat_t* dir = reinterpret_cast<DirFat_t*>(m_vol->cacheAddress()); | |||||
dir += 0XF & dirIndex; | dir += 0XF & dirIndex; | ||||
// Must be file or subdirectory. | // Must be file or subdirectory. | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
bool FatFile::openNext(FatFile* dirFile, oflag_t oflag) { | bool FatFile::openNext(FatFile* dirFile, oflag_t oflag) { | ||||
uint8_t checksum = 0; | uint8_t checksum = 0; | ||||
ldir_t* ldir; | |||||
DirLfn_t* ldir; | |||||
uint8_t lfnOrd = 0; | uint8_t lfnOrd = 0; | ||||
uint16_t index; | uint16_t index; | ||||
while (1) { | while (1) { | ||||
// read entry into cache | // read entry into cache | ||||
index = dirFile->curPosition()/32; | index = dirFile->curPosition()/32; | ||||
dir_t* dir = dirFile->readDirCache(); | |||||
DirFat_t* dir = dirFile->readDirCache(); | |||||
if (!dir) { | if (!dir) { | ||||
if (dirFile->getError()) { | if (dirFile->getError()) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
} | } | ||||
return true; | return true; | ||||
} else if (isLongName(dir)) { | } else if (isLongName(dir)) { | ||||
ldir = reinterpret_cast<ldir_t*>(dir); | |||||
ldir = reinterpret_cast<DirLfn_t*>(dir); | |||||
if (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) { | if (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) { | ||||
lfnOrd = ldir->order & 0X1F; | lfnOrd = ldir->order & 0X1F; | ||||
checksum = ldir->checksum; | checksum = ldir->checksum; | ||||
return -1; | return -1; | ||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
int8_t FatFile::readDir(dir_t* dir) { | |||||
int8_t FatFile::readDir(DirFat_t* dir) { | |||||
int16_t n; | int16_t n; | ||||
// if not a directory file or miss-positioned return an error | // if not a directory file or miss-positioned return an error | ||||
if (!isDir() || (0X1F & m_curPosition)) { | if (!isDir() || (0X1F & m_curPosition)) { | ||||
} | } | ||||
while (1) { | while (1) { | ||||
n = read(dir, sizeof(dir_t)); | |||||
if (n != sizeof(dir_t)) { | |||||
n = read(dir, sizeof(DirFat_t)); | |||||
if (n != sizeof(DirFat_t)) { | |||||
return n == 0 ? 0 : -1; | return n == 0 ? 0 : -1; | ||||
} | } | ||||
// last entry if FAT_NAME_FREE | // last entry if FAT_NAME_FREE | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
// Read next directory entry into the cache | // Read next directory entry into the cache | ||||
// Assumes file is correctly positioned | // Assumes file is correctly positioned | ||||
dir_t* FatFile::readDirCache(bool skipReadOk) { | |||||
DirFat_t* FatFile::readDirCache(bool skipReadOk) { | |||||
uint8_t i = (m_curPosition >> 5) & 0XF; | uint8_t i = (m_curPosition >> 5) & 0XF; | ||||
if (i == 0 || !skipReadOk) { | if (i == 0 || !skipReadOk) { | ||||
m_curPosition += 32; | m_curPosition += 32; | ||||
} | } | ||||
// return pointer to entry | // return pointer to entry | ||||
return reinterpret_cast<dir_t*>(m_vol->cacheAddress()) + i; | |||||
return reinterpret_cast<DirFat_t*>(m_vol->cacheAddress()) + i; | |||||
fail: | fail: | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
bool FatFile::rename(FatFile* dirFile, const char* newPath) { | bool FatFile::rename(FatFile* dirFile, const char* newPath) { | ||||
dir_t entry; | |||||
DirFat_t entry; | |||||
uint32_t dirCluster = 0; | uint32_t dirCluster = 0; | ||||
FatFile file; | FatFile file; | ||||
FatFile oldFile; | FatFile oldFile; | ||||
cache_t* pc; | cache_t* pc; | ||||
dir_t* dir; | |||||
DirFat_t* dir; | |||||
// Must be an open file or subdirectory. | // Must be an open file or subdirectory. | ||||
if (!(isFile() || isSubDir())) { | if (!(isFile() || isSubDir())) { | ||||
// make sure directory is empty | // make sure directory is empty | ||||
while (1) { | while (1) { | ||||
dir_t* dir = readDirCache(true); | |||||
DirFat_t* dir = readDirCache(true); | |||||
if (!dir) { | if (!dir) { | ||||
// EOF if no error. | // EOF if no error. | ||||
if (!getError()) { | if (!getError()) { | ||||
// remember position | // remember position | ||||
index = m_curPosition/32; | index = m_curPosition/32; | ||||
dir_t* dir = readDirCache(); | |||||
DirFat_t* dir = readDirCache(); | |||||
if (!dir) { | if (!dir) { | ||||
// At EOF if no error. | // At EOF if no error. | ||||
if (!getError()) { | if (!getError()) { | ||||
return true; | return true; | ||||
} | } | ||||
if (m_flags & FILE_FLAG_DIR_DIRTY) { | if (m_flags & FILE_FLAG_DIR_DIRTY) { | ||||
dir_t* dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE); | |||||
DirFat_t* dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE); | |||||
// check for deleted by another open file object | // check for deleted by another open file object | ||||
if (!dir || dir->name[0] == FAT_NAME_DELETED) { | if (!dir || dir->name[0] == FAT_NAME_DELETED) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { | uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { | ||||
uint16_t dirDate; | uint16_t dirDate; | ||||
uint16_t dirTime; | uint16_t dirTime; | ||||
dir_t* dir; | |||||
DirFat_t* dir; | |||||
if (!isFile() | if (!isFile() | ||||
|| year < 1980 | || year < 1980 |
* | * | ||||
* \return true for success or false for failure. | * \return true for success or false for failure. | ||||
*/ | */ | ||||
bool dirEntry(dir_t* dir); | |||||
bool dirEntry(DirFat_t* dir); | |||||
/** \return The number of bytes allocated to a directory or zero | /** \return The number of bytes allocated to a directory or zero | ||||
* if an error occurs. | * if an error occurs. | ||||
*/ | */ | ||||
int read(void* buf, size_t count); | int read(void* buf, size_t count); | ||||
/** Read the next directory entry from a directory file. | /** Read the next directory entry from a directory file. | ||||
* | * | ||||
* \param[out] dir The dir_t struct that will receive the data. | |||||
* \param[out] dir The DirFat_t struct that will receive the data. | |||||
* | * | ||||
* \return For success readDir() returns the number of bytes read. | * \return For success readDir() returns the number of bytes read. | ||||
* A value of zero will be returned if end of file is reached. | * A value of zero will be returned if end of file is reached. | ||||
* readDir() called before a directory has been opened, this is not | * readDir() called before a directory has been opened, this is not | ||||
* a directory file or an I/O error occurred. | * a directory file or an I/O error occurred. | ||||
*/ | */ | ||||
int8_t readDir(dir_t* dir); | |||||
int8_t readDir(DirFat_t* dir); | |||||
/** Remove a file. | /** Remove a file. | ||||
* | * | ||||
* The directory entry and all data for the file are deleted. | * The directory entry and all data for the file are deleted. | ||||
// private functions | // private functions | ||||
bool addCluster(); | bool addCluster(); | ||||
bool addDirCluster(); | bool addDirCluster(); | ||||
dir_t* cacheDirEntry(uint8_t action); | |||||
DirFat_t* cacheDirEntry(uint8_t action); | |||||
static uint8_t lfnChecksum(uint8_t* name); | static uint8_t lfnChecksum(uint8_t* name); | ||||
bool lfnUniqueSfn(fname_t* fname); | bool lfnUniqueSfn(fname_t* fname); | ||||
bool openCluster(FatFile* file); | bool openCluster(FatFile* file); | ||||
bool open(FatFile* dirFile, fname_t* fname, oflag_t oflag); | bool open(FatFile* dirFile, fname_t* fname, oflag_t oflag); | ||||
bool openCachedEntry(FatFile* dirFile, uint16_t cacheIndex, oflag_t oflag, | bool openCachedEntry(FatFile* dirFile, uint16_t cacheIndex, oflag_t oflag, | ||||
uint8_t lfnOrd); | uint8_t lfnOrd); | ||||
dir_t* readDirCache(bool skipReadOk = false); | |||||
DirFat_t* readDirCache(bool skipReadOk = false); | |||||
// bits defined in m_flags | // bits defined in m_flags | ||||
static const uint8_t FILE_FLAG_READ = 0X01; | static const uint8_t FILE_FLAG_READ = 0X01; |
* \param[in] i Index of character. | * \param[in] i Index of character. | ||||
* \return The 16-bit character. | * \return The 16-bit character. | ||||
*/ | */ | ||||
static uint16_t lfnGetChar(ldir_t *ldir, uint8_t i) { | |||||
static uint16_t lfnGetChar(DirLfn_t *ldir, uint8_t i) { | |||||
if (i < 5) { | if (i < 5) { | ||||
return getLe16(ldir->unicode1 + 2*i); | return getLe16(ldir->unicode1 + 2*i); | ||||
} else if (i < 11) { | } else if (i < 11) { | ||||
return 0; | return 0; | ||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
static bool lfnGetName(ldir_t *ldir, char* name, size_t n) { | |||||
static bool lfnGetName(DirLfn_t *ldir, char* name, size_t n) { | |||||
uint8_t i; | uint8_t i; | ||||
size_t k = 13*((ldir->order & 0X1F) - 1); | size_t k = 13*((ldir->order & 0X1F) - 1); | ||||
for (i = 0; i < 13; i++) { | for (i = 0; i < 13; i++) { | ||||
* \param[in] i Index of character. | * \param[in] i Index of character. | ||||
* \param[in] c The 16-bit character. | * \param[in] c The 16-bit character. | ||||
*/ | */ | ||||
static void lfnPutChar(ldir_t *ldir, uint8_t i, uint16_t c) { | |||||
static void lfnPutChar(DirLfn_t *ldir, uint8_t i, uint16_t c) { | |||||
if (i < 5) { | if (i < 5) { | ||||
setLe16(ldir->unicode1 + 2*i, c); | setLe16(ldir->unicode1 + 2*i, c); | ||||
} else if (i < 11) { | } else if (i < 11) { | ||||
} | } | ||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
static void lfnPutName(ldir_t *ldir, const char* name, size_t n) { | |||||
static void lfnPutName(DirLfn_t *ldir, const char* name, size_t n) { | |||||
size_t k = 13*((ldir->order & 0X1F) - 1); | size_t k = 13*((ldir->order & 0X1F) - 1); | ||||
for (uint8_t i = 0; i < 13; i++, k++) { | for (uint8_t i = 0; i < 13; i++, k++) { | ||||
uint16_t c = k < n ? name[k] : k == n ? 0 : 0XFFFF; | uint16_t c = k < n ? name[k] : k == n ? 0 : 0XFFFF; | ||||
//============================================================================== | //============================================================================== | ||||
bool FatFile::getName(char* name, size_t size) { | bool FatFile::getName(char* name, size_t size) { | ||||
FatFile dirFile; | FatFile dirFile; | ||||
ldir_t* ldir; | |||||
DirLfn_t* ldir; | |||||
if (!isOpen() || size < 13) { | if (!isOpen() || size < 13) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
ldir = reinterpret_cast<ldir_t*>(dirFile.readDirCache()); | |||||
ldir = reinterpret_cast<DirLfn_t*>(dirFile.readDirCache()); | |||||
if (!ldir) { | if (!ldir) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
uint16_t curIndex; | uint16_t curIndex; | ||||
uint16_t date; | uint16_t date; | ||||
uint16_t time; | uint16_t time; | ||||
dir_t* dir; | |||||
ldir_t* ldir; | |||||
DirFat_t* dir; | |||||
DirLfn_t* ldir; | |||||
size_t len = fname->len; | size_t len = fname->len; | ||||
if (!dirFile->isDir() || isOpen()) { | if (!dirFile->isDir() || isOpen()) { | ||||
if (dir->name[0] == FAT_NAME_DELETED || dir->name[0] == '.') { | if (dir->name[0] == FAT_NAME_DELETED || dir->name[0] == '.') { | ||||
lfnOrd = 0; | lfnOrd = 0; | ||||
} else if (isLongName(dir)) { | } else if (isLongName(dir)) { | ||||
ldir = reinterpret_cast<ldir_t*>(dir); | |||||
ldir = reinterpret_cast<DirLfn_t*>(dir); | |||||
if (!lfnOrd) { | if (!lfnOrd) { | ||||
if ((ldir->order & FAT_ORDER_LAST_LONG_ENTRY) == 0) { | if ((ldir->order & FAT_ORDER_LAST_LONG_ENTRY) == 0) { | ||||
continue; | continue; | ||||
} | } | ||||
lfnOrd = freeNeed - 1; | lfnOrd = freeNeed - 1; | ||||
for (order = lfnOrd ; order ; order--) { | for (order = lfnOrd ; order ; order--) { | ||||
ldir = reinterpret_cast<ldir_t*>(dirFile->readDirCache()); | |||||
ldir = reinterpret_cast<DirLfn_t*>(dirFile->readDirCache()); | |||||
if (!ldir) { | if (!ldir) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
// initialize as empty file | // initialize as empty file | ||||
memset(dir, 0, sizeof(dir_t)); | |||||
memset(dir, 0, sizeof(DirFat_t)); | |||||
memcpy(dir->name, fname->sfn, 11); | memcpy(dir->name, fname->sfn, 11); | ||||
// Set base-name and extension lower case bits. | // Set base-name and extension lower case bits. | ||||
FatFile dirFile; | FatFile dirFile; | ||||
uint16_t u; | uint16_t u; | ||||
size_t n = 0; | size_t n = 0; | ||||
ldir_t* ldir; | |||||
DirLfn_t* ldir; | |||||
if (!isLFN()) { | if (!isLFN()) { | ||||
return printSFN(pr); | return printSFN(pr); | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
ldir = reinterpret_cast<ldir_t*>(dirFile.readDirCache()); | |||||
ldir = reinterpret_cast<DirLfn_t*>(dirFile.readDirCache()); | |||||
if (!ldir) { | if (!ldir) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
uint8_t checksum; | uint8_t checksum; | ||||
uint8_t order; | uint8_t order; | ||||
FatFile dirFile; | FatFile dirFile; | ||||
dir_t* dir; | |||||
ldir_t* ldir; | |||||
DirFat_t* dir; | |||||
DirLfn_t* ldir; | |||||
// Cant' remove not open for write. | // Cant' remove not open for write. | ||||
if (!isWritable()) { | if (!isWritable()) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
ldir = reinterpret_cast<ldir_t*>(dirFile.readDirCache()); | |||||
ldir = reinterpret_cast<DirLfn_t*>(dirFile.readDirCache()); | |||||
if (!ldir) { | if (!ldir) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
bool FatFile::lfnUniqueSfn(fname_t* fname) { | bool FatFile::lfnUniqueSfn(fname_t* fname) { | ||||
const uint8_t FIRST_HASH_SEQ = 2; // min value is 2 | const uint8_t FIRST_HASH_SEQ = 2; // min value is 2 | ||||
uint8_t pos = fname->seqPos;; | uint8_t pos = fname->seqPos;; | ||||
dir_t *dir; | |||||
DirFat_t *dir; | |||||
uint16_t hex; | uint16_t hex; | ||||
DBG_HALT_IF(!(fname->flags & FNAME_FLAG_LOST_CHARS)); | DBG_HALT_IF(!(fname->flags & FNAME_FLAG_LOST_CHARS)); |
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
size_t FatFile::printAccessDate(print_t* pr) { | size_t FatFile::printAccessDate(print_t* pr) { | ||||
dir_t dir; | |||||
DirFat_t dir; | |||||
if (!dirEntry(&dir)) { | if (!dirEntry(&dir)) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
size_t FatFile::printCreateDateTime(print_t* pr) { | size_t FatFile::printCreateDateTime(print_t* pr) { | ||||
dir_t dir; | |||||
DirFat_t dir; | |||||
if (!dirEntry(&dir)) { | if (!dirEntry(&dir)) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
size_t FatFile::printModifyDateTime(print_t* pr) { | size_t FatFile::printModifyDateTime(print_t* pr) { | ||||
dir_t dir; | |||||
DirFat_t dir; | |||||
if (!dirEntry(&dir)) { | if (!dirEntry(&dir)) { | ||||
DBG_FAIL_MACRO; | DBG_FAIL_MACRO; | ||||
goto fail; | goto fail; |
/** Used to access cached FAT32 entries. */ | /** Used to access cached FAT32 entries. */ | ||||
uint32_t fat32[128]; | uint32_t fat32[128]; | ||||
/** Used to access cached directory entries. */ | /** Used to access cached directory entries. */ | ||||
dir_t dir[16]; | |||||
DirFat_t dir[16]; | |||||
}; | }; | ||||
//============================================================================== | //============================================================================== | ||||
/** | /** |
*/ | */ | ||||
#if HAS_SDIO_CLASS | #if HAS_SDIO_CLASS | ||||
class SdSpiCard : public SdCardInterface { | class SdSpiCard : public SdCardInterface { | ||||
#elif USE_BLOCK_DEVICE_INTERFACE | |||||
class SdSpiCard : public BlockDeviceInterface { | |||||
#else // HAS_SDIO_CLASS | #else // HAS_SDIO_CLASS | ||||
class SdSpiCard { | class SdSpiCard { | ||||
#endif // HAS_SDIO_CLASS | #endif // HAS_SDIO_CLASS |
#define ENABLE_ARDUINO_SERIAL 1 | #define ENABLE_ARDUINO_SERIAL 1 | ||||
/** For Debug - must be one */ | /** For Debug - must be one */ | ||||
#define ENABLE_ARDUINO_STRING 1 | #define ENABLE_ARDUINO_STRING 1 | ||||
/** Set USE_BLOCK_DEVICE_INTERFACE nonzero to use generic of block device */ | |||||
#define USE_BLOCK_DEVICE_INTERFACE 0 | |||||
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||
#if ENABLE_ARDUINO_FEATURES | #if ENABLE_ARDUINO_FEATURES | ||||
#include "Arduino.h" | #include "Arduino.h" |
#ifndef BlockDevice_h | #ifndef BlockDevice_h | ||||
#define BlockDevice_h | #define BlockDevice_h | ||||
#include "SdCard/SdCard.h" | #include "SdCard/SdCard.h" | ||||
#if HAS_SDIO_CLASS || USE_BLOCK_DEVICE_INTERFACE | |||||
typedef BlockDeviceInterface BlockDevice; | |||||
#else | |||||
typedef SdCard BlockDevice; | typedef SdCard BlockDevice; | ||||
#endif | |||||
#endif // BlockDevice_h | #endif // BlockDevice_h |
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
* DEALINGS IN THE SOFTWARE. | * DEALINGS IN THE SOFTWARE. | ||||
*/ | */ | ||||
#ifndef BlockDeviceInterface_h | |||||
#define BlockDeviceInterface_h | |||||
/** | /** | ||||
* \file | * \file | ||||
* \brief BlockDeviceInterface include file. | * \brief BlockDeviceInterface include file. | ||||
*/ | */ | ||||
#ifndef BlockDeviceInterface_h | |||||
#define BlockDeviceInterface_h | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stddef.h> | #include <stddef.h> | ||||
#include "SdFatConfig.h" | |||||
/** | /** | ||||
* \class BlockDeviceInterface | * \class BlockDeviceInterface | ||||
* \brief BlockDeviceInterface class. | * \brief BlockDeviceInterface class. | ||||
* \return true for success or false for failure. | * \return true for success or false for failure. | ||||
*/ | */ | ||||
virtual bool readSector(uint32_t sector, uint8_t* dst) = 0; | virtual bool readSector(uint32_t sector, uint8_t* dst) = 0; | ||||
#if USE_MULTI_SECTOR_IO | |||||
/** | /** | ||||
* Read multiple 512 byte sectors. | * Read multiple 512 byte sectors. | ||||
* | * | ||||
* \return true for success or false for failure. | * \return true for success or false for failure. | ||||
*/ | */ | ||||
virtual bool readSectors(uint32_t sector, uint8_t* dst, size_t ns) = 0; | virtual bool readSectors(uint32_t sector, uint8_t* dst, size_t ns) = 0; | ||||
#endif // USE_MULTI_SECTOR_IO | |||||
/** \return device size in sectors. */ | /** \return device size in sectors. */ | ||||
virtual uint32_t sectorCount() = 0; | virtual uint32_t sectorCount() = 0; | ||||
* \return true for success or false for failure. | * \return true for success or false for failure. | ||||
*/ | */ | ||||
virtual bool writeSector(uint32_t sector, const uint8_t* src) = 0; | virtual bool writeSector(uint32_t sector, const uint8_t* src) = 0; | ||||
#if USE_MULTI_SECTOR_IO | |||||
/** | /** | ||||
* Write multiple 512 byte sectors. | * Write multiple 512 byte sectors. | ||||
* | * | ||||
* \return true for success or false for failure. | * \return true for success or false for failure. | ||||
*/ | */ | ||||
virtual bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns) = 0; | virtual bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns) = 0; | ||||
#endif // USE_MULTI_SECTOR_IO | |||||
}; | }; | ||||
#endif // BlockDeviceInterface_h | #endif // BlockDeviceInterface_h |
#include "Arduino.h" | #include "Arduino.h" | ||||
#ifndef DBG_FILE | #ifndef DBG_FILE | ||||
#error DBG_FILE not defined | #error DBG_FILE not defined | ||||
#endif // DBG_FILE | |||||
#endif // DBG_FILE | |||||
static void dbgPrint(uint16_t line) { | static void dbgPrint(uint16_t line) { | ||||
Serial.print(F("DBG_FAIL: ")); | Serial.print(F("DBG_FAIL: ")); | ||||
Serial.print(F(DBG_FILE)); | Serial.print(F(DBG_FILE)); |
uint8_t firstClusterLow[2]; | uint8_t firstClusterLow[2]; | ||||
uint8_t fileSize[4]; | uint8_t fileSize[4]; | ||||
} DirFat_t; | } DirFat_t; | ||||
typedef DirFat_t dir_t; | |||||
static inline bool isFileDir(const DirFat_t* dir) { | static inline bool isFileDir(const DirFat_t* dir) { | ||||
return (dir->attributes & (FAT_ATTRIB_DIRECTORY | FAT_ATTRIB_LABEL)) == 0; | return (dir->attributes & (FAT_ATTRIB_DIRECTORY | FAT_ATTRIB_LABEL)) == 0; | ||||
uint8_t mustBeZero2[2]; | uint8_t mustBeZero2[2]; | ||||
uint8_t unicode3[4]; | uint8_t unicode3[4]; | ||||
} DirLfn_t; | } DirLfn_t; | ||||
typedef DirLfn_t ldir_t; | |||||
//============================================================================= | //============================================================================= | ||||
inline uint32_t exFatChecksum(uint32_t sum, uint8_t data) { | inline uint32_t exFatChecksum(uint32_t sum, uint8_t data) { | ||||
return (sum << 31) + (sum >> 1) + data; | return (sum << 31) + (sum >> 1) + data; |