Arduino FatFS
fatfs.h
1 /*
2 
3  SD - a slightly more friendly wrapper for FatFs
4 
5  This library aims to expose a subset of SD card functionality
6  in the form of a higher level "wrapper" object.
7 
8  It uses the same API like the Arduino SD libaray.
9 
10  License: GNU General Public License V3
11  (Because sdfatlib is licensed with this.)
12 
13  (C) Copyright 2022 Phil Schatzmann
14 
15 */
16 
30 #pragma once
31 
32 #ifdef ARDUINO
33 #include <Stream.h>
34 #else
35 #include "stream/Stream.h"
36 #endif
37 
38 #include "fatfs-drivers.h"
39 #include "ff/ff.h"
40 
41 #define FILE_READ FA_READ
42 #define FILE_WRITE (FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_APPEND)
43 
44 namespace fatfs {
45 using namespace fatfs;
46 
47 // forward declaration
48 class SDClass;
49 
55 class File : public Stream {
56  friend class SDClass;
57 
58  public:
59  File() = default;
60  ~File() {
61  if (is_open) close();
62  }
63 
64  virtual size_t write(uint8_t ch) {
65  if (fs == nullptr) return 0;
66  int rc = fs->f_putc(ch, &file);
67  return rc == EOF ? 0 : 1;
68  }
69  virtual size_t write(const uint8_t *buf, size_t size) {
70  if (fs == nullptr) return 0;
71  UINT result;
72  FRESULT rc = fs->f_write(&file, buf, size, &result);
73  return rc == FR_OK ? result : 0;
74  }
76  virtual int read() {
77  UINT result;
78  char buf[1] = {0};
79  readBytes((uint8_t *)buf, 1);
80  return result == 1 ? buf[0] : -1;
81  }
83  virtual int peek() {
84  uint32_t pos = position();
85  int result = read();
86  seek(pos);
87  return result;
88  }
89  virtual int available() { return info.fsize - position(); }
90 
91  virtual void flush() {
92  if (!isDirectory()) fs->f_sync(&file);
93  }
94 
95  size_t readBytes(uint8_t *data, size_t len) override {
96  if (isDirectory()) return 0;
97  UINT result;
98  auto rc = fs->f_read(&file, data, len, &result);
99  return rc == FR_OK ? result : 0;
100 
101  }
102 
103  int read(void *buf, size_t nbyte) {
104  return readBytes((uint8_t*)buf, nbyte);
105  }
106 
107  bool seek(uint32_t pos) {
108  if (isDirectory()) return 0;
109 
110  return fs->f_lseek(&file, pos);
111  }
112 
113  uint32_t position() {
114  if (isDirectory()) return 0;
115  return fs->f_tell(&file);
116  }
117 
118  uint32_t size() { return fs->f_size(&file); }
119 
120  void close() {
121  if (isDirectory())
122  fs->f_closedir(&dir);
123  else
124  fs->f_close(&file);
125  is_open = false;
126  }
127 
128  char *name() { return info.fname; }
129 
131  void getName(char *name, int len) { strncpy(name, info.fname, len); }
132 
133  bool isDirectory(void) { return info.fattrib & AM_DIR; }
134 
135  File openNextFile(uint8_t mode = FA_READ) {
136  File result;
137  FRESULT rc = fs->f_findnext(&dir, &result.info);
138  if (rc == FR_OK) {
139  result.is_open = true;
140  if (!result.isDirectory()) {
141  fs->f_open(&result.file, result.name(), mode);
142  } else {
143  fs->f_opendir(&result.dir, result.name());
144  }
145  }
146 
147  return result;
148  }
149  void rewindDirectory(void) { fs->f_rewinddir(&dir); }
150 
151  operator bool() { return is_open; }
152 
153  bool isEOF() {
154  if (isDirectory()) return false;
155  return fs->f_eof(&file);
156  }
157 
158  using Print::print;
159  using Print::println;
160  using Print::write;
161 
163  FIL *getFIL() { return isDirectory() ? nullptr : &file; }
165  DIR *getDIR() { return isDirectory() ? &dir : nullptr; }
167  FatFs *getFatFs() { return fs; }
169  IO *getDriver() { return fs->getDriver(); }
170 
171  protected:
172  FIL file = {0};
173  DIR dir = {0};
174  FILINFO info = {0};
175  FatFs *fs = nullptr;
176  bool is_open = false;
177 
179  bool update_stat(FatFs &fat_fs, const char *filepath) {
180  is_open = fat_fs.f_stat(filepath, &info) == FR_OK;
181  return is_open;
182  }
183 };
184 
190 class SDClass {
191  public:
192  SDClass() {
193 #ifdef ARDUINO
194  setDriver(&drv);
195 #endif
196  };
197  SDClass(IO &driver) { setDriver(driver); }
198  ~SDClass() { end(); }
199 
201  bool begin(IO &driver) {
202  setDriver(driver);
203  return begin();
204  }
205 
208  bool begin() {
209  if (getDriver() == nullptr) return false;
210  return handleError(getDriver()->mount(fat_fs));
211  }
212 
213 #ifdef ARDUINO
215  bool begin(int cs, SPIClass &spi = SPI) {
216  drv.setSPI(cs, spi);
217  return begin();
218  }
219 #endif
222  void end() {
223  if (getDriver() != nullptr) getDriver()->un_mount(fat_fs);
224  delete[] (work_buffer);
225  work_buffer = nullptr;
226  }
227 
231  File open(const char *filename, uint8_t mode = FILE_READ) {
232  File file;
233  FRESULT result;
234  if (mode & FA_WRITE || file.update_stat(fat_fs, filename)) {
235  if (file.isDirectory()) {
236  result = fat_fs.f_opendir(&file.dir, filename);
237  } else {
238  result = fat_fs.f_open(&file.file, filename, mode);
239  }
240  file.is_open = handleError(result);
241  file.fs = &fat_fs;
242  }
243  return file;
244  }
245 
246  File open(const String &filename, uint8_t mode = FILE_READ) {
247  return open(filename.c_str(), mode);
248  }
249 
251  bool exists(const char *filepath) {
252  FILINFO info;
253  FRESULT rc = fat_fs.f_stat(filepath, &info); /* Get file status */
254  return rc == FR_OK;
255  }
256 
257  bool exists(const String &filepath) { return exists(filepath.c_str()); }
258 
261  bool mkdir(const char *filepath) { return fat_fs.f_mkdir(filepath) == FR_OK; }
262  bool mkdir(const String &filepath) { return mkdir(filepath.c_str()); }
263 
265  bool remove(const char *filepath) {
266  return fat_fs.f_unlink(filepath) == FR_OK;
267  }
268  bool remove(const String &filepath) { return remove(filepath.c_str()); }
269 
270  bool rmdir(const char *filepath) {
271  return fat_fs.f_unlink(filepath) == FR_OK;
272  }
273  bool rmdir(const String &filepath) { return rmdir(filepath.c_str()); }
274 
276  bool chdir(const char *filepath) { return fat_fs.f_chdir(filepath) == FR_OK; }
278  bool chdir(String filepath) { return chdir(filepath.c_str()); }
281  bool getcwd(char *buff, size_t len) {
282  return fat_fs.f_getcwd(buff, len) == FR_OK;
283  }
284 
285 #if FF_USE_MKFS == 1
287  bool mkfs(int workBufferSize = FF_MAX_SS) {
288  if (work_buffer == nullptr) work_buffer = new uint8_t[workBufferSize];
289  return handleError(fat_fs.f_mkfs("", nullptr, work_buffer, workBufferSize));
290  }
291 #endif
293  FatFs *getFatFs() { return &fat_fs; }
294 
296  void setDriver(IO &driver) { fat_fs.setDriver(driver); }
298  IO *getDriver() { return fat_fs.getDriver(); }
299 
300  protected:
301 #ifdef ARDUINO
303 #endif
304  FatFs fat_fs;
305  uint8_t *work_buffer = nullptr;
306 
307  bool handleError(FRESULT rc) {
308  if (rc != FR_OK) {
309  Serial.print("fatfs: error no: ");
310  Serial.println((int)rc);
311  return false;
312  }
313  return true;
314  }
315 };
316 }; // namespace fatfs
317 
318 // This ensure compatibility with sketches that uses only SD library
319 #if !defined(FATFS_NO_NAMESPACE)
320 using namespace fatfs;
321 #endif
322 
323 static fatfs::SDClass SD;
API for FatFS See http://elm-chan.org/fsw/ff/00index_e.html.
Definition: ff.h:34
FRESULT f_close(FIL *fp)
Definition: ff.cpp:4065
FRESULT f_getcwd(TCHAR *buff, UINT len)
FRESULT f_findnext(DIR *dp, FILINFO *fno)
FRESULT f_stat(const TCHAR *path, FILINFO *fno)
Definition: ff.cpp:4625
FRESULT f_opendir(DIR *dp, const TCHAR *path)
Definition: ff.cpp:4443
FRESULT f_unlink(const TCHAR *path)
Definition: ff.cpp:4800
IO * getDriver()
Definition: ff.h:40
FRESULT f_sync(FIL *fp)
Definition: ff.cpp:3984
FRESULT f_mkfs(const TCHAR *path, const MKFS_PARM *opt, void *work, UINT len)
Definition: ff.cpp:5708
FRESULT f_lseek(FIL *fp, FSIZE_t ofs)
Definition: ff.cpp:4280
FRESULT f_write(FIL *fp, const void *buff, UINT btw, UINT *bw)
Definition: ff.cpp:3862
FRESULT f_read(FIL *fp, void *buff, UINT btr, UINT *br)
Definition: ff.cpp:3761
FRESULT f_chdir(const TCHAR *path)
FRESULT f_mkdir(const TCHAR *path)
Definition: ff.cpp:4894
FRESULT f_closedir(DIR *dp)
Definition: ff.cpp:4509
int f_putc(TCHAR c, FIL *fp)
Definition: ff.cpp:6530
FRESULT f_open(FIL *fp, const TCHAR *path, BYTE mode)
Definition: ff.cpp:3569
File implementation for fatfs.
Definition: fatfs.h:55
virtual int peek()
Very inefficient: to be avoided.
Definition: fatfs.h:83
IO * getDriver()
Access lo low level driver.
Definition: fatfs.h:169
void getName(char *name, int len)
Provides the name: getName() is supported by the SDFat Library.
Definition: fatfs.h:131
DIR * getDIR()
Access to low level FatFS api.
Definition: fatfs.h:165
virtual int read()
Very inefficient: to be avoided.
Definition: fatfs.h:76
FatFs * getFatFs()
Access to low level FatFS api to use functionality not exposed by this API.
Definition: fatfs.h:167
FIL * getFIL()
Access to low level FatFS api.
Definition: fatfs.h:163
bool update_stat(FatFs &fat_fs, const char *filepath)
update fs, info and is_open
Definition: fatfs.h:179
FatFS interface definition.
Definition: IO.h:74
virtual FRESULT un_mount(FatFs &fs)
unmount the file system
Definition: IO.cpp:8
Accessing a SD card via the Arduino SPI API.
Definition: SDArduinoSPIIO.h:48
SDClass: starting driver, access to files.
Definition: fatfs.h:190
bool chdir(const char *filepath)
Change directoy: extended functionality not available in Arduino SD API.
Definition: fatfs.h:276
void setDriver(IO &driver)
Set the driver.
Definition: fatfs.h:296
void end()
Definition: fatfs.h:222
bool mkdir(const char *filepath)
Definition: fatfs.h:261
bool chdir(String filepath)
Change directoy: extended functionality not available in Arduino SD API.
Definition: fatfs.h:278
bool begin(IO &driver)
Initialization of SD card: Use before other methods.
Definition: fatfs.h:201
bool mkfs(int workBufferSize=FF_MAX_SS)
format drive
Definition: fatfs.h:287
File open(const char *filename, uint8_t mode=FILE_READ)
Definition: fatfs.h:231
bool getcwd(char *buff, size_t len)
Definition: fatfs.h:281
bool exists(const char *filepath)
Methods to determine if the requested file path exists.
Definition: fatfs.h:251
bool begin()
Initialization of SD card. We use the SPI SD driver if nothing has been defined in the constructor.
Definition: fatfs.h:208
FatFs * getFatFs()
Access to low level FatFS api to use functionality not exposed by this API.
Definition: fatfs.h:293
IO * getDriver()
Access lo low level driver.
Definition: fatfs.h:298
bool remove(const char *filepath)
Delete the file.
Definition: fatfs.h:265
Definition: ffdef.h:200
Definition: ffdef.h:218
Definition: ffdef.h:175