Subversion Repositories MK-Marlin

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ron 1
/**
2
 * Marlin 3D Printer Firmware
3
 * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
 *
5
 * Based on Sprinter and grbl.
6
 * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
 
23
/**
24
 * \file
25
 * \brief SdBaseFile class
26
 */
27
 
28
/**
29
 * Arduino SdFat Library
30
 * Copyright (C) 2009 by William Greiman
31
 *
32
 * This file is part of the Arduino Sd2Card Library
33
 */
34
#ifndef _SDBASEFILE_H_
35
#define _SDBASEFILE_H_
36
 
37
#include "SdFatConfig.h"
38
#include "SdVolume.h"
39
 
40
#include <stdint.h>
41
 
42
/**
43
 * \struct filepos_t
44
 * \brief internal type for istream
45
 * do not use in user apps
46
 */
47
struct filepos_t {
48
  uint32_t position;  // stream byte position
49
  uint32_t cluster;   // cluster of position
50
  filepos_t() : position(0), cluster(0) {}
51
};
52
 
53
// use the gnu style oflag in open()
54
uint8_t const O_READ = 0x01,                    // open() oflag for reading
55
              O_RDONLY = O_READ,                // open() oflag - same as O_IN
56
              O_WRITE = 0x02,                   // open() oflag for write
57
              O_WRONLY = O_WRITE,               // open() oflag - same as O_WRITE
58
              O_RDWR = (O_READ | O_WRITE),      // open() oflag for reading and writing
59
              O_ACCMODE = (O_READ | O_WRITE),   // open() oflag mask for access modes
60
              O_APPEND = 0x04,                  // The file offset shall be set to the end of the file prior to each write.
61
              O_SYNC = 0x08,                    // Synchronous writes - call sync() after each write
62
              O_TRUNC = 0x10,                   // Truncate the file to zero length
63
              O_AT_END = 0x20,                  // Set the initial position at the end of the file
64
              O_CREAT = 0x40,                   // Create the file if nonexistent
65
              O_EXCL = 0x80;                    // If O_CREAT and O_EXCL are set, open() shall fail if the file exists
66
 
67
// SdBaseFile class static and const definitions
68
 
69
// flags for ls()
70
uint8_t const LS_DATE = 1,    // ls() flag to print modify date
71
              LS_SIZE = 2,    // ls() flag to print file size
72
              LS_R = 4;       // ls() flag for recursive list of subdirectories
73
 
74
 
75
// flags for timestamp
76
uint8_t const T_ACCESS = 1,   // Set the file's last access date
77
              T_CREATE = 2,   // Set the file's creation date and time
78
              T_WRITE = 4;    // Set the file's write date and time
79
 
80
// values for type_
81
uint8_t const FAT_FILE_TYPE_CLOSED = 0,                           // This file has not been opened.
82
              FAT_FILE_TYPE_NORMAL = 1,                           // A normal file
83
              FAT_FILE_TYPE_ROOT_FIXED = 2,                       // A FAT12 or FAT16 root directory
84
              FAT_FILE_TYPE_ROOT32 = 3,                           // A FAT32 root directory
85
              FAT_FILE_TYPE_SUBDIR = 4,                           // A subdirectory file
86
              FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED;   // Test value for directory type
87
 
88
/**
89
 * date field for FAT directory entry
90
 * \param[in] year [1980,2107]
91
 * \param[in] month [1,12]
92
 * \param[in] day [1,31]
93
 *
94
 * \return Packed date for dir_t entry.
95
 */
96
static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { return (year - 1980) << 9 | month << 5 | day; }
97
 
98
/**
99
 * year part of FAT directory date field
100
 * \param[in] fatDate Date in packed dir format.
101
 *
102
 * \return Extracted year [1980,2107]
103
 */
104
static inline uint16_t FAT_YEAR(uint16_t fatDate) { return 1980 + (fatDate >> 9); }
105
 
106
/**
107
 * month part of FAT directory date field
108
 * \param[in] fatDate Date in packed dir format.
109
 *
110
 * \return Extracted month [1,12]
111
 */
112
static inline uint8_t FAT_MONTH(uint16_t fatDate) { return (fatDate >> 5) & 0XF; }
113
 
114
/**
115
 * day part of FAT directory date field
116
 * \param[in] fatDate Date in packed dir format.
117
 *
118
 * \return Extracted day [1,31]
119
 */
120
static inline uint8_t FAT_DAY(uint16_t fatDate) { return fatDate & 0x1F; }
121
 
122
/**
123
 * time field for FAT directory entry
124
 * \param[in] hour [0,23]
125
 * \param[in] minute [0,59]
126
 * \param[in] second [0,59]
127
 *
128
 * \return Packed time for dir_t entry.
129
 */
