My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SdBaseFile.h 14KB

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