initial commit
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
/* Arduino FatReader Library
|
||||
* Copyright (C) 2009 by William Greiman
|
||||
*
|
||||
* This file is part of the Arduino FatReader Library
|
||||
*
|
||||
* This Library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the Arduino FatReader Library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef FatReader_h
|
||||
#define FatReader_h
|
||||
#include <FatStructs.h>
|
||||
#include <SdReader.h>
|
||||
|
||||
// flags for ls()
|
||||
/** ls() flag to print modify date */
|
||||
#define LS_FLAG_FRAGMENTED 1
|
||||
/** ls() flag to print file size */
|
||||
#define LS_SIZE 2
|
||||
/** ls() flag for recursive list of subdirectories */
|
||||
#define LS_R 4
|
||||
|
||||
// offsets for structures used in volume init
|
||||
/** Offset to BIOS Parameter Block in FAT Boot Sector */
|
||||
#define BPB_OFFSET 11
|
||||
/** Byte count for part of BIOS Parameter Block to be read by init() */
|
||||
#define BPB_COUNT 37
|
||||
/** offset to partition table in mbr */
|
||||
#define PART_OFFSET (512 - 64 - 2)
|
||||
|
||||
// format dir.name into name[13] as standard 8.3 string
|
||||
void dirName(dir_t &dir, char name[]);
|
||||
// Print name field of dir_t struct in 8.3 format
|
||||
void printEntryName(dir_t &dir);
|
||||
//------------------------------------------------------------------------------
|
||||
/** \class FatVolume
|
||||
* \brief FatVolume provides access to FAT volumes.
|
||||
*/
|
||||
class FatVolume {
|
||||
/** Allow FatReader access to FatVolume private data. */
|
||||
friend class FatReader;
|
||||
uint8_t blocksPerCluster_;
|
||||
uint32_t blocksPerFat_;
|
||||
uint32_t clusterCount_;
|
||||
uint32_t dataStartBlock_;
|
||||
uint8_t fatCount_;
|
||||
uint32_t fatStartBlock_;
|
||||
uint8_t fatType_;
|
||||
SdReader *rawDevice_;
|
||||
uint16_t rootDirEntryCount_;
|
||||
uint32_t rootDirStart_;
|
||||
uint32_t totalBlocks_;
|
||||
uint8_t chainIsContiguous(uint32_t cluster);
|
||||
uint32_t chainSize(uint32_t cluster);
|
||||
uint8_t isEOC(uint32_t cluster) {
|
||||
return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN);
|
||||
}
|
||||
uint32_t nextCluster(uint32_t cluster);
|
||||
uint8_t rawRead(uint32_t block, uint16_t offset, uint8_t *dst,
|
||||
uint16_t count) {
|
||||
return rawDevice_->readData(block, offset, dst, count);
|
||||
}
|
||||
uint8_t validCluster(uint32_t cluster) {
|
||||
return (1 < cluster && cluster < (clusterCount_ + 2));
|
||||
}
|
||||
|
||||
public:
|
||||
/** Create an instance of FatVolume */
|
||||
FatVolume(void) : fatType_(0) {}
|
||||
/**
|
||||
* Initialize a FAT volume. Try partition one first then try super
|
||||
* floppy format.
|
||||
*
|
||||
* \param[in] dev The SdReader where the volume is located.
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure. Reasons for
|
||||
* failure include not finding a valid partition, not finding a valid
|
||||
* FAT file system or an I/O error.
|
||||
*/
|
||||
uint8_t init(SdReader &dev) { return init(dev, 1) ? 1 : init(dev, 0); }
|
||||
uint8_t init(SdReader &dev, uint8_t part);
|
||||
|
||||
// inline functions that return volume info
|
||||
/** \return The volume's cluster size in blocks. */
|
||||
uint8_t blocksPerCluster(void) { return blocksPerCluster_; }
|
||||
/** \return The number of blocks in one FAT. */
|
||||
uint32_t blocksPerFat(void) { return blocksPerFat_; }
|
||||
/** \return The total number of clusters in the volume. */
|
||||
uint32_t clusterCount(void) { return clusterCount_; }
|
||||
/** \return The logical block number for the start of file data. */
|
||||
uint32_t dataStartBlock(void) { return dataStartBlock_; }
|
||||
/** \return The number of FAT structures on the volume. */
|
||||
uint8_t fatCount(void) { return fatCount_; }
|
||||
/** \return The logical block number for the start of the first FAT. */
|
||||
uint32_t fatStartBlock(void) { return fatStartBlock_; }
|
||||
/** \return The FAT type of the volume. Values are 12, 16 or 32. */
|
||||
uint8_t fatType(void) { return fatType_; }
|
||||
|
||||
/*!
|
||||
@brief Raw device for this volume
|
||||
@returns the raw device
|
||||
*/
|
||||
SdReader *rawDevice(void) { return rawDevice_; }
|
||||
/** \return The number of entries in the root directory for FAT16 volumes. */
|
||||
uint32_t rootDirEntryCount(void) { return rootDirEntryCount_; }
|
||||
/** \return The logical block number for the start of the root directory
|
||||
on FAT16 volumes or the first cluster number on FAT32 volumes. */
|
||||
uint32_t rootDirStart(void) { return rootDirStart_; }
|
||||
/** \return The total number of blocks in the volume. */
|
||||
uint32_t totalBlocks(void) { return totalBlocks_; }
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/** \class FatReader
|
||||
* \brief FatReader implements a minimal FAT16/FAT32 file reader class.
|
||||
*/
|
||||
class FatReader {
|
||||
// values for type_
|
||||
/** File is contiguous file */
|
||||
#define FILE_IS_CONTIGUOUS 0X08
|
||||
/** File type mask */
|
||||
#define FILE_TYPE_MASK 0X07
|
||||
/** This FatReader has not been opened. */
|
||||
#define FILE_TYPE_CLOSED 0X00
|
||||
/** FatReader for a file */
|
||||
#define FILE_TYPE_NORMAL 0X01
|
||||
/** FatReader for a FAT16 root directory */
|
||||
#define FILE_TYPE_ROOT16 0X02
|
||||
/** FatReader for a FAT32 root directory */
|
||||
#define FILE_TYPE_ROOT32 0X03
|
||||
/** FatReader for a subdirectory */
|
||||
#define FILE_TYPE_SUBDIR 0X04
|
||||
/** Test value for directory type */
|
||||
#define FILE_TYPE_MIN_DIR FILE_TYPE_ROOT16
|
||||
uint8_t type_;
|
||||
uint32_t fileSize_;
|
||||
uint32_t readCluster_;
|
||||
uint32_t readPosition_;
|
||||
uint32_t firstCluster_;
|
||||
FatVolume *vol_;
|
||||
int16_t readBlockData(uint8_t *dst, uint16_t count);
|
||||
void lsR(dir_t &d, uint8_t flags, uint8_t indent);
|
||||
|
||||
public:
|
||||
/** Create an instance of FatReader. */
|
||||
FatReader(void) : type_(FILE_TYPE_CLOSED) {}
|
||||
void ls(uint8_t flags = 0);
|
||||
uint8_t openRoot(FatVolume &vol);
|
||||
uint8_t open(FatVolume &vol, dir_t &dir);
|
||||
uint8_t open(FatReader &dir, char *name);
|
||||
uint8_t open(FatReader &dir, uint16_t index);
|
||||
void optimizeContiguous(void);
|
||||
int16_t read(void *buf, uint16_t count);
|
||||
int8_t readDir(dir_t &dir);
|
||||
void rewind(void);
|
||||
uint8_t seekCur(uint32_t pos);
|
||||
// inline functions
|
||||
/** Close this instance of FatReader. */
|
||||
void close(void) { type_ = FILE_TYPE_CLOSED; }
|
||||
/** \return The total number of bytes in a file or directory. */
|
||||
uint32_t fileSize(void) { return fileSize_; }
|
||||
/**
|
||||
* Type of this FatReader. You should use isFile() or isDir()
|
||||
* instead of type() if possible.
|
||||
*
|
||||
* \return The file or directory type.
|
||||
*/
|
||||
uint8_t fileType(void) { return type_ & FILE_TYPE_MASK; }
|
||||
/** \return The first cluster number for a file or directory. */
|
||||
uint32_t firstCluster(void) { return firstCluster_; }
|
||||
/**
|
||||
* \return True if the bit for optimized reads is set.
|
||||
* See optimizeContiguous(). */
|
||||
uint8_t isContiguous(void) { return type_ & FILE_IS_CONTIGUOUS; }
|
||||
/** \return True if this is a FatReader for a directory else false */
|
||||
uint8_t isDir(void) { return fileType() >= FILE_TYPE_MIN_DIR; }
|
||||
/** \return True if this is a FatReader for a file else false */
|
||||
uint8_t isFile(void) { return fileType() == FILE_TYPE_NORMAL; }
|
||||
/** \return True if FatReader is for an open file/directory else false */
|
||||
uint8_t isOpen(void) { return fileType() != FILE_TYPE_CLOSED; }
|
||||
/** \return The current cluster number for a file or directory. */
|
||||
uint32_t readCluster(void) { return readCluster_; }
|
||||
/** \return The read position for a file or directory. */
|
||||
uint32_t readPosition(void) { return readPosition_; }
|
||||
/**
|
||||
* Set the read position for a file or directory to \a pos.
|
||||
*
|
||||
* \param[in] pos The new read position in bytes from the beginning
|
||||
* of the file.
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
uint8_t seekSet(uint32_t pos) {
|
||||
if (pos >= readPosition_)
|
||||
return seekCur(pos - readPosition_);
|
||||
rewind();
|
||||
return seekCur(pos);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief get the parent volume
|
||||
@returns the parent volume
|
||||
*/
|
||||
FatVolume *volume(void) { return vol_; }
|
||||
};
|
||||
#endif // FatReader_h
|
||||
Reference in New Issue
Block a user