130
static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { return hour << 11 | minute << 5 | second >> 1; }
131
 
132
/**
133
 * hour part of FAT directory time field
134
 * \param[in] fatTime Time in packed dir format.
135
 *
136
 * \return Extracted hour [0,23]
137
 */
138
static inline uint8_t FAT_HOUR(uint16_t fatTime) { return fatTime >> 11; }
139
 
140
/**
141
 * minute part of FAT directory time field
142
 * \param[in] fatTime Time in packed dir format.
143
 *
144
 * \return Extracted minute [0,59]
145
 */
146
static inline uint8_t FAT_MINUTE(uint16_t fatTime) { return (fatTime >> 5) & 0x3F; }
147
 
148
/**
149
 * second part of FAT directory time field
150
 * Note second/2 is stored in packed time.
151
 *
152
 * \param[in] fatTime Time in packed dir format.
153
 *
154
 * \return Extracted second [0,58]
155
 */
156
static inline uint8_t FAT_SECOND(uint16_t fatTime) { return 2 * (fatTime & 0x1F); }
157
 
158
// Default date for file timestamps is 1 Jan 2000
159
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
160
// Default time for file timestamp is 1 am
161
uint16_t const FAT_DEFAULT_TIME = (1 << 11);
162
 
163
/**
164
 * \class SdBaseFile
165
 * \brief Base class for SdFile with Print and C++ streams.
166
 */
167
class SdBaseFile {
168
 public:
169
  SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
170
  SdBaseFile(const char* path, uint8_t oflag);
171
  ~SdBaseFile() { if (isOpen()) close(); }
172
 
173
  /**
174
   * writeError is set to true if an error occurs during a write().
175
   * Set writeError to false before calling print() and/or write() and check
176
   * for true after calls to print() and/or write().
177
   */
178
  bool writeError;
179
 
180
  // helpers for stream classes
181
 
182
  /**
183
   * get position for streams
184
   * \param[out] pos struct to receive position
185
   */
186
  void getpos(filepos_t* pos);
187
 
188
  /**
189
   * set position for streams
190
   * \param[out] pos struct with value for new position
191
   */
192
  void setpos(filepos_t* pos);
193
 
194
  bool close();
195
  bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
196
  bool createContiguous(SdBaseFile* dirFile,
197
                        const char* path, uint32_t size);
198
  /**
199
   * \return The current cluster number for a file or directory.
200
   */
201
  uint32_t curCluster() const { return curCluster_; }
202
 
203
  /**
204
   * \return The current position for a file or directory.
205
   */
206
  uint32_t curPosition() const { return curPosition_; }
207
 
208
  /**
209
   * \return Current working directory
210
   */
211
  static SdBaseFile* cwd() { return cwd_; }
212
 
213
  /**
214
   * Set the date/time callback function
215
   *
216
   * \param[in] dateTime The user's call back function.  The callback
217
   * function is of the form:
218
   *
219
   * \code
220
   * void dateTime(uint16_t* date, uint16_t* time) {
221
   *   uint16_t year;
222
   *   uint8_t month, day, hour, minute, second;
223
   *
224
   *   // User gets date and time from GPS or real-time clock here
225
   *
226
   *   // return date using FAT_DATE macro to format fields
227
   *   *date = FAT_DATE(year, month, day);
228
   *
229
   *   // return time using FAT_TIME macro to format fields
230
   *   *time = FAT_TIME(hour, minute, second);
231
   * }
232
   * \endcode
233
   *
234
   * Sets the function that is called when a file is created or when
235
   * a file's directory entry is modified by sync(). All timestamps,
236
   * access, creation, and modify, are set when a file is created.
237
   * sync() maintains the last access date and last modify date/time.
238
   *
239
   * See the timestamp() function.
240
   */
241
  static void dateTimeCallback(
242
    void (*dateTime)(uint16_t* date, uint16_t* time)) {
243
    dateTime_ = dateTime;
244
  }
245
 
246
  /**
247
   * Cancel the date/time callback function.
248
   */
249
  static void dateTimeCallbackCancel() { dateTime_ = 0; }
250
  bool dirEntry(dir_t* dir);
251
  static void dirName(const dir_t& dir, char* name);
252
  bool exists(const char* name);
253
  int16_t fgets(char* str, int16_t num, char* delim = 0);
254
 
255
  /**
256
   * \return The total number of bytes in a file or directory.
257
   */
258
  uint32_t fileSize() const { return fileSize_; }
259
 
260
  /**
261
   * \return The first cluster number for a file or directory.
262
   */
263
  uint32_t firstCluster() const { return firstCluster_; }
264
 
265
  /**
266
   * \return True if this is a directory else false.
267
   */
268
  bool isDir() const { return type_ >= FAT_FILE_TYPE_MIN_DIR; }
269
 
270
  /**
271
   * \return True if this is a normal file else false.
272
   */
273
  bool isFile() const { return type_ == FAT_FILE_TYPE_NORMAL; }
274
 
275
  /**
276
   * \return True if this is an open file/directory else false.
277
   */
278
  bool isOpen() const { return type_ != FAT_FILE_TYPE_CLOSED; }
279
 
280
  /**
281
   * \return True if this is a subdirectory else false.
282
   */
283
  bool isSubDir() const { return type_ == FAT_FILE_TYPE_SUBDIR; }
284
 
285
  /**
286
   * \return True if this is the root directory.
287
   */
288
  bool isRoot() const { return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32; }
289
 
290
  bool getFilename(char * const name);
291
  void ls(uint8_t flags = 0, uint8_t indent = 0);
292
 
293
  bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
294
  bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
295
  bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
296
  bool open(const char* path, uint8_t oflag = O_READ);
297
  bool openNext(SdBaseFile* dirFile, uint8_t oflag);
298
  bool openRoot(SdVolume* vol);
299
  int peek();
300
  static void printFatDate(uint16_t fatDate);
301
  static void printFatTime(uint16_t fatTime);
302
  bool printName();
303
  int16_t read();
304
  int16_t read(void* buf, uint16_t nbyte);
305
  int8_t readDir(dir_t* dir, char* longFilename);
306
  static bool remove(SdBaseFile* dirFile, const char* path);
307
  bool remove();
308
 
309
  /**
310
   * Set the file's current position to zero.
311
   */
312
  void rewind() { seekSet(0); }
313
  bool rename(SdBaseFile* dirFile, const char* newPath);
314
  bool rmdir();
315
  bool rmRfStar();
316
 
317
  /**
318
   * Set the files position to current position + \a pos. See seekSet().
319
   * \param[in] offset The new position in bytes from the current position.
320
   * \return true for success or false for failure.
321
   */
322
  bool seekCur(const int32_t offset) { return seekSet(curPosition_ + offset); }
323
 
324
  /**
325
   * Set the files position to end-of-file + \a offset. See seekSet().
326
   * \param[in] offset The new position in bytes from end-of-file.
327
   * \return true for success or false for failure.
328
   */
329
  bool seekEnd(const int32_t offset = 0) { return seekSet(fileSize_ + offset); }
330
  bool seekSet(const uint32_t pos);
331
  bool sync();
332
  bool timestamp(SdBaseFile* file);
333
  bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
334
                 uint8_t hour, uint8_t minute, uint8_t second);
