COSA
An Object-Oriented Platform for Arduino Programming
FAT16.hh
Go to the documentation of this file.
1 
22 #ifndef COSA_FAT16_HH
23 #define COSA_FAT16_HH
24 
25 #include <SD.h>
26 
27 #include "Cosa/IOStream.hh"
28 #include "Cosa/FS.hh"
29 
30 /*
31  * FAT16 file structures on SD card. Note: may only access files on the
32  * root directory.
33  *
34  * @section Acknowledgement
35  * Refactoring of Arduino Fat16 Library, Copyright (C) 2009 by William Greiman
36  *
37  * @section References
38  * 1. http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
39  * 2. http://code.google.com/p/fat16lib/
40  */
41 class FAT16 {
42 protected:
44  static uint8_t const BOOTSIG0 = 0X55;
45 
47  static uint8_t const BOOTSIG1 = 0XAA;
48 
53  struct part_t {
59  uint8_t boot;
64  uint8_t beginHead;
69  unsigned beginSector : 6;
73  unsigned beginCylinderHigh : 2;
83  uint8_t type;
88  uint8_t endHead;
93  unsigned endSector : 6;
97  unsigned endCylinderHigh : 2;
102  uint8_t endCylinderLow;
106  uint32_t firstSector;
110  uint32_t totalSectors;
111  };
112 
117  struct mbr_t {
121  uint8_t codeArea[440];
125  uint32_t diskSignature;
129  uint16_t usuallyZero;
133  part_t part[4];
137  uint8_t mbrSig0;
141  uint8_t mbrSig1;
142  };
143 
148  struct bpb_t {
153  uint16_t bytesPerSector;
168  uint8_t fatCount;
187  uint16_t totalSectors16;
194  uint8_t mediaType;
200  uint16_t sectorsPerFat16;
208  uint16_t headCount;
214  uint32_t hidddenSectors;
221  uint32_t totalSectors32;
225  uint32_t sectorsPerFat32;
236  uint16_t fat32Flags;
241  uint16_t fat32Version;
251  uint16_t fat32FSInfo;
262  uint8_t fat32Reserved[12];
263  };
264 
268  struct fbs_t {
272  uint8_t jmpToBootCode[3];
276  char oemName[8];
284  uint8_t driveNumber;
288  uint8_t reserved1;
292  uint8_t bootSignature;
300  char volumeLabel[11];
304  char fileSystemType[8];
308  uint8_t bootCode[420];
312  uint8_t bootSectorSig0;
316  uint8_t bootSectorSig1;
317  };
318 
320  static uint16_t const EOC16 = 0XFFFF;
321 
323  static uint16_t const EOC16_MIN = 0XFFF8;
324 
326  static uint32_t const EOC32 = 0X0FFFFFFF;
327 
329  static uint32_t const EOC32_MIN = 0X0FFFFFF8;
330 
332  static uint32_t const ENTRY32_MASK = 0X0FFFFFFF;
333 
338  struct dir_t {
344  uint8_t name[11];
351  uint8_t attributes;
356  uint8_t reservedNT;
366  uint16_t creationTime;
370  uint16_t creationDate;
376  uint16_t lastAccessDate;
385  uint16_t lastWriteTime;
389  uint16_t lastWriteDate;
393  uint16_t firstClusterLow;
397  uint32_t fileSize;
398  };
399 
402  static uint8_t const DIR_NAME_0XE5 = 0X05;
404  static uint8_t const DIR_NAME_DELETED = 0XE5;
406  static uint8_t const DIR_NAME_FREE = 0X00;
407 
409  static uint8_t const DIR_ATT_READ_ONLY = 0X01;
411  static uint8_t const DIR_ATT_HIDDEN = 0X02;
413  static uint8_t const DIR_ATT_SYSTEM = 0X04;
415  static uint8_t const DIR_ATT_VOLUME_ID = 0X08;
417  static uint8_t const DIR_ATT_DIRECTORY = 0X10;
419  static uint8_t const DIR_ATT_ARCHIVE = 0X20;
421  static uint8_t const DIR_ATT_LONG_NAME = 0X0F;
423  static uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F;
425  static uint8_t const DIR_ATT_DEFINED_BITS = 0X3F;
427  static uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
428  static uint8_t const DIR_ATT_SKIP = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
429 
433  static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir)
434  {
435  return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;
436  }
437 
441  static inline uint8_t DIR_IS_FILE(const dir_t* dir)
442  {
443  return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
444  }
445 
449  static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir)
450  {
451  return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
452  }
453 
457  static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir)
458  {
459  return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
460  }
461 
463  typedef uint16_t fat_t;
464 
465  union cache16_t {
467  uint8_t data[512];
469  fat_t fat[256];
471  dir_t dir[16];
476  };
477 
491  union date_t {
492  uint16_t as_uint16;
493  struct {
494  uint8_t day:5;
495  uint8_t month:4;
496  uint8_t year:7;
497  };
498  date_t(uint16_t y, uint8_t m, uint8_t d)
499  {
500  year = (y - 1980);
501  month = m;
502  day = d;
503  }
504  date_t(uint16_t date) { as_uint16 = date; }
505  uint16_t YEAR() { return (1980 + year); }
506  uint8_t MONTH() { return (month); }
507  uint8_t DAY() { return (day); }
508  operator uint16_t() { return (as_uint16); }
509  };
510 
512  friend IOStream& operator<<(IOStream& outs, date_t& date);
513 
527  union time_t {
528  uint16_t as_uint16;
529  struct {
530  uint8_t seconds:5;
531  uint8_t minutes:6;
532  uint8_t hours:5;
533  };
534  time_t(uint16_t h, uint8_t m, uint8_t s)
535  {
536  hours = h;
537  minutes = m;
538  seconds = s >> 1;
539  }
540  time_t(uint16_t now) { as_uint16 = now; }
541  uint16_t HOURS() { return (hours); }
542  uint8_t MINUTES() { return (minutes); }
543  uint8_t SECONDS() { return (seconds << 1); }
544  operator uint16_t() { return (as_uint16); }
545  };
546 
548  friend IOStream& operator<<(IOStream& outs, time_t& time);
549 
551  static const uint16_t DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
552 
554  static const uint16_t DEFAULT_TIME = (1 << 11);
555 
556 public:
557 
558  class File : public IOStream::Device {
559  public:
564  File() : IOStream::Device(), m_flags(0) {}
565 
578  bool open(const char* fileName, uint8_t oflag);
579 
584  bool is_open(void) const { return (m_flags & O_RDWR) != 0; }
585 
593  bool sync();
594 
604  bool remove();
605 
613  bool close()
614  {
615  if (!sync()) return false;
616  m_flags = 0;
617  return true;
618  }
619 
627  bool seek(uint32_t pos, uint8_t whence = SEEK_SET);
628 
632  uint32_t tell() { return (m_curPosition); }
633 
637  void rewind() { m_curPosition = m_curCluster = 0; }
638 
642  uint32_t size() { return (m_fileSize); }
643 
654  bool truncate(uint32_t size);
655 
662  virtual int putchar(char c);
663 
666 
674  virtual int write(const void *buf, size_t size);
675 
681  virtual int getchar();
682 
685 
693  virtual int read(void* buf, size_t size);
694 
695  protected:
696  uint8_t m_flags; // see above for bit definitions
697  int16_t m_dirEntryIndex; // index of directory entry for open file
698  fat_t m_firstCluster; // first cluster of file
699  uint32_t m_fileSize; // fileSize
700  fat_t m_curCluster; // current cluster
701  uint32_t m_curPosition; // current byte offset
702 
703  static uint8_t isEOC(fat_t cluster) { return cluster >= 0XFFF8; }
704  bool addCluster();
705  bool freeChain(fat_t cluster);
706  bool open(uint16_t entry, uint8_t oflag);
707  bool dirEntry(dir_t* dir);
708  };
709 
713  enum {
714  LS_DATE = 1,
716  } __attribute__((packed));
717 
731  static bool begin(SD* sd, uint8_t partion);
732 
743  static bool begin(SD* sd);
744 
752  static void ls(IOStream& outs, uint8_t flags = 0);
753 
767  static bool rm(const char* fileName)
768  {
769  FAT16::File file;
770  if (!file.open(fileName, O_WRITE)) return false;
771  return file.remove();
772  }
773 
774 protected:
775  // SD device (Fix: Should be an IOBlock::Device)
776  static SD *device;
777 
778  // Volume info
779  static bool volumeInitialized; // true if volume has been initialized
780  static uint8_t fatCount; // number of FATs
781  static uint8_t blocksPerCluster; // must be power of 2
782  static uint16_t rootDirEntryCount; // should be 512 for FAT16
783  static fat_t blocksPerFat; // number of blocks in one FAT
784  static fat_t clusterCount; // total clusters in volume
785  static uint32_t fatStartBlock; // start of first FAT
786  static uint32_t rootDirStartBlock; // start of root dir
787  static uint32_t dataStartBlock; // start of data clusters
788 
789  // block cache
790  static uint8_t const CACHE_FOR_READ = 0; // cache a block for read
791  static uint8_t const CACHE_FOR_WRITE = 1; // cache a block and set dirty
792  static cache16_t cacheBuffer; // 512 byte cache for raw blocks
793  static uint32_t cacheBlockNumber; // Logical number of block in the cache
794  static uint8_t cacheDirty; // cacheFlush() will write block if true
795  static uint32_t cacheMirrorBlock; // mirror block for second FAT
796 
797  // callback function for date/time
798  static void (*dateTime)(uint16_t* date, uint16_t* time);
799 
800  // define fields in flags_ require sync directory entry
801  static uint8_t const F_OFLAG = O_RDWR | O_APPEND | O_SYNC;
802  static uint8_t const F_FILE_DIR_DIRTY = 0X80;
803 
804  static bool make83Name(const char* str, uint8_t* name);
805 
806  static uint8_t blockOfCluster(uint32_t position)
807  {
808  return (position >> 9) & (blocksPerCluster - 1);
809  }
810  static uint16_t cacheDataOffset(uint32_t position)
811  {
812  return position & 0X1FF;
813  }
814  static dir_t* cacheDirEntry(uint16_t index, uint8_t action = 0);
815  static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action = 0);
816  static uint8_t cacheFlush(void);
817  static void cacheSetDirty(void)
818  {
819  cacheDirty |= CACHE_FOR_WRITE;
820  }
821  static uint32_t dataBlockLba(fat_t cluster, uint8_t blockOfCluster)
822  {
823  return (dataStartBlock +
824  (uint32_t)(cluster - 2) * blocksPerCluster +
825  blockOfCluster);
826  }
827 
828  static bool fatGet(fat_t cluster, fat_t* value);
829  static bool fatPut(fat_t cluster, fat_t value);
830 
831  static bool read(dir_t* dir, uint16_t* index, uint8_t skip = DIR_ATT_SKIP);
832  static void printDirName(IOStream& outs, const dir_t& dir, uint8_t width);
833 };
834 
835 #endif
uint16_t sectorsPerFat16
Definition: FAT16.hh:200
int16_t m_dirEntryIndex
Definition: FAT16.hh:697
static uint16_t const EOC16
Definition: FAT16.hh:320
static void(* dateTime)(uint16_t *date, uint16_t *time)
Definition: FAT16.hh:798
static uint32_t const EOC32
Definition: FAT16.hh:326
static uint8_t const F_OFLAG
Definition: FAT16.hh:801
static uint8_t cacheDirty
Definition: FAT16.hh:794
static uint8_t isEOC(fat_t cluster)
Definition: FAT16.hh:703
uint16_t as_uint16
Definition: FAT16.hh:492
static uint16_t const EOC16_MIN
Definition: FAT16.hh:323
uint8_t m_flags
Definition: FAT16.hh:696
Absolute position.
Definition: FS.hh:47
static uint8_t const CACHE_FOR_READ
Definition: FAT16.hh:790
uint16_t creationTime
Definition: FAT16.hh:366
static bool volumeInitialized
Definition: FAT16.hh:779
static SD * device
Definition: FAT16.hh:776
uint16_t lastWriteTime
Definition: FAT16.hh:385
static bool rm(const char *fileName)
Definition: FAT16.hh:767
static uint8_t const BOOTSIG1
Definition: FAT16.hh:47
static uint8_t const DIR_ATT_DIRECTORY
Definition: FAT16.hh:417
bool is_open(void) const
Definition: FAT16.hh:584
static uint8_t const CACHE_FOR_WRITE
Definition: FAT16.hh:791
uint8_t endHead
Definition: FAT16.hh:88
uint8_t type
Definition: FAT16.hh:83
uint8_t MINUTES()
Definition: FAT16.hh:542
uint32_t fat32RootCluster
Definition: FAT16.hh:246
uint16_t firstClusterHigh
Definition: FAT16.hh:381
static uint8_t const DIR_ATT_FILE_TYPE_MASK
Definition: FAT16.hh:427
uint16_t rootDirEntryCount
Definition: FAT16.hh:177
uint8_t mediaType
Definition: FAT16.hh:194
virtual int write(const void *buf, size_t size)
static uint8_t const DIR_NAME_FREE
Definition: FAT16.hh:406
virtual int read(void *buf, size_t size)
uint16_t firstClusterLow
Definition: FAT16.hh:393
uint32_t tell()
Definition: FAT16.hh:632
bool open(const char *fileName, uint8_t oflag)
Definition: FAT16.cpp:143
uint16_t fat32Version
Definition: FAT16.hh:241
unsigned beginCylinderHigh
Definition: FAT16.hh:73
static uint8_t blockOfCluster(uint32_t position)
Definition: FAT16.hh:806
static uint32_t const EOC32_MIN
Definition: FAT16.hh:329
unsigned beginSector
Definition: FAT16.hh:69
uint8_t driveNumber
Definition: FAT16.hh:284
time_t(uint16_t h, uint8_t m, uint8_t s)
Definition: FAT16.hh:534
static uint32_t rootDirStartBlock
Definition: FAT16.hh:786
static const uint16_t DEFAULT_TIME
Definition: FAT16.hh:554
uint16_t totalSectors16
Definition: FAT16.hh:187
static const uint16_t DEFAULT_DATE
Definition: FAT16.hh:551
static uint8_t const DIR_ATT_VOLUME_ID
Definition: FAT16.hh:415
static uint8_t const DIR_ATT_READ_ONLY
Definition: FAT16.hh:409
static fat_t clusterCount
Definition: FAT16.hh:784
uint8_t MONTH()
Definition: FAT16.hh:506
uint8_t beginCylinderLow
Definition: FAT16.hh:78
bool remove()
Definition: FAT16.cpp:228
void rewind()
Definition: FAT16.hh:637
unsigned endCylinderHigh
Definition: FAT16.hh:97
uint32_t fileSize
Definition: FAT16.hh:397
uint8_t bootSectorSig0
Definition: FAT16.hh:312
uint8_t bootSignature
Definition: FAT16.hh:292
uint32_t diskSignature
Definition: FAT16.hh:125
uint16_t fat32FSInfo
Definition: FAT16.hh:251
static uint8_t const DIR_ATT_DEFINED_BITS
Definition: FAT16.hh:425
static uint32_t dataBlockLba(fat_t cluster, uint8_t blockOfCluster)
Definition: FAT16.hh:821
uint8_t bootSectorSig1
Definition: FAT16.hh:316
Definition: SD.hh:35
static uint32_t fatStartBlock
Definition: FAT16.hh:785
uint16_t fat32BackBootBlock
Definition: FAT16.hh:257
static uint8_t const DIR_ATT_ARCHIVE
Definition: FAT16.hh:419
uint8_t mbrSig1
Definition: FAT16.hh:141
date_t(uint16_t y, uint8_t m, uint8_t d)
Definition: FAT16.hh:498
static uint8_t fatCount
Definition: FAT16.hh:780
static uint8_t const BOOTSIG0
Definition: FAT16.hh:44
static uint32_t cacheMirrorBlock
Definition: FAT16.hh:795
static uint8_t const DIR_NAME_DELETED
Definition: FAT16.hh:404
uint32_t hidddenSectors
Definition: FAT16.hh:214
static bool fatGet(fat_t cluster, fat_t *value)
Definition: FAT16.cpp:599
uint8_t DAY()
Definition: FAT16.hh:507
static void printDirName(IOStream &outs, const dir_t &dir, uint8_t width)
Definition: FAT16.cpp:483
fat_t m_firstCluster
Definition: FAT16.hh:698
static uint8_t blocksPerCluster
Definition: FAT16.hh:781
uint16_t as_uint16
Definition: FAT16.hh:528
static uint8_t const DIR_ATT_HIDDEN
Definition: FAT16.hh:411
uint8_t sectorsPerCluster
Definition: FAT16.hh:159
uint8_t endCylinderLow
Definition: FAT16.hh:102
uint8_t SECONDS()
Definition: FAT16.hh:543
uint16_t usuallyZero
Definition: FAT16.hh:129
static uint8_t const DIR_ATT_LONG_NAME
Definition: FAT16.hh:421
uint8_t beginHead
Definition: FAT16.hh:64
static fat_t blocksPerFat
Definition: FAT16.hh:783
uint16_t YEAR()
Definition: FAT16.hh:505
uint8_t creationTimeTenths
Definition: FAT16.hh:362
static bool begin(SD *sd, uint8_t partion)
Definition: FAT16.cpp:68
Open for reading and writing.
Definition: FS.hh:32
uint32_t sectorsPerFat32
Definition: FAT16.hh:225
static uint8_t const DIR_ATT_SYSTEM
Definition: FAT16.hh:413
static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action=0)
Definition: FAT16.cpp:587
time_t(uint16_t now)
Definition: FAT16.hh:540
uint16_t creationDate
Definition: FAT16.hh:370
static uint8_t DIR_IS_FILE(const dir_t *dir)
Definition: FAT16.hh:441
Definition: FAT16.hh:41
uint16_t sectorsPerTrtack
Definition: FAT16.hh:204
fat_t m_curCluster
Definition: FAT16.hh:700
uint16_t lastAccessDate
Definition: FAT16.hh:376
unsigned endSector
Definition: FAT16.hh:93
date_t(uint16_t date)
Definition: FAT16.hh:504
static uint8_t DIR_IS_SUBDIR(const dir_t *dir)
Definition: FAT16.hh:449
static bool make83Name(const char *str, uint8_t *name)
Definition: FAT16.cpp:25
bool close()
Definition: FAT16.hh:613
static void cacheSetDirty(void)
Definition: FAT16.hh:817
static uint8_t cacheFlush(void)
Definition: FAT16.cpp:569
static void ls(IOStream &outs, uint8_t flags=0)
Definition: FAT16.cpp:506
uint8_t fatCount
Definition: FAT16.hh:168
uint16_t fat_t
Definition: FAT16.hh:463
uint32_t totalSectors
Definition: FAT16.hh:110
uint32_t m_fileSize
Definition: FAT16.hh:699
friend IOStream & operator<<(IOStream &outs, date_t &date)
Definition: FAT16.cpp:638
static uint8_t const DIR_NAME_0XE5
Definition: FAT16.hh:402
static uint32_t dataStartBlock
Definition: FAT16.hh:787
uint16_t headCount
Definition: FAT16.hh:208
static uint16_t rootDirEntryCount
Definition: FAT16.hh:782
uint16_t lastWriteDate
Definition: FAT16.hh:389
uint32_t size()
Definition: FAT16.hh:642
uint32_t m_curPosition
Definition: FAT16.hh:701
static uint8_t const DIR_ATT_LONG_NAME_MASK
Definition: FAT16.hh:423
static uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t *dir)
Definition: FAT16.hh:457
uint8_t boot
Definition: FAT16.hh:59
uint16_t HOURS()
Definition: FAT16.hh:541
uint8_t mbrSig0
Definition: FAT16.hh:137
static uint32_t cacheBlockNumber
Definition: FAT16.hh:793
static bool fatPut(fat_t cluster, fat_t value)
Definition: FAT16.cpp:611
static bool read(dir_t *dir, uint16_t *index, uint8_t skip=DIR_ATT_SKIP)
Definition: FAT16.cpp:455
uint8_t attributes
Definition: FAT16.hh:351
uint16_t reservedSectorCount
Definition: FAT16.hh:164
uint16_t fat32Flags
Definition: FAT16.hh:236
uint8_t reservedNT
Definition: FAT16.hh:356
static uint32_t const ENTRY32_MASK
Definition: FAT16.hh:332
uint32_t volumeSerialNumber
Definition: FAT16.hh:296
static dir_t * cacheDirEntry(uint16_t index, uint8_t action=0)
Definition: FAT16.cpp:561
Definition: FS.hh:33
static uint8_t DIR_IS_LONG_NAME(const dir_t *dir)
Definition: FAT16.hh:433
uint16_t bytesPerSector
Definition: FAT16.hh:153
uint32_t totalSectors32
Definition: FAT16.hh:221
Open for write.
Definition: FS.hh:30
static uint8_t const F_FILE_DIR_DIRTY
Definition: FAT16.hh:802
Synchronous writes.
Definition: FS.hh:35
static uint8_t const DIR_ATT_SKIP
Definition: FAT16.hh:428
uint8_t reserved1
Definition: FAT16.hh:288
bpb_t bpb
Definition: FAT16.hh:280
uint32_t firstSector
Definition: FAT16.hh:106
static cache16_t cacheBuffer
Definition: FAT16.hh:792
static uint16_t cacheDataOffset(uint32_t position)
Definition: FAT16.hh:810