| 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; |