335
 
336
  /**
337
   * Type of file. Use isFile() or isDir() instead of type() if possible.
338
   *
339
   * \return The file or directory type.
340
   */
341
  uint8_t type() const { return type_; }
342
  bool truncate(uint32_t size);
343
 
344
  /**
345
   * \return SdVolume that contains this file.
346
   */
347
  SdVolume* volume() const { return vol_; }
348
  int16_t write(const void* buf, uint16_t nbyte);
349
 
350
 private:
351
  friend class SdFat;           // allow SdFat to set cwd_
352
  static SdBaseFile* cwd_;      // global pointer to cwd dir
353
 
354
  // data time callback function
355
  static void (*dateTime_)(uint16_t* date, uint16_t* time);
356
 
357
  // bits defined in flags_
358
  static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC),   // should be 0x0F
359
                       F_FILE_DIR_DIRTY = 0x80;                     // sync of directory entry required
360
 
361
  // private data
362
  uint8_t   flags_;         // See above for definition of flags_ bits
363
  uint8_t   fstate_;        // error and eof indicator
364
  uint8_t   type_;          // type of file see above for values
365
  uint32_t  curCluster_;    // cluster for current file position
366
  uint32_t  curPosition_;   // current file position in bytes from beginning
367
  uint32_t  dirBlock_;      // block for this files directory entry
368
  uint8_t   dirIndex_;      // index of directory entry in dirBlock
369
  uint32_t  fileSize_;      // file size in bytes
370
  uint32_t  firstCluster_;  // first cluster of file
371
  SdVolume* vol_;           // volume where file is located
372
 
373
  /**
374
   * EXPERIMENTAL - Don't use!
375
   */
376
  //bool openParent(SdBaseFile* dir);
377
 
378
  // private functions
379
  bool addCluster();
380
  bool addDirCluster();
381
  dir_t* cacheDirEntry(uint8_t action);
382
  int8_t lsPrintNext(uint8_t flags, uint8_t indent);
383
  static bool make83Name(const char* str, uint8_t* name, const char** ptr);
384
  bool mkdir(SdBaseFile* parent, const uint8_t dname[11]);
385
  bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
386
  bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
387
  dir_t* readDirCache();
388
};
389
 
390
#endif // _SDBASEFILE_H_