diff --git a/Marlin/src/gcode/queue.cpp b/Marlin/src/gcode/queue.cpp
index 9f104ce801dc4e3b33e10f9f29a7b683dcef73af..54614bc25efd4916a2eb7f3fdbfecb506d916df0 100644
--- a/Marlin/src/gcode/queue.cpp
+++ b/Marlin/src/gcode/queue.cpp
@@ -361,19 +361,25 @@ inline void get_serial_commands() {
|| ((sd_char == '#' || sd_char == ':') && !sd_comment_mode)
) {
if (card_eof) {
- SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
+
card.printingHasFinished();
- #if ENABLED(PRINTER_EVENT_LEDS)
- LCD_MESSAGEPGM(MSG_INFO_COMPLETED_PRINTS);
- set_led_color(0, 255, 0); // Green
- #if HAS_RESUME_CONTINUE
- enqueue_and_echo_commands_P(PSTR("M0")); // end of the queue!
- #else
- safe_delay(1000);
+
+ if (card.sdprinting)
+ sd_count = 0; // If a sub-file was printing, continue from call point
+ else {
+ SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
+ #if ENABLED(PRINTER_EVENT_LEDS)
+ LCD_MESSAGEPGM(MSG_INFO_COMPLETED_PRINTS);
+ set_led_color(0, 255, 0); // Green
+ #if HAS_RESUME_CONTINUE
+ enqueue_and_echo_commands_P(PSTR("M0")); // end of the queue!
+ #else
+ safe_delay(1000);
+ #endif
+ set_led_color(0, 0, 0); // OFF
#endif
- set_led_color(0, 0, 0); // OFF
- #endif
- card.checkautostart(true);
+ card.checkautostart(true);
+ }
}
else if (n == -1) {
SERIAL_ERROR_START();
diff --git a/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M928.cpp b/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M928.cpp
index 001783585fea8748ba4b719e92fd7f5e2e69cdb6..566a8801036f3643d233b7c27abd3d88ee871746 100644
--- a/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M928.cpp
+++ b/Marlin/src/gcode/sdcard/M20-M30_M32-M34_M928.cpp
@@ -124,19 +124,23 @@ void GcodeSuite::M30() {
/**
* M32: Select file and start SD Print
+ *
+ * Examples:
+ *
+ * M32 !PATH/TO/FILE.GCO# ; Start FILE.GCO
+ * M32 P !PATH/TO/FILE.GCO# ; Start FILE.GCO as a procedure
+ * M32 S60 !PATH/TO/FILE.GCO# ; Start FILE.GCO at byte 60
+ *
*/
void GcodeSuite::M32() {
- if (IS_SD_PRINTING)
- stepper.synchronize();
-
- char* namestartpos = parser.string_arg;
- const bool call_procedure = parser.boolval('P');
+ if (card.sdprinting) stepper.synchronize();
if (card.cardOK) {
- card.openFile(namestartpos, true, call_procedure);
+ const bool call_procedure = parser.boolval('P');
+
+ card.openFile(parser.string_arg, true, call_procedure);
- if (parser.seenval('S'))
- card.setIndex(parser.value_long());
+ if (parser.seenval('S')) card.setIndex(parser.value_long());
card.startFileprint();
diff --git a/Marlin/src/sd/Sd2Card.cpp b/Marlin/src/sd/Sd2Card.cpp
index d0e807f82f994841109ddef0392f3de094bec0e0..4955e9949a7313ff05f4c4952d663023c44485ec 100644
--- a/Marlin/src/sd/Sd2Card.cpp
+++ b/Marlin/src/sd/Sd2Card.cpp
@@ -35,7 +35,6 @@
#include "../Marlin.h"
-//------------------------------------------------------------------------------
// send command and return error code. Return zero for OK
uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
// select card
@@ -63,7 +62,7 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
for (uint8_t i = 0; ((status_ = spiRec()) & 0x80) && i != 0xFF; i++) { /* Intentionally left empty */ }
return status_;
}
-//------------------------------------------------------------------------------
+
/**
* Determine the size of an SD flash memory card.
*
@@ -91,19 +90,20 @@ uint32_t Sd2Card::cardSize() {
return 0;
}
}
-//------------------------------------------------------------------------------
+
void Sd2Card::chipSelectHigh() {
digitalWrite(chipSelectPin_, HIGH);
}
-//------------------------------------------------------------------------------
+
void Sd2Card::chipSelectLow() {
#if DISABLED(SOFTWARE_SPI)
spiInit(spiRate_);
#endif // SOFTWARE_SPI
digitalWrite(chipSelectPin_, LOW);
}
-//------------------------------------------------------------------------------
-/** Erase a range of blocks.
+
+/**
+ * Erase a range of blocks.
*
* \param[in] firstBlock The address of the first block in the range.
* \param[in] lastBlock The address of the last block in the range.
@@ -113,8 +113,7 @@ void Sd2Card::chipSelectLow() {
* either 0 or 1, depends on the card vendor. The card must support
* single block erase.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
csd_t csd;
@@ -149,26 +148,26 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
chipSelectHigh();
return false;
}
-//------------------------------------------------------------------------------
-/** Determine if card supports single block erase.
+
+/**
+ * Determine if card supports single block erase.
*
- * \return The value one, true, is returned if single block erase is supported.
- * The value zero, false, is returned if single block erase is not supported.
+ * \return true if single block erase is supported.
+ * false if single block erase is not supported.
*/
bool Sd2Card::eraseSingleBlockEnable() {
csd_t csd;
return readCSD(&csd) ? csd.v1.erase_blk_en : false;
}
-//------------------------------------------------------------------------------
+
/**
* Initialize an SD flash memory card.
*
* \param[in] sckRateID SPI clock rate selector. See setSckRate().
* \param[in] chipSelectPin SD chip select pin number.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure. The reason for failure
- * can be determined by calling errorCode() and errorData().
+ * \return true for success, false for failure.
+ * The reason for failure can be determined by calling errorCode() and errorData().
*/
bool Sd2Card::init(uint8_t sckRateID, pin_t chipSelectPin) {
errorCode_ = type_ = 0;
@@ -247,14 +246,13 @@ bool Sd2Card::init(uint8_t sckRateID, pin_t chipSelectPin) {
chipSelectHigh();
return false;
}
-//------------------------------------------------------------------------------
+
/**
* Read a 512 byte block from an SD card.
*
* \param[in] blockNumber Logical block to be read.
* \param[out] dst Pointer to the location that will receive the data.
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
// use address if not SDHC card
@@ -262,19 +260,18 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
#if ENABLED(SD_CHECK_AND_RETRY)
uint8_t retryCnt = 3;
- do {
- if (!cardCommand(CMD17, blockNumber)) {
- if (readData(dst, 512)) return true;
- }
- else
+ for(;;) {
+ if (cardCommand(CMD17, blockNumber))
error(SD_CARD_ERROR_CMD17);
+ else if (readData(dst, 512))
+ return true;
if (!--retryCnt) break;
chipSelectHigh();
cardCommand(CMD12, 0); // Try sending a stop command, ignore the result.
errorCode_ = 0;
- } while (true);
+ }
#else
if (cardCommand(CMD17, blockNumber))
error(SD_CARD_ERROR_CMD17);
@@ -285,13 +282,13 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
chipSelectHigh();
return false;
}
-//------------------------------------------------------------------------------
-/** Read one data block in a multiple block read sequence
+
+/**
+ * Read one data block in a multiple block read sequence
*
* \param[in] dst Pointer to the location for the data to be read.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool Sd2Card::readData(uint8_t* dst) {
chipSelectLow();
@@ -299,50 +296,49 @@ bool Sd2Card::readData(uint8_t* dst) {
}
#if ENABLED(SD_CHECK_AND_RETRY)
-static const uint16_t crctab[] PROGMEM = {
- 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
- 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
- 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
- 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
- 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
- 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
- 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
- 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
- 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
- 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
- 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
- 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
- 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
- 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
- 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
- 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
- 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
- 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
- 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
- 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
- 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
- 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
- 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
- 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
- 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
- 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
- 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
- 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
- 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
- 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
- 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
- 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
-};
-static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
- uint16_t crc = 0;
- for (size_t i = 0; i < n; i++) {
- crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0xFF]) ^ (crc << 8);
+ static const uint16_t crctab[] PROGMEM = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+ 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+ 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+ 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+ 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+ 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+ 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+ 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+ 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+ 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+ 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+ 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+ 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+ 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+ 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+ 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+ 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+ 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+ 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+ 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+ 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+ 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+ 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+ };
+ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
+ uint16_t crc = 0;
+ for (size_t i = 0; i < n; i++) {
+ crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0xFF]) ^ (crc << 8);
+ }
+ return crc;
}
- return crc;
-}
-#endif
+#endif // SD_CHECK_AND_RETRY
-//------------------------------------------------------------------------------
bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
// wait for start block token
uint16_t t0 = millis();
@@ -384,61 +380,55 @@ bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
spiSend(0XFF);
return false;
}
-//------------------------------------------------------------------------------
+
/** read CID or CSR register */
bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
if (cardCommand(cmd, 0)) {
error(SD_CARD_ERROR_READ_REG);
- goto FAIL;
+ chipSelectHigh();
+ return false;
}
return readData(dst, 16);
- FAIL:
- chipSelectHigh();
- return false;
}
-//------------------------------------------------------------------------------
-/** Start a read multiple blocks sequence.
+
+/**
+ * Start a read multiple blocks sequence.
*
* \param[in] blockNumber Address of first block in sequence.
*
* \note This function is used with readData() and readStop() for optimized
* multiple block reads. SPI chipSelect must be low for the entire sequence.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool Sd2Card::readStart(uint32_t blockNumber) {
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (cardCommand(CMD18, blockNumber)) {
error(SD_CARD_ERROR_CMD18);
- goto FAIL;
+ chipSelectHigh();
+ return false;
}
chipSelectHigh();
return true;
- FAIL:
- chipSelectHigh();
- return false;
}
-//------------------------------------------------------------------------------
-/** End a read multiple blocks sequence.
+
+/**
+ * End a read multiple blocks sequence.
*
-* \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool Sd2Card::readStop() {
chipSelectLow();
if (cardCommand(CMD12, 0)) {
error(SD_CARD_ERROR_CMD12);
- goto FAIL;
+ chipSelectHigh();
+ return false;
}
chipSelectHigh();
return true;
- FAIL:
- chipSelectHigh();
- return false;
}
-//------------------------------------------------------------------------------
+
/**
* Set the SPI clock rate.
*
@@ -459,25 +449,22 @@ bool Sd2Card::setSckRate(uint8_t sckRateID) {
spiRate_ = sckRateID;
return true;
}
-//------------------------------------------------------------------------------
+
// wait for card to go not busy
bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
uint16_t t0 = millis();
- while (spiRec() != 0XFF) {
- if (((uint16_t)millis() - t0) >= timeoutMillis) goto FAIL;
- }
+ while (spiRec() != 0XFF)
+ if (((uint16_t)millis() - t0) >= timeoutMillis) return false;
+
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
/**
* Writes a 512 byte block to an SD card.
*
* \param[in] blockNumber Logical block to be written.
* \param[in] src Pointer to the location of the data to be written.
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
// use address if not SDHC card
@@ -504,25 +491,24 @@ bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
chipSelectHigh();
return false;
}
-//------------------------------------------------------------------------------
-/** Write one data block in a multiple block write sequence
+
+/**
+ * Write one data block in a multiple block write sequence
* \param[in] src Pointer to the location of the data to be written.
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool Sd2Card::writeData(const uint8_t* src) {
chipSelectLow();
// wait for previous write to finish
- if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
- if (!writeData(WRITE_MULTIPLE_TOKEN, src)) goto FAIL;
+ if (!waitNotBusy(SD_WRITE_TIMEOUT) || !writeData(WRITE_MULTIPLE_TOKEN, src)) {
+ error(SD_CARD_ERROR_WRITE_MULTIPLE);
+ chipSelectHigh();
+ return false;
+ }
chipSelectHigh();
return true;
- FAIL:
- error(SD_CARD_ERROR_WRITE_MULTIPLE);
- chipSelectHigh();
- return false;
}
-//------------------------------------------------------------------------------
+
// send one block of data for write block or write multiple blocks
bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
spiSendBlock(token, src);
@@ -533,15 +519,14 @@ bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
status_ = spiRec();
if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
error(SD_CARD_ERROR_WRITE);
- goto FAIL;
+ chipSelectHigh();
+ return false;
}
return true;
- FAIL:
- chipSelectHigh();
- return false;
}
-//------------------------------------------------------------------------------
-/** Start a write multiple blocks sequence.
+
+/**
+ * Start a write multiple blocks sequence.
*
* \param[in] blockNumber Address of first block in sequence.
* \param[in] eraseCount The number of blocks to be pre-erased.
@@ -549,8 +534,7 @@ bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
* \note This function is used with writeData() and writeStop()
* for optimized multiple block writes.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
// send pre-erase count
@@ -570,11 +554,11 @@ bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
chipSelectHigh();
return false;
}
-//------------------------------------------------------------------------------
-/** End a write multiple blocks sequence.
+
+/**
+ * End a write multiple blocks sequence.
*
-* \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool Sd2Card::writeStop() {
chipSelectLow();
@@ -589,4 +573,4 @@ bool Sd2Card::writeStop() {
return false;
}
-#endif
+#endif // SDSUPPORT
diff --git a/Marlin/src/sd/Sd2Card.h b/Marlin/src/sd/Sd2Card.h
index 5aaffe72f48421932610f567f3744960b3548d0a..0f596ce4c7baa9d6abfe649ea3e2b62d93ab23e4 100644
--- a/Marlin/src/sd/Sd2Card.h
+++ b/Marlin/src/sd/Sd2Card.h
@@ -20,100 +20,67 @@
*
*/
+/**
+ * \file
+ * \brief Sd2Card class for V2 SD/SDHC cards
+ */
+
/**
* Arduino Sd2Card Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
+#ifndef _SD2CARD_H_
+#define _SD2CARD_H_
-#ifndef SD2CARD_H
-#define SD2CARD_H
-/**
- * \file
- * \brief Sd2Card class for V2 SD/SDHC cards
- */
#include "SdFatConfig.h"
#include "SdInfo.h"
#include <stdint.h>
-//------------------------------------------------------------------------------
-/** init timeout ms */
-uint16_t const SD_INIT_TIMEOUT = 2000;
-/** erase timeout ms */
-uint16_t const SD_ERASE_TIMEOUT = 10000;
-/** read timeout ms */
-uint16_t const SD_READ_TIMEOUT = 300;
-/** write time out ms */
-uint16_t const SD_WRITE_TIMEOUT = 600;
-//------------------------------------------------------------------------------
+uint16_t const SD_INIT_TIMEOUT = 2000, // init timeout ms
+ SD_ERASE_TIMEOUT = 10000, // erase timeout ms
+ SD_READ_TIMEOUT = 300, // read timeout ms
+ SD_WRITE_TIMEOUT = 600; // write time out ms
+
// SD card errors
-/** timeout error for command CMD0 (initialize card in SPI mode) */
-uint8_t const SD_CARD_ERROR_CMD0 = 0X1;
-/** CMD8 was not accepted - not a valid SD card*/
-uint8_t const SD_CARD_ERROR_CMD8 = 0X2;
-/** card returned an error response for CMD12 (write stop) */
-uint8_t const SD_CARD_ERROR_CMD12 = 0X3;
-/** card returned an error response for CMD17 (read block) */
-uint8_t const SD_CARD_ERROR_CMD17 = 0X4;
-/** card returned an error response for CMD18 (read multiple block) */
-uint8_t const SD_CARD_ERROR_CMD18 = 0X5;
-/** card returned an error response for CMD24 (write block) */
-uint8_t const SD_CARD_ERROR_CMD24 = 0X6;
-/** WRITE_MULTIPLE_BLOCKS command failed */
-uint8_t const SD_CARD_ERROR_CMD25 = 0X7;
-/** card returned an error response for CMD58 (read OCR) */
-uint8_t const SD_CARD_ERROR_CMD58 = 0X8;
-/** SET_WR_BLK_ERASE_COUNT failed */
-uint8_t const SD_CARD_ERROR_ACMD23 = 0X9;
-/** ACMD41 initialization process timeout */
-uint8_t const SD_CARD_ERROR_ACMD41 = 0XA;
-/** card returned a bad CSR version field */
-uint8_t const SD_CARD_ERROR_BAD_CSD = 0XB;
-/** erase block group command failed */
-uint8_t const SD_CARD_ERROR_ERASE = 0XC;
-/** card not capable of single block erase */
-uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0XD;
-/** Erase sequence timed out */
-uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0XE;
-/** card returned an error token instead of read data */
-uint8_t const SD_CARD_ERROR_READ = 0XF;
-/** read CID or CSD failed */
-uint8_t const SD_CARD_ERROR_READ_REG = 0x10;
-/** timeout while waiting for start of read data */
-uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0x11;
-/** card did not accept STOP_TRAN_TOKEN */
-uint8_t const SD_CARD_ERROR_STOP_TRAN = 0x12;
-/** card returned an error token as a response to a write operation */
-uint8_t const SD_CARD_ERROR_WRITE = 0x13;
-/** attempt to write protected block zero */
-uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0x14; // REMOVE - not used
-/** card did not go ready for a multiple block write */
-uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0x15;
-/** card returned an error to a CMD13 status check after a write */
-uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0x16;
-/** timeout occurred during write programming */
-uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0x17;
-/** incorrect rate selected */
-uint8_t const SD_CARD_ERROR_SCK_RATE = 0x18;
-/** init() not called */
-uint8_t const SD_CARD_ERROR_INIT_NOT_CALLED = 0x19;
-/** crc check error */
-uint8_t const SD_CARD_ERROR_CRC = 0x20;
-//------------------------------------------------------------------------------
+uint8_t const SD_CARD_ERROR_CMD0 = 0X1, // timeout error for command CMD0 (initialize card in SPI mode)
+ SD_CARD_ERROR_CMD8 = 0X2, // CMD8 was not accepted - not a valid SD card
+ SD_CARD_ERROR_CMD12 = 0X3, // card returned an error response for CMD12 (write stop)
+ SD_CARD_ERROR_CMD17 = 0X4, // card returned an error response for CMD17 (read block)
+ SD_CARD_ERROR_CMD18 = 0X5, // card returned an error response for CMD18 (read multiple block)
+ SD_CARD_ERROR_CMD24 = 0X6, // card returned an error response for CMD24 (write block)
+ SD_CARD_ERROR_CMD25 = 0X7, // WRITE_MULTIPLE_BLOCKS command failed
+ SD_CARD_ERROR_CMD58 = 0X8, // card returned an error response for CMD58 (read OCR)
+ SD_CARD_ERROR_ACMD23 = 0X9, // SET_WR_BLK_ERASE_COUNT failed
+ SD_CARD_ERROR_ACMD41 = 0XA, // ACMD41 initialization process timeout
+ SD_CARD_ERROR_BAD_CSD = 0XB, // card returned a bad CSR version field
+ SD_CARD_ERROR_ERASE = 0XC, // erase block group command failed
+ SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0XD, // card not capable of single block erase
+ SD_CARD_ERROR_ERASE_TIMEOUT = 0XE, // Erase sequence timed out
+ SD_CARD_ERROR_READ = 0XF, // card returned an error token instead of read data
+ SD_CARD_ERROR_READ_REG = 0x10, // read CID or CSD failed
+ SD_CARD_ERROR_READ_TIMEOUT = 0x11, // timeout while waiting for start of read data
+ SD_CARD_ERROR_STOP_TRAN = 0x12, // card did not accept STOP_TRAN_TOKEN
+ SD_CARD_ERROR_WRITE = 0x13, // card returned an error token as a response to a write operation
+ SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0x14, // REMOVE - not used ... attempt to write protected block zero
+ SD_CARD_ERROR_WRITE_MULTIPLE = 0x15, // card did not go ready for a multiple block write
+ SD_CARD_ERROR_WRITE_PROGRAMMING = 0x16, // card returned an error to a CMD13 status check after a write
+ SD_CARD_ERROR_WRITE_TIMEOUT = 0x17, // timeout occurred during write programming
+ SD_CARD_ERROR_SCK_RATE = 0x18, // incorrect rate selected
+ SD_CARD_ERROR_INIT_NOT_CALLED = 0x19, // init() not called
+ SD_CARD_ERROR_CRC = 0x20; // crc check error
+
// card types
-/** Standard capacity V1 SD card */
-uint8_t const SD_CARD_TYPE_SD1 = 1;
-/** Standard capacity V2 SD card */
-uint8_t const SD_CARD_TYPE_SD2 = 2;
-/** High Capacity SD card */
-uint8_t const SD_CARD_TYPE_SDHC = 3;
+uint8_t const SD_CARD_TYPE_SD1 = 1, // Standard capacity V1 SD card
+ SD_CARD_TYPE_SD2 = 2, // Standard capacity V2 SD card
+ SD_CARD_TYPE_SDHC = 3; // High Capacity SD card
+
/**
* define SOFTWARE_SPI to use bit-bang SPI
*/
-//------------------------------------------------------------------------------
#if MEGA_SOFT_SPI
#define SOFTWARE_SPI
#elif USE_SOFTWARE_SPI
@@ -127,53 +94,47 @@ uint8_t const SD_CARD_TYPE_SDHC = 3;
#if 0
#if DISABLED(SOFTWARE_SPI)
// hardware pin defs
- /** The default chip select pin for the SD card is SS. */
- #define SD_CHIP_SELECT_PIN SS_PIN
+ #define SD_CHIP_SELECT_PIN SS_PIN // The default chip select pin for the SD card is SS.
// The following three pins must not be redefined for hardware SPI.
- /** SPI Master Out Slave In pin */
- #define SPI_MOSI_PIN MOSI_PIN
- /** SPI Master In Slave Out pin */
- #define SPI_MISO_PIN MISO_PIN
- /** SPI Clock pin */
- #define SPI_SCK_PIN SCK_PIN
-
+ #define SPI_MOSI_PIN MOSI_PIN // SPI Master Out Slave In pin
+ #define SPI_MISO_PIN MISO_PIN // SPI Master In Slave Out pin
+ #define SPI_SCK_PIN SCK_PIN // SPI Clock pin
#else // SOFTWARE_SPI
-
- /** SPI chip select pin */
- #define SD_CHIP_SELECT_PIN SOFT_SPI_CS_PIN
- /** SPI Master Out Slave In pin */
- #define SPI_MOSI_PIN SOFT_SPI_MOSI_PIN
- /** SPI Master In Slave Out pin */
- #define SPI_MISO_PIN SOFT_SPI_MISO_PIN
- /** SPI Clock pin */
- #define SPI_SCK_PIN SOFT_SPI_SCK_PIN
+ #define SD_CHIP_SELECT_PIN SOFT_SPI_CS_PIN // SPI chip select pin
+ #define SPI_MOSI_PIN SOFT_SPI_MOSI_PIN // SPI Master Out Slave In pin
+ #define SPI_MISO_PIN SOFT_SPI_MISO_PIN // SPI Master In Slave Out pin
+ #define SPI_SCK_PIN SOFT_SPI_SCK_PIN // SPI Clock pin
#endif // SOFTWARE_SPI
#endif
-//------------------------------------------------------------------------------
/**
* \class Sd2Card
* \brief Raw access to SD and SDHC flash memory cards.
*/
class Sd2Card {
- public:
- /** Construct an instance of Sd2Card. */
+ public:
+
Sd2Card() : errorCode_(SD_CARD_ERROR_INIT_NOT_CALLED), type_(0) {}
+
uint32_t cardSize();
bool erase(uint32_t firstBlock, uint32_t lastBlock);
bool eraseSingleBlockEnable();
+
/**
* Set SD error code.
* \param[in] code value for error code.
*/
void error(uint8_t code) {errorCode_ = code;}
+
/**
* \return error code for last error. See Sd2Card.h for a list of error codes.
*/
int errorCode() const {return errorCode_;}
+
/** \return error data for last error. */
int errorData() const {return status_;}
+
/**
* Initialize an SD flash memory card with default clock rate and chip
* select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
@@ -183,6 +144,7 @@ class Sd2Card {
bool init(uint8_t sckRateID = SPI_FULL_SPEED,
pin_t chipSelectPin = SD_CHIP_SELECT_PIN);
bool readBlock(uint32_t block, uint8_t* dst);
+
/**
* Read a card's CID register. The CID contains card identification
* information such as Manufacturer ID, Product name, Product serial
@@ -192,9 +154,8 @@ class Sd2Card {
*
* \return true for success or false for failure.
*/
- bool readCID(cid_t* cid) {
- return readRegister(CMD10, cid);
- }
+ bool readCID(cid_t* cid) { return readRegister(CMD10, cid); }
+
/**
* Read a card's CSD register. The CSD contains Card-Specific Data that
* provides information regarding access to the card's contents.
@@ -203,14 +164,14 @@ class Sd2Card {
*
* \return true for success or false for failure.
*/
- bool readCSD(csd_t* csd) {
- return readRegister(CMD9, csd);
- }
+ bool readCSD(csd_t* csd) { return readRegister(CMD9, csd); }
+
bool readData(uint8_t* dst);
bool readStart(uint32_t blockNumber);
bool readStop();
bool setSckRate(uint8_t sckRateID);
- /** Return the card type: SD V1, SD V2 or SDHC
+ /**
+ * Return the card type: SD V1, SD V2 or SDHC
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
*/
int type() const {return type_;}
@@ -218,13 +179,14 @@ class Sd2Card {
bool writeData(const uint8_t* src);
bool writeStart(uint32_t blockNumber, uint32_t eraseCount);
bool writeStop();
- private:
- //----------------------------------------------------------------------------
- pin_t chipSelectPin_;
- uint8_t errorCode_;
- uint8_t spiRate_;
- uint8_t status_;
- uint8_t type_;
+
+ private:
+ uint8_t chipSelectPin_,
+ errorCode_,
+ spiRate_,
+ status_,
+ type_;
+
// private functions
uint8_t cardAcmd(uint8_t cmd, uint32_t arg) {
cardCommand(CMD55, 0);
@@ -236,9 +198,9 @@ class Sd2Card {
bool readRegister(uint8_t cmd, void* buf);
void chipSelectHigh();
void chipSelectLow();
- void type(uint8_t value) {type_ = value;}
+ void type(uint8_t value) { type_ = value; }
bool waitNotBusy(uint16_t timeoutMillis);
bool writeData(uint8_t token, const uint8_t* src);
};
-#endif // SD2CARD_H
+#endif // _SD2CARD_H_
diff --git a/Marlin/src/sd/SdBaseFile.cpp b/Marlin/src/sd/SdBaseFile.cpp
index b6d98542e8e32759af812dd07d4e613a635b9d03..59e7d200acd4cef6e7e11da2bbd9560bfe1ac4bb 100644
--- a/Marlin/src/sd/SdBaseFile.cpp
+++ b/Marlin/src/sd/SdBaseFile.cpp
@@ -34,16 +34,14 @@
#include "SdBaseFile.h"
#include "../Marlin.h"
+SdBaseFile* SdBaseFile::cwd_ = 0; // Pointer to Current Working Directory
-//------------------------------------------------------------------------------
-// pointer to cwd directory
-SdBaseFile* SdBaseFile::cwd_ = 0;
// callback function for date/time
void (*SdBaseFile::dateTime_)(uint16_t* date, uint16_t* time) = 0;
-//------------------------------------------------------------------------------
+
// add a cluster to a file
bool SdBaseFile::addCluster() {
- if (!vol_->allocContiguous(1, &curCluster_)) goto FAIL;
+ if (!vol_->allocContiguous(1, &curCluster_)) return false;
// if first cluster of file link to directory entry
if (firstCluster_ == 0) {
@@ -51,20 +49,17 @@ bool SdBaseFile::addCluster() {
flags_ |= F_FILE_DIR_DIRTY;
}
return true;
-
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
// Add a cluster to a directory file and zero the cluster.
// return with first block of cluster in the cache
bool SdBaseFile::addDirCluster() {
uint32_t block;
// max folder size
- if (fileSize_ / sizeof(dir_t) >= 0xFFFF) goto FAIL;
+ if (fileSize_ / sizeof(dir_t) >= 0xFFFF) return false;
- if (!addCluster()) goto FAIL;
- if (!vol_->cacheFlush()) goto FAIL;
+ if (!addCluster()) return false;
+ if (!vol_->cacheFlush()) return false;
block = vol_->clusterStartBlock(curCluster_);
@@ -76,29 +71,25 @@ bool SdBaseFile::addDirCluster() {
// zero rest of cluster
for (uint8_t i = 1; i < vol_->blocksPerCluster_; i++) {
- if (!vol_->writeBlock(block + i, vol_->cacheBuffer_.data)) goto FAIL;
+ if (!vol_->writeBlock(block + i, vol_->cacheBuffer_.data)) return false;
}
// Increase directory file size by cluster size
fileSize_ += 512UL << vol_->clusterSizeShift_;
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
// cache a file's directory entry
// return pointer to cached entry or null for failure
dir_t* SdBaseFile::cacheDirEntry(uint8_t action) {
- if (!vol_->cacheRawBlock(dirBlock_, action)) goto FAIL;
+ if (!vol_->cacheRawBlock(dirBlock_, action)) return NULL;
return vol_->cache()->dir + dirIndex_;
- FAIL:
- return 0;
}
-//------------------------------------------------------------------------------
-/** Close a file and force cached data and directory information
+
+/**
+ * Close a file and force cached data and directory information
* to be written to the storage device.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include no file is open or an I/O error.
*/
bool SdBaseFile::close() {
@@ -106,41 +97,40 @@ bool SdBaseFile::close() {
type_ = FAT_FILE_TYPE_CLOSED;
return rtn;
}
-//------------------------------------------------------------------------------
-/** Check for contiguous file and return its raw block range.
+
+/**
+ * Check for contiguous file and return its raw block range.
*
* \param[out] bgnBlock the first block address for the file.
* \param[out] endBlock the last block address for the file.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include file is not contiguous, file has zero length
* or an I/O error occurred.
*/
bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
// error if no blocks
- if (firstCluster_ == 0) goto FAIL;
+ if (firstCluster_ == 0) return false;
for (uint32_t c = firstCluster_; ; c++) {
uint32_t next;
- if (!vol_->fatGet(c, &next)) goto FAIL;
+ if (!vol_->fatGet(c, &next)) return false;
// check for contiguous
if (next != (c + 1)) {
// error if not end of chain
- if (!vol_->isEOC(next)) goto FAIL;
+ if (!vol_->isEOC(next)) return false;
*bgnBlock = vol_->clusterStartBlock(firstCluster_);
*endBlock = vol_->clusterStartBlock(c)
+ vol_->blocksPerCluster_ - 1;
return true;
}
}
-
- FAIL:
return false;
}
-//------------------------------------------------------------------------------
-/** Create and open a new contiguous file of a specified size.
+
+/**
+ * Create and open a new contiguous file of a specified size.
*
* \note This function only supports short DOS 8.3 names.
* See open() for more information.
@@ -149,20 +139,18 @@ bool SdBaseFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) {
* \param[in] path A path with a valid DOS 8.3 file name.
* \param[in] size The desired file size.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include \a path contains
* an invalid DOS 8.3 file name, the FAT volume has not been initialized,
* a file is already open, the file already exists, the root
* directory is full or an I/O error.
*
*/
-bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
- const char* path, uint32_t size) {
+bool SdBaseFile::createContiguous(SdBaseFile* dirFile, const char* path, uint32_t size) {
uint32_t count;
// don't allow zero length file
- if (size == 0) goto FAIL;
- if (!open(dirFile, path, O_CREAT | O_EXCL | O_RDWR)) goto FAIL;
+ if (size == 0) return false;
+ if (!open(dirFile, path, O_CREAT | O_EXCL | O_RDWR)) return false;
// calculate number of clusters needed
count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1;
@@ -170,7 +158,7 @@ bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
// allocate clusters
if (!vol_->allocContiguous(count, &firstCluster_)) {
remove();
- goto FAIL;
+ return false;
}
fileSize_ = size;
@@ -178,34 +166,31 @@ bool SdBaseFile::createContiguous(SdBaseFile* dirFile,
flags_ |= F_FILE_DIR_DIRTY;
return sync();
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Return a file's directory entry.
+
+/**
+ * Return a file's directory entry.
*
* \param[out] dir Location for return of the file's directory entry.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool SdBaseFile::dirEntry(dir_t* dir) {
dir_t* p;
// make sure fields on SD are correct
- if (!sync()) goto FAIL;
+ if (!sync()) return false;
// read entry
p = cacheDirEntry(SdVolume::CACHE_FOR_READ);
- if (!p) goto FAIL;
+ if (!p) return false;
// copy to caller's struct
memcpy(dir, p, sizeof(dir_t));
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Format the name field of \a dir into the 13 byte array
+
+/**
+ * Format the name field of \a dir into the 13 byte array
* \a name in standard 8.3 short name format.
*
* \param[in] dir The directory structure containing the name.
@@ -220,8 +205,9 @@ void SdBaseFile::dirName(const dir_t& dir, char* name) {
}
name[j] = 0;
}
-//------------------------------------------------------------------------------
-/** Test for the existence of a file in a directory
+
+/**
+ * Test for the existence of a file in a directory
*
* \param[in] name Name of the file to be tested for.
*
@@ -236,7 +222,7 @@ bool SdBaseFile::exists(const char* name) {
SdBaseFile file;
return file.open(this, name, O_READ);
}
-//------------------------------------------------------------------------------
+
/**
* Get a string from a file.
*
@@ -279,15 +265,15 @@ int16_t SdBaseFile::fgets(char* str, int16_t num, char* delim) {
str[n] = '\0';
return n;
}
-//------------------------------------------------------------------------------
-/** Get a file's name
+
+/**
+ * Get a file's name
*
* \param[out] name An array of 13 characters for the file's name.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
-bool SdBaseFile::getFilename(char* name) {
+bool SdBaseFile::getFilename(char * const name) {
if (!isOpen()) return false;
if (isRoot()) {
@@ -303,14 +289,14 @@ bool SdBaseFile::getFilename(char* name) {
dirName(*p, name);
return true;
}
-//------------------------------------------------------------------------------
+
void SdBaseFile::getpos(filepos_t* pos) {
pos->position = curPosition_;
pos->cluster = curCluster_;
}
-//------------------------------------------------------------------------------
-/** List directory contents.
+/**
+ * List directory contents.
*
* \param[in] pr Print stream for list.
*
@@ -337,7 +323,7 @@ void SdBaseFile::ls(uint8_t flags, uint8_t indent) {
}
}
}
-//------------------------------------------------------------------------------
+
// saves 32 bytes on stack for ls recursion
// return 0 - EOF, 1 - normal file, or 2 - directory
int8_t SdBaseFile::lsPrintNext(uint8_t flags, uint8_t indent) {
@@ -387,41 +373,33 @@ int8_t SdBaseFile::lsPrintNext(uint8_t flags, uint8_t indent) {
MYSERIAL.println();
return DIR_IS_FILE(&dir) ? 1 : 2;
}
-//------------------------------------------------------------------------------
-// format directory name field from a 8.3 name string
+
+// Format directory name field from a 8.3 name string
bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) {
- uint8_t c;
- uint8_t n = 7; // max index for part before dot
- uint8_t i = 0;
- // blank fill name and extension
- while (i < 11) name[i++] = ' ';
- i = 0;
- while (*str != '\0' && *str != '/') {
- c = *str++;
- if (c == '.') {
- if (n == 10) goto FAIL; // only one dot allowed
- n = 10; // max index for full 8.3 name
- i = 8; // place for extension
+ uint8_t n = 7, // Max index until a dot is found
+ i = 11;
+ while (i) name[--i] = ' '; // Set whole FILENAME.EXT to spaces
+ while (*str && *str != '/') { // For each character, until nul or '/'
+ uint8_t c = *str++; // Get char and advance
+ if (c == '.') { // For a dot...
+ if (n == 10) return false; // Already moved the max index? fail!
+ n = 10; // Move the max index for full 8.3 name
+ i = 8; // Move up to the extension place
}
else {
- // illegal FAT characters
+ // Fail for illegal characters
PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
- uint8_t b;
- while ((b = pgm_read_byte(p++))) if (b == c) goto FAIL;
- // check size and only allow ASCII printable characters
- if (i > n || c < 0x21 || c == 0x7F) goto FAIL;
- // only upper case allowed in 8.3 names - convert lower to upper
- name[i++] = (c < 'a' || c > 'z') ? (c) : (c + ('A' - 'a'));
+ while (uint8_t b = pgm_read_byte(p++)) if (b == c) return false;
+ if (i > n || c < 0x21 || c == 0x7F) return false; // Check size, non-printable characters
+ name[i++] = (c < 'a' || c > 'z') ? (c) : (c + ('A' - 'a')); // Uppercase required for 8.3 name
}
}
- *ptr = str;
- // must have a file name, extension is optional
- return name[0] != ' ';
- FAIL:
- return false;
+ *ptr = str; // Set passed pointer to the end
+ return name[0] != ' '; // Return true if any name was set
}
-//------------------------------------------------------------------------------
-/** Make a new directory.
+
+/**
+ * Make a new directory.
*
* \param[in] parent An open SdFat instance for the directory that will contain
* the new directory.
@@ -430,8 +408,7 @@ bool SdBaseFile::make83Name(const char* str, uint8_t* name, const char** ptr) {
*
* \param[in] pFlag Create missing parent directories if true.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include this file is already open, \a parent is not a
* directory, \a path is invalid or already exists in \a parent.
*/
@@ -441,56 +418,53 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) {
SdBaseFile* sub = &dir1;
SdBaseFile* start = parent;
- if (!parent || isOpen()) goto FAIL;
+ if (!parent || isOpen()) return false;
if (*path == '/') {
while (*path == '/') path++;
if (!parent->isRoot()) {
- if (!dir2.openRoot(parent->vol_)) goto FAIL;
+ if (!dir2.openRoot(parent->vol_)) return false;
parent = &dir2;
}
}
while (1) {
- if (!make83Name(path, dname, &path)) goto FAIL;
+ if (!make83Name(path, dname, &path)) return false;
while (*path == '/') path++;
if (!*path) break;
if (!sub->open(parent, dname, O_READ)) {
- if (!pFlag || !sub->mkdir(parent, dname)) {
- goto FAIL;
- }
+ if (!pFlag || !sub->mkdir(parent, dname))
+ return false;
}
if (parent != start) parent->close();
parent = sub;
sub = parent != &dir1 ? &dir1 : &dir2;
}
return mkdir(parent, dname);
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
uint32_t block;
dir_t d;
dir_t* p;
- if (!parent->isDir()) goto FAIL;
+ if (!parent->isDir()) return false;
// create a normal file
- if (!open(parent, dname, O_CREAT | O_EXCL | O_RDWR)) goto FAIL;
+ if (!open(parent, dname, O_CREAT | O_EXCL | O_RDWR)) return false;
// convert file to directory
flags_ = O_READ;
type_ = FAT_FILE_TYPE_SUBDIR;
// allocate and zero first cluster
- if (!addDirCluster())goto FAIL;
+ if (!addDirCluster()) return false;
// force entry to SD
- if (!sync()) goto FAIL;
+ if (!sync()) return false;
// cache entry - should already be in cache due to sync() call
p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!p) goto FAIL;
+ if (!p) return false;
// change directory entry attribute
p->attributes = DIR_ATT_DIRECTORY;
@@ -502,7 +476,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
// cache block for '.' and '..'
block = vol_->clusterStartBlock(firstCluster_);
- if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto FAIL;
+ if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false;
// copy '.' to block
memcpy(&vol_->cache()->dir[0], &d, sizeof(d));
@@ -522,25 +496,24 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
// write first block
return vol_->cacheFlush();
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Open a file in the current working directory.
+
+/**
+ * Open a file in the current working directory.
*
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
*
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
* OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t).
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool SdBaseFile::open(const char* path, uint8_t oflag) {
return open(cwd_, path, oflag);
}
-//------------------------------------------------------------------------------
-/** Open a file or directory by name.
+
+/**
+ * Open a file or directory by name.
*
* \param[in] dirFile An open SdFat instance for the directory containing the
* file to be opened.
@@ -584,8 +557,7 @@ bool SdBaseFile::open(const char* path, uint8_t oflag) {
* \note Directory files must be opened read only. Write and truncation is
* not allowed for directory files.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include this file is already open, \a dirFile is not
* a directory, \a path is invalid, the file does not exist
* or can't be opened in the access mode specified by oflag.
@@ -593,40 +565,33 @@ bool SdBaseFile::open(const char* path, uint8_t oflag) {
bool SdBaseFile::open(SdBaseFile* dirFile, const char* path, uint8_t oflag) {
uint8_t dname[11];
SdBaseFile dir1, dir2;
- SdBaseFile* parent = dirFile;
- SdBaseFile* sub = &dir1;
-
- if (!dirFile) goto FAIL;
+ SdBaseFile *parent = dirFile, *sub = &dir1;
- // error if already open
- if (isOpen()) goto FAIL;
+ if (!dirFile || isOpen()) return false;
- if (*path == '/') {
- while (*path == '/') path++;
- if (!dirFile->isRoot()) {
- if (!dir2.openRoot(dirFile->vol_)) goto FAIL;
- parent = &dir2;
+ if (*path == '/') { // Path starts with '/'
+ if (!dirFile->isRoot()) { // Is the passed dirFile the root?
+ if (!dir2.openRoot(dirFile->vol_)) return false; // Get the root in dir2, if possible
+ parent = &dir2; // Change 'parent' to point at the root dir
}
+ while (*path == '/') path++; // Skip all leading slashes
}
- while (1) {
- if (!make83Name(path, dname, &path)) goto FAIL;
+
+ for (;;) {
+ if (!make83Name(path, dname, &path)) return false;
while (*path == '/') path++;
if (!*path) break;
- if (!sub->open(parent, dname, O_READ)) goto FAIL;
+ if (!sub->open(parent, dname, O_READ)) return false;
if (parent != dirFile) parent->close();
parent = sub;
sub = parent != &dir1 ? &dir1 : &dir2;
}
return open(parent, dname, oflag);
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
// open with filename in dname
-bool SdBaseFile::open(SdBaseFile* dirFile,
- const uint8_t dname[11], uint8_t oflag) {
- bool emptyFound = false;
- bool fileFound = false;
+bool SdBaseFile::open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag) {
+ bool emptyFound = false, fileFound = false;
uint8_t index;
dir_t* p;
@@ -638,7 +603,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
while (dirFile->curPosition_ < dirFile->fileSize_) {
index = 0XF & (dirFile->curPosition_ >> 5);
p = dirFile->readDirCache();
- if (!p) goto FAIL;
+ if (!p) return false;
if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) {
// remember first empty slot
@@ -657,21 +622,21 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
}
if (fileFound) {
// don't open existing file if O_EXCL
- if (oflag & O_EXCL) goto FAIL;
+ if (oflag & O_EXCL) return false;
}
else {
// don't create unless O_CREAT and O_WRITE
- if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) goto FAIL;
+ if (!(oflag & O_CREAT) || !(oflag & O_WRITE)) return false;
if (emptyFound) {
index = dirIndex_;
p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!p) goto FAIL;
+ if (!p) return false;
}
else {
- if (dirFile->type_ == FAT_FILE_TYPE_ROOT_FIXED) goto FAIL;
+ if (dirFile->type_ == FAT_FILE_TYPE_ROOT_FIXED) return false;
// add and zero cluster for dirFile - first cluster is in cache for write
- if (!dirFile->addDirCluster()) goto FAIL;
+ if (!dirFile->addDirCluster()) return false;
// use first entry in cluster
p = dirFile->vol_->cache()->dir;
@@ -696,15 +661,14 @@ bool SdBaseFile::open(SdBaseFile* dirFile,
p->lastWriteTime = p->creationTime;
// write entry to SD
- if (!dirFile->vol_->cacheFlush()) goto FAIL;
+ if (!dirFile->vol_->cacheFlush()) return false;
}
// open entry in cache
return openCachedEntry(index, oflag);
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Open a file by index.
+
+/**
+ * Open a file by index.
*
* \param[in] dirFile An open SdFat instance for the directory.
*
@@ -723,29 +687,27 @@ bool SdBaseFile::open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag) {
vol_ = dirFile->vol_;
// error if already open
- if (isOpen() || !dirFile) goto FAIL;
+ if (isOpen() || !dirFile) return false;
// don't open existing file if O_EXCL - user call error
- if (oflag & O_EXCL) goto FAIL;
+ if (oflag & O_EXCL) return false;
// seek to location of entry
- if (!dirFile->seekSet(32 * index)) goto FAIL;
+ if (!dirFile->seekSet(32 * index)) return false;
// read entry into cache
p = dirFile->readDirCache();
- if (!p) goto FAIL;
+ if (!p) return false;
// error if empty slot or '.' or '..'
if (p->name[0] == DIR_NAME_FREE ||
p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
- goto FAIL;
+ return false;
}
// open cached entry
return openCachedEntry(index & 0XF, oflag);
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
// open a cached directory entry. Assumes vol_ is initialized
bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
// location of entry in cache
@@ -772,9 +734,9 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
if (!vol_->chainSize(firstCluster_, &fileSize_)) goto FAIL;
type_ = FAT_FILE_TYPE_SUBDIR;
}
- else {
+ else
goto FAIL;
- }
+
// save open flags for read/write
flags_ = oflag & F_OFLAG;
@@ -783,12 +745,14 @@ bool SdBaseFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) {
curPosition_ = 0;
if ((oflag & O_TRUNC) && !truncate(0)) return false;
return oflag & O_AT_END ? seekEnd(0) : true;
+
FAIL:
type_ = FAT_FILE_TYPE_CLOSED;
return false;
}
-//------------------------------------------------------------------------------
-/** Open the next file or subdirectory in a directory.
+
+/**
+ * Open the next file or subdirectory in a directory.
*
* \param[in] dirFile An open SdFat instance for the directory containing the
* file to be opened.
@@ -803,10 +767,10 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
dir_t* p;
uint8_t index;
- if (!dirFile) goto FAIL;
+ if (!dirFile) return false;
// error if already open
- if (isOpen()) goto FAIL;
+ if (isOpen()) return false;
vol_ = dirFile->vol_;
@@ -815,10 +779,10 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
// read entry into cache
p = dirFile->readDirCache();
- if (!p) goto FAIL;
+ if (!p) return false;
// done if last entry
- if (p->name[0] == DIR_NAME_FREE) goto FAIL;
+ if (p->name[0] == DIR_NAME_FREE) return false;
// skip empty slot or '.' or '..'
if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') {
@@ -829,16 +793,16 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
return openCachedEntry(index, oflag);
}
}
- FAIL:
return false;
}
-//------------------------------------------------------------------------------
-/** Open a directory's parent directory.
+
+#if 0
+/**
+ * Open a directory's parent directory.
*
* \param[in] dir Parent of this directory will be opened. Must not be root.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool SdBaseFile::openParent(SdBaseFile* dir) {
dir_t entry;
@@ -848,14 +812,14 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
uint32_t cluster;
uint32_t lbn;
// error if already open or dir is root or dir is not a directory
- if (isOpen() || !dir || dir->isRoot() || !dir->isDir()) goto FAIL;
+ if (isOpen() || !dir || dir->isRoot() || !dir->isDir()) return false;
vol_ = dir->vol_;
// position to '..'
- if (!dir->seekSet(32)) goto FAIL;
+ if (!dir->seekSet(32)) return false;
// read '..' entry
- if (dir->read(&entry, sizeof(entry)) != 32) goto FAIL;
+ if (dir->read(&entry, sizeof(entry)) != 32) return false;
// verify it is '..'
- if (entry.name[0] != '.' || entry.name[1] != '.') goto FAIL;
+ if (entry.name[0] != '.' || entry.name[1] != '.') return false;
// start cluster for '..'
cluster = entry.firstClusterLow;
cluster |= (uint32_t)entry.firstClusterHigh << 16;
@@ -863,43 +827,42 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
// start block for '..'
lbn = vol_->clusterStartBlock(cluster);
// first block of parent dir
- if (!vol_->cacheRawBlock(lbn, SdVolume::CACHE_FOR_READ)) {
- goto FAIL;
- }
+ if (!vol_->cacheRawBlock(lbn, SdVolume::CACHE_FOR_READ)) return false;
+
p = &vol_->cacheBuffer_.dir[1];
// verify name for '../..'
- if (p->name[0] != '.' || p->name[1] != '.') goto FAIL;
+ if (p->name[0] != '.' || p->name[1] != '.') return false;
// '..' is pointer to first cluster of parent. open '../..' to find parent
if (p->firstClusterHigh == 0 && p->firstClusterLow == 0) {
- if (!file.openRoot(dir->volume())) goto FAIL;
- }
- else if (!file.openCachedEntry(1, O_READ)) {
- goto FAIL;
+ if (!file.openRoot(dir->volume())) return false;
}
+ else if (!file.openCachedEntry(1, O_READ))
+ return false;
+
// search for parent in '../..'
do {
- if (file.readDir(&entry, NULL) != 32) goto FAIL;
+ if (file.readDir(&entry, NULL) != 32) return false;
c = entry.firstClusterLow;
c |= (uint32_t)entry.firstClusterHigh << 16;
} while (c != cluster);
+
// open parent
return open(&file, file.curPosition() / 32 - 1, O_READ);
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Open a volume's root directory.
+#endif
+
+/**
+ * Open a volume's root directory.
*
* \param[in] vol The FAT volume containing the root directory to be opened.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include the file is already open, the FAT volume has
* not been initialized or it a FAT12 volume.
*/
bool SdBaseFile::openRoot(SdVolume* vol) {
// error if file is already open
- if (isOpen()) goto FAIL;
+ if (isOpen()) return false;
if (vol->fatType() == 16 || (FAT12_SUPPORT && vol->fatType() == 12)) {
type_ = FAT_FILE_TYPE_ROOT_FIXED;
@@ -909,29 +872,25 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
else if (vol->fatType() == 32) {
type_ = FAT_FILE_TYPE_ROOT32;
firstCluster_ = vol->rootDirStart();
- if (!vol->chainSize(firstCluster_, &fileSize_)) goto FAIL;
+ if (!vol->chainSize(firstCluster_, &fileSize_)) return false;
}
- else {
- // volume is not initialized, invalid, or FAT12 without support
+ else // volume is not initialized, invalid, or FAT12 without support
return false;
- }
+
vol_ = vol;
// read only
flags_ = O_READ;
// set to start of file
- curCluster_ = 0;
- curPosition_ = 0;
+ curCluster_ = curPosition_ = 0;
// root has no directory entry
- dirBlock_ = 0;
- dirIndex_ = 0;
+ dirBlock_ = dirIndex_ = 0;
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Return the next available byte without consuming it.
+
+/**
+ * Return the next available byte without consuming it.
*
* \return The byte if no error and not at eof else -1;
*/
@@ -943,50 +902,24 @@ int SdBaseFile::peek() {
return c;
}
-//------------------------------------------------------------------------------
-/** %Print the name field of a directory entry in 8.3 format.
- * \param[in] pr Print stream for output.
- * \param[in] dir The directory structure containing the name.
- * \param[in] width Blank fill name if length is less than \a width.
- * \param[in] printSlash Print '/' after directory names if true.
- */
-void SdBaseFile::printDirName(const dir_t& dir,
- uint8_t width, bool printSlash) {
- uint8_t w = 0;
- for (uint8_t i = 0; i < 11; i++) {
- if (dir.name[i] == ' ')continue;
- if (i == 8) {
- MYSERIAL.write('.');
- w++;
- }
- MYSERIAL.write(dir.name[i]);
- w++;
- }
- if (DIR_IS_SUBDIR(&dir) && printSlash) {
- MYSERIAL.write('/');
- w++;
- }
- while (w < width) {
- MYSERIAL.write(' ');
- w++;
- }
-}
-//------------------------------------------------------------------------------
+
// print uint8_t with width 2
static void print2u(uint8_t v) {
if (v < 10) MYSERIAL.write('0');
MYSERIAL.print(v, DEC);
}
-//------------------------------------------------------------------------------
-/** %Print a directory date field to Serial.
+
+/**
+ * %Print a directory date field to Serial.
*
* Format is yyyy-mm-dd.
*
* \param[in] fatDate The date field from a directory entry.
*/
-//------------------------------------------------------------------------------
-/** %Print a directory date field.
+
+/**
+ * %Print a directory date field.
*
* Format is yyyy-mm-dd.
*
@@ -1001,8 +934,9 @@ void SdBaseFile::printFatDate(uint16_t fatDate) {
print2u(FAT_DAY(fatDate));
}
-//------------------------------------------------------------------------------
-/** %Print a directory time field.
+
+/**
+ * %Print a directory time field.
*
* Format is hh:mm:ss.
*
@@ -1016,11 +950,11 @@ void SdBaseFile::printFatTime(uint16_t fatTime) {
MYSERIAL.write(':');
print2u(FAT_SECOND(fatTime));
}
-//------------------------------------------------------------------------------
-/** Print a file's name to Serial
+
+/**
+ * Print a file's name to Serial
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool SdBaseFile::printName() {
char name[FILENAME_LENGTH];
@@ -1028,8 +962,9 @@ bool SdBaseFile::printName() {
MYSERIAL.print(name);
return true;
}
-//------------------------------------------------------------------------------
-/** Read the next byte from a file.
+
+/**
+ * Read the next byte from a file.
*
* \return For success read returns the next byte in the file as an int.
* If an error occurs or end of file is reached -1 is returned.
@@ -1038,8 +973,9 @@ int16_t SdBaseFile::read() {
uint8_t b;
return read(&b, 1) == 1 ? b : -1;
}
-//------------------------------------------------------------------------------
-/** Read data from a file starting at the current position.
+
+/**
+ * Read data from a file starting at the current position.
*
* \param[out] buf Pointer to the location that will receive the data.
*
@@ -1054,12 +990,11 @@ int16_t SdBaseFile::read() {
*/
int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
- uint16_t offset;
- uint16_t toRead;
+ uint16_t offset, toRead;
uint32_t block; // raw device block number
// error if not open or write only
- if (!isOpen() || !(flags_ & O_READ)) goto FAIL;
+ if (!isOpen() || !(flags_ & O_READ)) return -1;
// max bytes left in file
NOMORE(nbyte, fileSize_ - curPosition_);
@@ -1075,14 +1010,10 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
if (offset == 0 && blockOfCluster == 0) {
// start of new cluster
- if (curPosition_ == 0) {
- // use first cluster in file
- curCluster_ = firstCluster_;
- }
- else {
- // get next cluster from FAT
- if (!vol_->fatGet(curCluster_, &curCluster_)) goto FAIL;
- }
+ if (curPosition_ == 0)
+ curCluster_ = firstCluster_; // use first cluster in file
+ else if (!vol_->fatGet(curCluster_, &curCluster_)) // get next cluster from FAT
+ return -1;
}
block = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
}
@@ -1093,11 +1024,11 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
// no buffering needed if n == 512
if (n == 512 && block != vol_->cacheBlockNumber()) {
- if (!vol_->readBlock(block, dst)) goto FAIL;
+ if (!vol_->readBlock(block, dst)) return -1;
}
else {
// read block to cache and copy data to caller
- if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) goto FAIL;
+ if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return -1;
uint8_t* src = vol_->cache()->data + offset;
memcpy(dst, src, n);
}
@@ -1106,8 +1037,6 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) {
toRead -= n;
}
return nbyte;
- FAIL:
- return -1;
}
/**
@@ -1159,30 +1088,29 @@ int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
}
}
-//------------------------------------------------------------------------------
+
// Read next directory entry into the cache
// Assumes file is correctly positioned
dir_t* SdBaseFile::readDirCache() {
uint8_t i;
// error if not directory
- if (!isDir()) goto FAIL;
+ if (!isDir()) return 0;
// index of entry in cache
i = (curPosition_ >> 5) & 0XF;
// use read to locate and cache block
- if (read() < 0) goto FAIL;
+ if (read() < 0) return 0;
// advance to next entry
curPosition_ += 31;
// return pointer to entry
return vol_->cache()->dir + i;
- FAIL:
- return 0;
}
-//------------------------------------------------------------------------------
-/** Remove a file.
+
+/**
+ * Remove a file.
*
* The directory entry and all data for the file are deleted.
*
@@ -1190,19 +1118,18 @@ dir_t* SdBaseFile::readDirCache() {
* file that has a long name. For example if a file has the long name
* "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include the file read-only, is a directory,
* or an I/O error occurred.
*/
bool SdBaseFile::remove() {
dir_t* d;
// free any clusters - will fail if read-only or directory
- if (!truncate(0)) goto FAIL;
+ if (!truncate(0)) return false;
// cache directory entry
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!d) goto FAIL;
+ if (!d) return false;
// mark entry deleted
d->name[0] = DIR_NAME_DELETED;
@@ -1213,11 +1140,10 @@ bool SdBaseFile::remove() {
// write entry to SD
return vol_->cacheFlush();
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Remove a file.
+
+/**
+ * Remove a file.
*
* The directory entry and all data for the file are deleted.
*
@@ -1228,28 +1154,23 @@ bool SdBaseFile::remove() {
* file that has a long name. For example if a file has the long name
* "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT".
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include the file is a directory, is read only,
* \a dirFile is not a directory, \a path is not found
* or an I/O error occurred.
*/
bool SdBaseFile::remove(SdBaseFile* dirFile, const char* path) {
SdBaseFile file;
- if (!file.open(dirFile, path, O_WRITE)) goto FAIL;
- return file.remove();
- FAIL:
- // can't set iostate - static function
- return false;
+ return file.open(dirFile, path, O_WRITE) ? file.remove() : false;
}
-//------------------------------------------------------------------------------
-/** Rename a file or subdirectory.
+
+/**
+ * Rename a file or subdirectory.
*
* \param[in] dirFile Directory for the new path.
* \param[in] newPath New path name for the file/directory.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include \a dirFile is not open or is not a directory
* file, newPath is invalid or already exists, or an I/O error occurs.
*/
@@ -1260,15 +1181,15 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
dir_t* d;
// must be an open file or subdirectory
- if (!(isFile() || isSubDir())) goto FAIL;
+ if (!(isFile() || isSubDir())) return false;
// can't move file
- if (vol_ != dirFile->vol_) goto FAIL;
+ if (vol_ != dirFile->vol_) return false;
// sync() and cache directory entry
sync();
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!d) goto FAIL;
+ if (!d) return false;
// save directory entry
memcpy(&entry, d, sizeof(entry));
@@ -1299,7 +1220,7 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
// cache new directory entry
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!d) goto FAIL;
+ if (!d) return false;
// copy all but name field to new directory entry
memcpy(&d->attributes, &entry.attributes, sizeof(entry) - sizeof(d->name));
@@ -1308,31 +1229,30 @@ bool SdBaseFile::rename(SdBaseFile* dirFile, const char* newPath) {
if (dirCluster) {
// get new dot dot
uint32_t block = vol_->clusterStartBlock(dirCluster);
- if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) goto FAIL;
+ if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) return false;
memcpy(&entry, &vol_->cache()->dir[1], sizeof(entry));
// free unused cluster
- if (!vol_->freeChain(dirCluster)) goto FAIL;
+ if (!vol_->freeChain(dirCluster)) return false;
// store new dot dot
block = vol_->clusterStartBlock(firstCluster_);
- if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) goto FAIL;
+ if (!vol_->cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) return false;
memcpy(&vol_->cache()->dir[1], &entry, sizeof(entry));
}
return vol_->cacheFlush();
restore:
- d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!d) goto FAIL;
- // restore entry
- d->name[0] = entry.name[0];
- vol_->cacheFlush();
-
- FAIL:
+ if ((d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE))) {
+ // restore entry
+ d->name[0] = entry.name[0];
+ vol_->cacheFlush();
+ }
return false;
}
-//------------------------------------------------------------------------------
-/** Remove a directory file.
+
+/**
+ * Remove a directory file.
*
* The directory file will be removed only if it is empty and is not the
* root directory. rmdir() follows DOS and Windows and ignores the
@@ -1342,37 +1262,35 @@ restore:
* directory that has a long name. For example if a directory has the
* long name "New folder" you should not delete the 8.3 name "NEWFOL~1".
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include the file is not a directory, is the root
* directory, is not empty, or an I/O error occurred.
*/
bool SdBaseFile::rmdir() {
// must be open subdirectory
- if (!isSubDir()) goto FAIL;
+ if (!isSubDir()) return false;
rewind();
// make sure directory is empty
while (curPosition_ < fileSize_) {
dir_t* p = readDirCache();
- if (!p) goto FAIL;
+ if (!p) return false;
// done if past last used entry
if (p->name[0] == DIR_NAME_FREE) break;
// skip empty slot, '.' or '..'
if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') continue;
// error not empty
- if (DIR_IS_FILE_OR_SUBDIR(p)) goto FAIL;
+ if (DIR_IS_FILE_OR_SUBDIR(p)) return false;
}
// convert empty directory to normal file for remove
type_ = FAT_FILE_TYPE_NORMAL;
flags_ |= O_WRITE;
return remove();
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Recursively delete a directory and all contained files.
+
+/**
+ * Recursively delete a directory and all contained files.
*
* This is like the Unix/Linux 'rm -rf *' if called with the root directory
* hence the name.
@@ -1384,8 +1302,7 @@ bool SdBaseFile::rmdir() {
* \note This function should not be used to delete the 8.3 version of
* a directory that has a long name. See remove() and rmdir().
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool SdBaseFile::rmRfStar() {
uint32_t index;
@@ -1396,7 +1313,7 @@ bool SdBaseFile::rmRfStar() {
index = curPosition_ / 32;
dir_t* p = readDirCache();
- if (!p) goto FAIL;
+ if (!p) return false;
// done if past last entry
if (p->name[0] == DIR_NAME_FREE) break;
@@ -1407,31 +1324,30 @@ bool SdBaseFile::rmRfStar() {
// skip if part of long file name or volume label in root
if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
- if (!f.open(this, index, O_READ)) goto FAIL;
+ if (!f.open(this, index, O_READ)) return false;
if (f.isSubDir()) {
// recursively delete
- if (!f.rmRfStar()) goto FAIL;
+ if (!f.rmRfStar()) return false;
}
else {
// ignore read-only
f.flags_ |= O_WRITE;
- if (!f.remove()) goto FAIL;
+ if (!f.remove()) return false;
}
// position to next entry if required
if (curPosition_ != (32 * (index + 1))) {
- if (!seekSet(32 * (index + 1))) goto FAIL;
+ if (!seekSet(32 * (index + 1))) return false;
}
}
// don't try to delete root
if (!isRoot()) {
- if (!rmdir()) goto FAIL;
+ if (!rmdir()) return false;
}
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Create a file object and open it in the current working directory.
+
+/**
+ * Create a file object and open it in the current working directory.
*
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
*
@@ -1443,64 +1359,54 @@ SdBaseFile::SdBaseFile(const char* path, uint8_t oflag) {
writeError = false;
open(path, oflag);
}
-//------------------------------------------------------------------------------
-/** Sets a file's position.
+
+/**
+ * Sets a file's position.
*
* \param[in] pos The new 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.
+ * \return true for success, false for failure.
*/
-bool SdBaseFile::seekSet(uint32_t pos) {
- uint32_t nCur;
- uint32_t nNew;
+bool SdBaseFile::seekSet(const uint32_t pos) {
+ uint32_t nCur, nNew;
// error if file not open or seek past end of file
- if (!isOpen() || pos > fileSize_) goto FAIL;
+ if (!isOpen() || pos > fileSize_) return false;
if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
curPosition_ = pos;
- goto done;
+ return true;
}
if (pos == 0) {
- // set position to start of file
- curCluster_ = 0;
- curPosition_ = 0;
- goto done;
+ curCluster_ = curPosition_ = 0; // set position to start of file
+ return true;
}
+
// calculate cluster index for cur and new position
nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9);
nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9);
- if (nNew < nCur || curPosition_ == 0) {
- // must follow chain from first cluster
- curCluster_ = firstCluster_;
- }
- else {
- // advance from curPosition
- nNew -= nCur;
- }
- while (nNew--) {
- if (!vol_->fatGet(curCluster_, &curCluster_)) goto FAIL;
- }
- curPosition_ = pos;
+ if (nNew < nCur || curPosition_ == 0)
+ curCluster_ = firstCluster_; // must follow chain from first cluster
+ else
+ nNew -= nCur; // advance from curPosition
-done:
- return true;
+ while (nNew--)
+ if (!vol_->fatGet(curCluster_, &curCluster_)) return false;
- FAIL:
- return false;
+ curPosition_ = pos;
+ return true;
}
-//------------------------------------------------------------------------------
+
void SdBaseFile::setpos(filepos_t* pos) {
curPosition_ = pos->position;
curCluster_ = pos->cluster;
}
-//------------------------------------------------------------------------------
-/** The sync() call causes all modified data and directory fields
+
+/**
+ * The sync() call causes all modified data and directory fields
* to be written to the storage device.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include a call to sync() before a file has been
* opened or an I/O error.
*/
@@ -1534,8 +1440,9 @@ bool SdBaseFile::sync() {
writeError = true;
return false;
}
-//------------------------------------------------------------------------------
-/** Copy a file's timestamps
+
+/**
+ * Copy a file's timestamps
*
* \param[in] file File to copy timestamps from.
*
@@ -1543,21 +1450,20 @@ bool SdBaseFile::sync() {
* Modify and access timestamps may be overwritten if a date time callback
* function has been set by dateTimeCallback().
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool SdBaseFile::timestamp(SdBaseFile* file) {
dir_t* d;
dir_t dir;
// get timestamps
- if (!file->dirEntry(&dir)) goto FAIL;
+ if (!file->dirEntry(&dir)) return false;
// update directory fields
- if (!sync()) goto FAIL;
+ if (!sync()) return false;
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!d) goto FAIL;
+ if (!d) return false;
// copy timestamps
d->lastAccessDate = dir.lastAccessDate;
@@ -1569,12 +1475,10 @@ bool SdBaseFile::timestamp(SdBaseFile* file) {
// write back entry
return vol_->cacheFlush();
-
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Set a file's timestamps in its directory entry.
+
+/**
+ * Set a file's timestamps in its directory entry.
*
* \param[in] flags Values for \a flags are constructed by a bitwise-inclusive
* OR of flags from the following list
@@ -1604,13 +1508,11 @@ bool SdBaseFile::timestamp(SdBaseFile* file) {
* Modify and access timestamps may be overwritten if a date time callback
* function has been set by dateTimeCallback().
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
*/
bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
- uint16_t dirDate;
- uint16_t dirTime;
+ uint16_t dirDate, dirTime;
dir_t* d;
if (!isOpen()
@@ -1623,13 +1525,13 @@ bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
|| hour > 23
|| minute > 59
|| second > 59) {
- goto FAIL;
+ return false;
}
// update directory entry
- if (!sync()) goto FAIL;
+ if (!sync()) return false;
d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE);
- if (!d) goto FAIL;
+ if (!d) return false;
dirDate = FAT_DATE(year, month, day);
dirTime = FAT_TIME(hour, minute, second);
@@ -1647,28 +1549,26 @@ bool SdBaseFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
d->lastWriteTime = dirTime;
}
return vol_->cacheFlush();
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Truncate a file to a specified length. The current file position
+
+/**
+ * Truncate a file to a specified length. The current file position
* will be maintained if it is less than or equal to \a length otherwise
* it will be set to end of file.
*
* \param[in] length The desired length for the file.
*
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
+ * \return true for success, false for failure.
* Reasons for failure include file is read only, file is a directory,
* \a length is greater than the current file size or an I/O error occurs.
*/
bool SdBaseFile::truncate(uint32_t length) {
uint32_t newPos;
// error if not a normal file or read-only
- if (!isFile() || !(flags_ & O_WRITE)) goto FAIL;
+ if (!isFile() || !(flags_ & O_WRITE)) return false;
// error if length is greater than current size
- if (length > fileSize_) goto FAIL;
+ if (length > fileSize_) return false;
// fileSize and length are zero - nothing to do
if (fileSize_ == 0) return true;
@@ -1677,23 +1577,23 @@ bool SdBaseFile::truncate(uint32_t length) {
newPos = curPosition_ > length ? length : curPosition_;
// position to last cluster in truncated file
- if (!seekSet(length)) goto FAIL;
+ if (!seekSet(length)) return false;
if (length == 0) {
// free all clusters
- if (!vol_->freeChain(firstCluster_)) goto FAIL;
+ if (!vol_->freeChain(firstCluster_)) return false;
firstCluster_ = 0;
}
else {
uint32_t toFree;
- if (!vol_->fatGet(curCluster_, &toFree)) goto FAIL;
+ if (!vol_->fatGet(curCluster_, &toFree)) return false;
if (!vol_->isEOC(toFree)) {
// free extra clusters
- if (!vol_->freeChain(toFree)) goto FAIL;
+ if (!vol_->freeChain(toFree)) return false;
// current cluster is end of chain
- if (!vol_->fatPutEOC(curCluster_)) goto FAIL;
+ if (!vol_->fatPutEOC(curCluster_)) return false;
}
}
fileSize_ = length;
@@ -1701,16 +1601,14 @@ bool SdBaseFile::truncate(uint32_t length) {
// need to update directory entry
flags_ |= F_FILE_DIR_DIRTY;
- if (!sync()) goto FAIL;
+ if (!sync()) return false;
// set file to correct position
return seekSet(newPos);
-
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
-/** Write data to an open file.
+
+/**
+ * Write data to an open file.
*
* \note Data is moved to the cache but may not be written to the
* storage device until sync() is called.
@@ -1820,10 +1718,9 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
writeError = true;
return -1;
}
-//------------------------------------------------------------------------------
-// suppress cpplint warnings with NOLINT comment
-#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
- void (*SdBaseFile::oldDateTime_)(uint16_t &date, uint16_t &time) = 0; // NOLINT
-#endif // ALLOW_DEPRECATED_FUNCTIONS
+
+#if ALLOW_DEPRECATED_FUNCTIONS
+ void (*SdBaseFile::oldDateTime_)(uint16_t &date, uint16_t &time) = 0;
+#endif
#endif // SDSUPPORT
diff --git a/Marlin/src/sd/SdBaseFile.h b/Marlin/src/sd/SdBaseFile.h
index f514624f40dcf4fcb9104a3fd5ae7d83cb6e04c2..4a0397ccb5faf37e0804ee8b4fab6d7deeb2ca17 100644
--- a/Marlin/src/sd/SdBaseFile.h
+++ b/Marlin/src/sd/SdBaseFile.h
@@ -20,209 +20,199 @@
*
*/
+/**
+ * \file
+ * \brief SdBaseFile class
+ */
+
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
+#ifndef _SDBASEFILE_H_
+#define _SDBASEFILE_H_
-#ifndef SDBASEFILE_H
-#define SDBASEFILE_H
-/**
- * \file
- * \brief SdBaseFile class
- */
#include "SdFatConfig.h"
#include "SdVolume.h"
#include <stdint.h>
-//------------------------------------------------------------------------------
/**
* \struct filepos_t
* \brief internal type for istream
* do not use in user apps
*/
struct filepos_t {
- /** stream position */
- uint32_t position;
- /** cluster for position */
- uint32_t cluster;
+ uint32_t position; // stream byte position
+ uint32_t cluster; // cluster of position
filepos_t() : position(0), cluster(0) {}
};
// use the gnu style oflag in open()
-/** open() oflag for reading */
-uint8_t const O_READ = 0x01;
-/** open() oflag - same as O_IN */
-uint8_t const O_RDONLY = O_READ;
-/** open() oflag for write */
-uint8_t const O_WRITE = 0x02;
-/** open() oflag - same as O_WRITE */
-uint8_t const O_WRONLY = O_WRITE;
-/** open() oflag for reading and writing */
-uint8_t const O_RDWR = (O_READ | O_WRITE);
-/** open() oflag mask for access modes */
-uint8_t const O_ACCMODE = (O_READ | O_WRITE);
-/** The file offset shall be set to the end of the file prior to each write. */
-uint8_t const O_APPEND = 0x04;
-/** synchronous writes - call sync() after each write */
-uint8_t const O_SYNC = 0x08;
-/** truncate the file to zero length */
-uint8_t const O_TRUNC = 0x10;
-/** set the initial position at the end of the file */
-uint8_t const O_AT_END = 0x20;
-/** create the file if nonexistent */
-uint8_t const O_CREAT = 0x40;
-/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
-uint8_t const O_EXCL = 0x80;
+uint8_t const O_READ = 0x01, // open() oflag for reading
+ O_RDONLY = O_READ, // open() oflag - same as O_IN
+ O_WRITE = 0x02, // open() oflag for write
+ O_WRONLY = O_WRITE, // open() oflag - same as O_WRITE
+ O_RDWR = (O_READ | O_WRITE), // open() oflag for reading and writing
+ O_ACCMODE = (O_READ | O_WRITE), // open() oflag mask for access modes
+ O_APPEND = 0x04, // The file offset shall be set to the end of the file prior to each write.
+ O_SYNC = 0x08, // Synchronous writes - call sync() after each write
+ O_TRUNC = 0x10, // Truncate the file to zero length
+ O_AT_END = 0x20, // Set the initial position at the end of the file
+ O_CREAT = 0x40, // Create the file if nonexistent
+ O_EXCL = 0x80; // If O_CREAT and O_EXCL are set, open() shall fail if the file exists
// SdBaseFile class static and const definitions
+
// flags for ls()
-/** ls() flag to print modify date */
-uint8_t const LS_DATE = 1;
-/** ls() flag to print file size */
-uint8_t const LS_SIZE = 2;
-/** ls() flag for recursive list of subdirectories */
-uint8_t const LS_R = 4;
+uint8_t const LS_DATE = 1, // ls() flag to print modify date
+ LS_SIZE = 2, // ls() flag to print file size
+ LS_R = 4; // ls() flag for recursive list of subdirectories
// flags for timestamp
-/** set the file's last access date */
-uint8_t const T_ACCESS = 1;
-/** set the file's creation date and time */
-uint8_t const T_CREATE = 2;
-/** Set the file's write date and time */
-uint8_t const T_WRITE = 4;
+uint8_t const T_ACCESS = 1, // Set the file's last access date
+ T_CREATE = 2, // Set the file's creation date and time
+ T_WRITE = 4; // Set the file's write date and time
+
// values for type_
-/** This file has not been opened. */
-uint8_t const FAT_FILE_TYPE_CLOSED = 0;
-/** A normal file */
-uint8_t const FAT_FILE_TYPE_NORMAL = 1;
-/** A FAT12 or FAT16 root directory */
-uint8_t const FAT_FILE_TYPE_ROOT_FIXED = 2;
-/** A FAT32 root directory */
-uint8_t const FAT_FILE_TYPE_ROOT32 = 3;
-/** A subdirectory file*/
-uint8_t const FAT_FILE_TYPE_SUBDIR = 4;
-/** Test value for directory type */
-uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED;
-
-/** date field for FAT directory entry
+uint8_t const FAT_FILE_TYPE_CLOSED = 0, // This file has not been opened.
+ FAT_FILE_TYPE_NORMAL = 1, // A normal file
+ FAT_FILE_TYPE_ROOT_FIXED = 2, // A FAT12 or FAT16 root directory
+ FAT_FILE_TYPE_ROOT32 = 3, // A FAT32 root directory
+ FAT_FILE_TYPE_SUBDIR = 4, // A subdirectory file
+ FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED; // Test value for directory type
+
+/**
+ * date field for FAT directory entry
* \param[in] year [1980,2107]
* \param[in] month [1,12]
* \param[in] day [1,31]
*
* \return Packed date for dir_t entry.
*/
-static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
- return (year - 1980) << 9 | month << 5 | day;
-}
-/** year part of FAT directory date field
+static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { return (year - 1980) << 9 | month << 5 | day; }
+
+/**
+ * year part of FAT directory date field
* \param[in] fatDate Date in packed dir format.
*
* \return Extracted year [1980,2107]
*/
-static inline uint16_t FAT_YEAR(uint16_t fatDate) {
- return 1980 + (fatDate >> 9);
-}
-/** month part of FAT directory date field
+static inline uint16_t FAT_YEAR(uint16_t fatDate) { return 1980 + (fatDate >> 9); }
+
+/**
+ * month part of FAT directory date field
* \param[in] fatDate Date in packed dir format.
*
* \return Extracted month [1,12]
*/
-static inline uint8_t FAT_MONTH(uint16_t fatDate) {
- return (fatDate >> 5) & 0XF;
-}
-/** day part of FAT directory date field
+static inline uint8_t FAT_MONTH(uint16_t fatDate) { return (fatDate >> 5) & 0XF; }
+
+/**
+ * day part of FAT directory date field
* \param[in] fatDate Date in packed dir format.
*
* \return Extracted day [1,31]
*/
-static inline uint8_t FAT_DAY(uint16_t fatDate) {
- return fatDate & 0x1F;
-}
-/** time field for FAT directory entry
+static inline uint8_t FAT_DAY(uint16_t fatDate) { return fatDate & 0x1F; }
+
+/**
+ * time field for FAT directory entry
* \param[in] hour [0,23]
* \param[in] minute [0,59]
* \param[in] second [0,59]
*
* \return Packed time for dir_t entry.
*/
-static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
- return hour << 11 | minute << 5 | second >> 1;
-}
-/** hour part of FAT directory time field
+static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { return hour << 11 | minute << 5 | second >> 1; }
+
+/**
+ * hour part of FAT directory time field
* \param[in] fatTime Time in packed dir format.
*
* \return Extracted hour [0,23]
*/
-static inline uint8_t FAT_HOUR(uint16_t fatTime) {
- return fatTime >> 11;
-}
-/** minute part of FAT directory time field
+static inline uint8_t FAT_HOUR(uint16_t fatTime) { return fatTime >> 11; }
+
+/**
+ * minute part of FAT directory time field
* \param[in] fatTime Time in packed dir format.
*
* \return Extracted minute [0,59]
*/
-static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
- return (fatTime >> 5) & 0x3F;
-}
-/** second part of FAT directory time field
+static inline uint8_t FAT_MINUTE(uint16_t fatTime) { return (fatTime >> 5) & 0x3F; }
+
+/**
+ * second part of FAT directory time field
* Note second/2 is stored in packed time.
*
* \param[in] fatTime Time in packed dir format.
*
* \return Extracted second [0,58]
*/
-static inline uint8_t FAT_SECOND(uint16_t fatTime) {
- return 2 * (fatTime & 0x1F);
-}
-/** Default date for file timestamps is 1 Jan 2000 */
+static inline uint8_t FAT_SECOND(uint16_t fatTime) { return 2 * (fatTime & 0x1F); }
+
+// Default date for file timestamps is 1 Jan 2000
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
-/** Default time for file timestamp is 1 am */
+// Default time for file timestamp is 1 am
uint16_t const FAT_DEFAULT_TIME = (1 << 11);
-//------------------------------------------------------------------------------
+
/**
* \class SdBaseFile
* \brief Base class for SdFile with Print and C++ streams.
*/
class SdBaseFile {
public:
- /** Create an instance. */
SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
SdBaseFile(const char* path, uint8_t oflag);
- ~SdBaseFile() {if (isOpen()) close();}
+ ~SdBaseFile() { if (isOpen()) close(); }
+
/**
* writeError is set to true if an error occurs during a write().
* Set writeError to false before calling print() and/or write() and check
* for true after calls to print() and/or write().
*/
bool writeError;
- //----------------------------------------------------------------------------
+
// helpers for stream classes
- /** get position for streams
+
+ /**
+ * get position for streams
* \param[out] pos struct to receive position
*/
void getpos(filepos_t* pos);
- /** set position for streams
+
+ /**
+ * set position for streams
* \param[out] pos struct with value for new position
*/
void setpos(filepos_t* pos);
- //----------------------------------------------------------------------------
+
bool close();
bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
bool createContiguous(SdBaseFile* dirFile,
const char* path, uint32_t size);
- /** \return The current cluster number for a file or directory. */
- uint32_t curCluster() const {return curCluster_;}
- /** \return The current position for a file or directory. */
- uint32_t curPosition() const {return curPosition_;}
- /** \return Current working directory */
- static SdBaseFile* cwd() {return cwd_;}
- /** Set the date/time callback function
+ /**
+ * \return The current cluster number for a file or directory.
+ */
+ uint32_t curCluster() const { return curCluster_; }
+
+ /**
+ * \return The current position for a file or directory.
+ */
+ uint32_t curPosition() const { return curPosition_; }
+
+ /**
+ * \return Current working directory
+ */
+ static SdBaseFile* cwd() { return cwd_; }
+
+ /**
+ * Set the date/time callback function
*
* \param[in] dateTime The user's call back function. The callback
* function is of the form:
@@ -253,35 +243,55 @@ class SdBaseFile {
void (*dateTime)(uint16_t* date, uint16_t* time)) {
dateTime_ = dateTime;
}
- /** Cancel the date/time callback function. */
- static void dateTimeCallbackCancel() {dateTime_ = 0;}
+
+ /**
+ * Cancel the date/time callback function.
+ */
+ static void dateTimeCallbackCancel() { dateTime_ = 0; }
bool dirEntry(dir_t* dir);
static void dirName(const dir_t& dir, char* name);
bool exists(const char* name);
int16_t fgets(char* str, int16_t num, char* delim = 0);
- /** \return The total number of bytes in a file or directory. */
- uint32_t fileSize() const {return fileSize_;}
- /** \return The first cluster number for a file or directory. */
- uint32_t firstCluster() const {return firstCluster_;}
- bool getFilename(char* name);
- /** \return True if this is a directory else false. */
- bool isDir() const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}
- /** \return True if this is a normal file else false. */
- bool isFile() const {return type_ == FAT_FILE_TYPE_NORMAL;}
- /** \return True if this is an open file/directory else false. */
- bool isOpen() const {return type_ != FAT_FILE_TYPE_CLOSED;}
- /** \return True if this is a subdirectory else false. */
- bool isSubDir() const {return type_ == FAT_FILE_TYPE_SUBDIR;}
- /** \return True if this is the root directory. */
- bool isRoot() const {
- return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32;
- }
+
+ /**
+ * \return The total number of bytes in a file or directory.
+ */
+ uint32_t fileSize() const { return fileSize_; }
+
+ /**
+ * \return The first cluster number for a file or directory.
+ */
+ uint32_t firstCluster() const { return firstCluster_; }
+
+ /**
+ * \return True if this is a directory else false.
+ */
+ bool isDir() const { return type_ >= FAT_FILE_TYPE_MIN_DIR; }
+
+ /**
+ * \return True if this is a normal file else false.
+ */
+ bool isFile() const { return type_ == FAT_FILE_TYPE_NORMAL; }
+
+ /**
+ * \return True if this is an open file/directory else false.
+ */
+ bool isOpen() const { return type_ != FAT_FILE_TYPE_CLOSED; }
+
+ /**
+ * \return True if this is a subdirectory else false.
+ */
+ bool isSubDir() const { return type_ == FAT_FILE_TYPE_SUBDIR; }
+
+ /**
+ * \return True if this is the root directory.
+ */
+ bool isRoot() const { return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32; }
+
+ bool getFilename(char * const name);
void ls(uint8_t flags = 0, uint8_t indent = 0);
+
bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
- // alias for backward compactability
- bool makeDir(SdBaseFile* dir, const char* path) {
- return mkdir(dir, path, false);
- }
bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
bool open(const char* path, uint8_t oflag = O_READ);
@@ -296,53 +306,58 @@ class SdBaseFile {
int8_t readDir(dir_t* dir, char* longFilename);
static bool remove(SdBaseFile* dirFile, const char* path);
bool remove();
- /** Set the file's current position to zero. */
- void rewind() {seekSet(0);}
+
+ /**
+ * Set the file's current position to zero.
+ */
+ void rewind() { seekSet(0); }
bool rename(SdBaseFile* dirFile, const char* newPath);
bool rmdir();
- // for backward compatibility
- bool rmDir() {return rmdir();}
bool rmRfStar();
- /** Set the files position to current position + \a pos. See seekSet().
+
+ /**
+ * Set the files position to current position + \a pos. See seekSet().
* \param[in] offset The new position in bytes from the current position.
* \return true for success or false for failure.
*/
- bool seekCur(int32_t offset) {
- return seekSet(curPosition_ + offset);
- }
- /** Set the files position to end-of-file + \a offset. See seekSet().
+ bool seekCur(const int32_t offset) { return seekSet(curPosition_ + offset); }
+
+ /**
+ * Set the files position to end-of-file + \a offset. See seekSet().
* \param[in] offset The new position in bytes from end-of-file.
* \return true for success or false for failure.
*/
- bool seekEnd(int32_t offset = 0) {return seekSet(fileSize_ + offset);}
- bool seekSet(uint32_t pos);
+ bool seekEnd(const int32_t offset = 0) { return seekSet(fileSize_ + offset); }
+ bool seekSet(const uint32_t pos);
bool sync();
bool timestamp(SdBaseFile* file);
bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t minute, uint8_t second);
- /** Type of file. You should use isFile() or isDir() instead of type()
- * if possible.
+
+ /**
+ * Type of file. Use isFile() or isDir() instead of type() if possible.
*
* \return The file or directory type.
*/
- uint8_t type() const {return type_;}
+ uint8_t type() const { return type_; }
bool truncate(uint32_t size);
- /** \return SdVolume that contains this file. */
- SdVolume* volume() const {return vol_;}
+
+ /**
+ * \return SdVolume that contains this file.
+ */
+ SdVolume* volume() const { return vol_; }
int16_t write(const void* buf, uint16_t nbyte);
- //------------------------------------------------------------------------------
+
private:
- // allow SdFat to set cwd_
- friend class SdFat;
- // global pointer to cwd dir
- static SdBaseFile* cwd_;
+ friend class SdFat; // allow SdFat to set cwd_
+ static SdBaseFile* cwd_; // global pointer to cwd dir
+
// data time callback function
static void (*dateTime_)(uint16_t* date, uint16_t* time);
+
// bits defined in flags_
- // should be 0x0F
- static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
- // sync of directory entry required
- static uint8_t const F_FILE_DIR_DIRTY = 0x80;
+ static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC), // should be 0x0F
+ F_FILE_DIR_DIRTY = 0x80; // sync of directory entry required
// private data
uint8_t flags_; // See above for definition of flags_ bits
@@ -356,8 +371,11 @@ class SdBaseFile {
uint32_t firstCluster_; // first cluster of file
SdVolume* vol_; // volume where file is located
- /** experimental don't use */
- bool openParent(SdBaseFile* dir);
+ /**
+ * EXPERIMENTAL - Don't use!
+ */
+ //bool openParent(SdBaseFile* dir);
+
// private functions
bool addCluster();
bool addDirCluster();
@@ -368,61 +386,48 @@ class SdBaseFile {
bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
dir_t* readDirCache();
- //------------------------------------------------------------------------------
- // to be deleted
- static void printDirName(const dir_t& dir,
- uint8_t width, bool printSlash);
- //------------------------------------------------------------------------------
- // Deprecated functions - suppress cpplint warnings with NOLINT comment
-#if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
+
+// Deprecated functions
+#if ALLOW_DEPRECATED_FUNCTIONS
public:
- /** \deprecated Use:
+
+ /**
+ * \deprecated Use:
* bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
* \param[out] bgnBlock the first block address for the file.
* \param[out] endBlock the last block address for the file.
* \return true for success or false for failure.
*/
- bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT
+ bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) {
return contiguousRange(&bgnBlock, &endBlock);
}
- /** \deprecated Use:
- * bool createContiguous(SdBaseFile* dirFile,
- * const char* path, uint32_t size)
- * \param[in] dirFile The directory where the file will be created.
- * \param[in] path A path with a valid DOS 8.3 file name.
- * \param[in] size The desired file size.
- * \return true for success or false for failure.
- */
- bool createContiguous(SdBaseFile& dirFile, // NOLINT
- const char* path, uint32_t size) {
+
+ /**
+ * \deprecated Use:
+ * bool createContiguous(SdBaseFile* dirFile, const char* path, uint32_t size)
+ * \param[in] dirFile The directory where the file will be created.
+ * \param[in] path A path with a valid DOS 8.3 file name.
+ * \param[in] size The desired file size.
+ * \return true for success or false for failure.
+ */
+ bool createContiguous(SdBaseFile& dirFile, const char* path, uint32_t size) {
return createContiguous(&dirFile, path, size);
}
- /** \deprecated Use:
+
+ /**
+ * \deprecated Use:
* static void dateTimeCallback(
* void (*dateTime)(uint16_t* date, uint16_t* time));
* \param[in] dateTime The user's call back function.
*/
static void dateTimeCallback(
- void (*dateTime)(uint16_t &date, uint16_t &time)) { // NOLINT
+ void (*dateTime)(uint16_t &date, uint16_t &time)) {
oldDateTime_ = dateTime;
dateTime_ = dateTime ? oldToNew : 0;
}
- /** \deprecated Use: bool dirEntry(dir_t* dir);
- * \param[out] dir Location for return of the file's directory entry.
- * \return true for success or false for failure.
- */
- bool dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT
- /** \deprecated Use:
- * bool mkdir(SdBaseFile* dir, const char* path);
- * \param[in] dir An open SdFat instance for the directory that will contain
- * the new directory.
- * \param[in] path A path with a valid 8.3 DOS name for the new directory.
- * \return true for success or false for failure.
- */
- bool mkdir(SdBaseFile& dir, const char* path) { // NOLINT
- return mkdir(&dir, path);
- }
- /** \deprecated Use:
+
+ /**
+ * \deprecated Use:
* bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
* \param[in] dirFile An open SdFat instance for the directory containing the
* file to be opened.
@@ -431,20 +436,23 @@ class SdBaseFile {
* OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
* \return true for success or false for failure.
*/
- bool open(SdBaseFile& dirFile, // NOLINT
- const char* path, uint8_t oflag) {
+ bool open(SdBaseFile& dirFile, const char* path, uint8_t oflag) {
return open(&dirFile, path, oflag);
}
- /** \deprecated Do not use in new apps
+
+ /**
+ * \deprecated Do not use in new apps
* \param[in] dirFile An open SdFat instance for the directory containing the
* file to be opened.
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
* \return true for success or false for failure.
*/
- bool open(SdBaseFile& dirFile, const char* path) { // NOLINT
+ bool open(SdBaseFile& dirFile, const char* path) {
return open(dirFile, path, O_RDWR);
}
- /** \deprecated Use:
+
+ /**
+ * \deprecated Use:
* bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
* \param[in] dirFile An open SdFat instance for the directory.
* \param[in] index The \a index of the directory entry for the file to be
@@ -453,35 +461,39 @@ class SdBaseFile {
* OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
* \return true for success or false for failure.
*/
- bool open(SdBaseFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT
+ bool open(SdBaseFile& dirFile, uint16_t index, uint8_t oflag) {
return open(&dirFile, index, oflag);
}
- /** \deprecated Use: bool openRoot(SdVolume* vol);
+
+ /**
+ * \deprecated Use: bool openRoot(SdVolume* vol);
* \param[in] vol The FAT volume containing the root directory to be opened.
* \return true for success or false for failure.
*/
- bool openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT
- /** \deprecated Use: int8_t readDir(dir_t* dir);
+ bool openRoot(SdVolume& vol) { return openRoot(&vol); }
+
+ /**
+ * \deprecated Use: int8_t readDir(dir_t* dir);
* \param[out] dir The dir_t struct that will receive the data.
* \return bytes read for success zero for eof or -1 for failure.
*/
- int8_t readDir(dir_t& dir, char* longFilename) {return readDir(&dir, longFilename);} // NOLINT
- /** \deprecated Use:
+ int8_t readDir(dir_t& dir, char* longFilename) {
+ return readDir(&dir, longFilename);
+ }
+
+ /**
+ * \deprecated Use:
* static uint8_t remove(SdBaseFile* dirFile, const char* path);
* \param[in] dirFile The directory that contains the file.
* \param[in] path The name of the file to be removed.
* \return true for success or false for failure.
*/
- static bool remove(SdBaseFile& dirFile, const char* path) { // NOLINT
- return remove(&dirFile, path);
- }
- //------------------------------------------------------------------------------
- // rest are private
+ static bool remove(SdBaseFile& dirFile, const char* path) { return remove(&dirFile, path); }
+
private:
- static void (*oldDateTime_)(uint16_t &date, uint16_t &time); // NOLINT
- static void oldToNew(uint16_t* date, uint16_t* time) {
- uint16_t d;
- uint16_t t;
+ static void (*oldDateTime_)(uint16_t &date, uint16_t &time);
+ static void oldToNew(uint16_t * const date, uint16_t * const time) {
+ uint16_t d, t;
oldDateTime_(d, t);
*date = d;
*time = t;
@@ -489,4 +501,4 @@ class SdBaseFile {
#endif // ALLOW_DEPRECATED_FUNCTIONS
};
-#endif // SDBASEFILE_H
+#endif // _SDBASEFILE_H_
diff --git a/Marlin/src/sd/SdFatConfig.h b/Marlin/src/sd/SdFatConfig.h
index e4d6324ecbc8ca759be9b0df077c34f46b4db509..5cedddb06d5a224144671e39572d89db401e9551 100644
--- a/Marlin/src/sd/SdFatConfig.h
+++ b/Marlin/src/sd/SdFatConfig.h
@@ -33,7 +33,6 @@
#include "../inc/MarlinConfig.h"
-//------------------------------------------------------------------------------
/**
* To use multiple SD cards set USE_MULTIPLE_CARDS nonzero.
@@ -44,8 +43,6 @@
*/
#define USE_MULTIPLE_CARDS 0
-//------------------------------------------------------------------------------
-
/**
* Call flush for endl if ENDL_CALLS_FLUSH is nonzero
*
@@ -65,39 +62,29 @@
*/
#define ENDL_CALLS_FLUSH 0
-//------------------------------------------------------------------------------
-
/**
* Allow use of deprecated functions if ALLOW_DEPRECATED_FUNCTIONS is nonzero
*/
#define ALLOW_DEPRECATED_FUNCTIONS 1
-//------------------------------------------------------------------------------
-
/**
* Allow FAT12 volumes if FAT12_SUPPORT is nonzero.
* FAT12 has not been well tested.
*/
#define FAT12_SUPPORT 0
-//------------------------------------------------------------------------------
-
/**
* SPI init rate for SD initialization commands. Must be 5 (F_CPU/64)
* or 6 (F_CPU/128).
*/
#define SPI_SD_INIT_RATE 5
-//------------------------------------------------------------------------------
-
/**
* Set the SS pin high for hardware SPI. If SS is chip select for another SPI
* device this will disable that device during the SD init phase.
*/
#define SET_SPI_SS_HIGH 1
-//------------------------------------------------------------------------------
-
/**
* Define MEGA_SOFT_SPI nonzero to use software SPI on Mega Arduinos.
* Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.
@@ -108,8 +95,6 @@
*/
#define MEGA_SOFT_SPI 0
-//------------------------------------------------------------------------------
-
// Set USE_SOFTWARE_SPI nonzero to ALWAYS use Software SPI.
#define USE_SOFTWARE_SPI 0
@@ -119,8 +104,6 @@
#define SOFT_SPI_MISO_PIN 12 // Software SPI Master In Slave Out pin
#define SOFT_SPI_SCK_PIN 13 // Software SPI Clock pin
-//------------------------------------------------------------------------------
-
/**
* The __cxa_pure_virtual function is an error handler that is invoked when
* a pure virtual function is called.
diff --git a/Marlin/src/sd/SdFatStructs.h b/Marlin/src/sd/SdFatStructs.h
index 078be6c6a70def66e35b7d611a7821a1448b9d2d..7b84b1ad0cffaf2d9041d277dfd4d8fd8e05054d 100644
--- a/Marlin/src/sd/SdFatStructs.h
+++ b/Marlin/src/sd/SdFatStructs.h
@@ -20,35 +20,33 @@
*
*/
+/**
+ * \file
+ * \brief FAT file structures
+ */
+
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
-
#ifndef SDFATSTRUCTS_H
#define SDFATSTRUCTS_H
#include <stdint.h>
#define PACKED __attribute__((__packed__))
-/**
- * \file
- * \brief FAT file structures
- */
+
/**
* mostly from Microsoft document fatgen103.doc
* http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
*/
-//------------------------------------------------------------------------------
-/** Value for byte 510 of boot block or MBR */
-uint8_t const BOOTSIG0 = 0x55;
-/** Value for byte 511 of boot block or MBR */
-uint8_t const BOOTSIG1 = 0xAA;
-/** Value for bootSignature field int FAT/FAT32 boot sector */
-uint8_t const EXTENDED_BOOT_SIG = 0x29;
-//------------------------------------------------------------------------------
+
+uint8_t const BOOTSIG0 = 0x55, // Value for byte 510 of boot block or MBR
+ BOOTSIG1 = 0xAA, // Value for byte 511 of boot block or MBR
+ EXTENDED_BOOT_SIG = 0x29; // Value for bootSignature field int FAT/FAT32 boot sector
+
/**
* \struct partitionTable
* \brief MBR partition table entry
@@ -57,59 +55,58 @@ uint8_t const EXTENDED_BOOT_SIG = 0x29;
* The MBR partition table has four entries.
*/
struct partitionTable {
- /**
- * Boot Indicator . Indicates whether the volume is the active
- * partition. Legal values include: 0x00. Do not use for booting.
- * 0x80 Active partition.
- */
+ /**
+ * Boot Indicator . Indicates whether the volume is the active
+ * partition. Legal values include: 0x00. Do not use for booting.
+ * 0x80 Active partition.
+ */
uint8_t boot;
- /**
- * Head part of Cylinder-head-sector address of the first block in
- * the partition. Legal values are 0-255. Only used in old PC BIOS.
- */
+ /**
+ * Head part of Cylinder-head-sector address of the first block in
+ * the partition. Legal values are 0-255. Only used in old PC BIOS.
+ */
uint8_t beginHead;
- /**
- * Sector part of Cylinder-head-sector address of the first block in
- * the partition. Legal values are 1-63. Only used in old PC BIOS.
- */
+ /**
+ * Sector part of Cylinder-head-sector address of the first block in
+ * the partition. Legal values are 1-63. Only used in old PC BIOS.
+ */
unsigned beginSector : 6;
- /** High bits cylinder for first block in partition. */
+ /** High bits cylinder for first block in partition. */
unsigned beginCylinderHigh : 2;
- /**
- * Combine beginCylinderLow with beginCylinderHigh. Legal values
- * are 0-1023. Only used in old PC BIOS.
- */
+ /**
+ * Combine beginCylinderLow with beginCylinderHigh. Legal values
+ * are 0-1023. Only used in old PC BIOS.
+ */
uint8_t beginCylinderLow;
- /**
- * Partition type. See defines that begin with PART_TYPE_ for
- * some Microsoft partition types.
- */
+ /**
+ * Partition type. See defines that begin with PART_TYPE_ for
+ * some Microsoft partition types.
+ */
uint8_t type;
- /**
- * head part of cylinder-head-sector address of the last sector in the
- * partition. Legal values are 0-255. Only used in old PC BIOS.
- */
+ /**
+ * head part of cylinder-head-sector address of the last sector in the
+ * partition. Legal values are 0-255. Only used in old PC BIOS.
+ */
uint8_t endHead;
- /**
- * Sector part of cylinder-head-sector address of the last sector in
- * the partition. Legal values are 1-63. Only used in old PC BIOS.
- */
+ /**
+ * Sector part of cylinder-head-sector address of the last sector in
+ * the partition. Legal values are 1-63. Only used in old PC BIOS.
+ */
unsigned endSector : 6;
- /** High bits of end cylinder */
+ /** High bits of end cylinder */
unsigned endCylinderHigh : 2;
- /**
- * Combine endCylinderLow with endCylinderHigh. Legal values
- * are 0-1023. Only used in old PC BIOS.
- */
+ /**
+ * Combine endCylinderLow with endCylinderHigh. Legal values
+ * are 0-1023. Only used in old PC BIOS.
+ */
uint8_t endCylinderLow;
- /** Logical block address of the first block in the partition. */
- uint32_t firstSector;
- /** Length of the partition, in blocks. */
- uint32_t totalSectors;
+
+ uint32_t firstSector; // Logical block address of the first block in the partition.
+ uint32_t totalSectors; // Length of the partition, in blocks.
} PACKED;
-/** Type name for partitionTable */
-typedef struct partitionTable part_t;
-//------------------------------------------------------------------------------
+
+typedef struct partitionTable part_t; // Type name for partitionTable
+
/**
* \struct masterBootRecord
*
@@ -118,22 +115,16 @@ typedef struct partitionTable part_t;
* The first block of a storage device that is formatted with a MBR.
*/
struct masterBootRecord {
- /** Code Area for master boot program. */
- uint8_t codeArea[440];
- /** Optional Windows NT disk signature. May contain boot code. */
- uint32_t diskSignature;
- /** Usually zero but may be more boot code. */
- uint16_t usuallyZero;
- /** Partition tables. */
- part_t part[4];
- /** First MBR signature byte. Must be 0x55 */
- uint8_t mbrSig0;
- /** Second MBR signature byte. Must be 0xAA */
- uint8_t mbrSig1;
+ uint8_t codeArea[440]; // Code Area for master boot program.
+ uint32_t diskSignature; // Optional Windows NT disk signature. May contain boot code.
+ uint16_t usuallyZero; // Usually zero but may be more boot code.
+ part_t part[4]; // Partition tables.
+ uint8_t mbrSig0; // First MBR signature byte. Must be 0x55
+ uint8_t mbrSig1; // Second MBR signature byte. Must be 0xAA
} PACKED;
/** Type name for masterBootRecord */
typedef struct masterBootRecord mbr_t;
-//------------------------------------------------------------------------------
+
/**
* \struct fat_boot
*
@@ -141,285 +132,280 @@ typedef struct masterBootRecord mbr_t;
*
*/
struct fat_boot {
- /**
- * The first three bytes of the boot sector must be valid,
- * executable x 86-based CPU instructions. This includes a
- * jump instruction that skips the next nonexecutable bytes.
- */
+ /**
+ * The first three bytes of the boot sector must be valid,
+ * executable x 86-based CPU instructions. This includes a
+ * jump instruction that skips the next nonexecutable bytes.
+ */
uint8_t jump[3];
- /**
- * This is typically a string of characters that identifies
- * the operating system that formatted the volume.
- */
+ /**
+ * This is typically a string of characters that identifies
+ * the operating system that formatted the volume.
+ */
char oemId[8];
- /**
- * The size of a hardware sector. Valid decimal values for this
- * field are 512, 1024, 2048, and 4096. For most disks used in
- * the United States, the value of this field is 512.
- */
+ /**
+ * The size of a hardware sector. Valid decimal values for this
+ * field are 512, 1024, 2048, and 4096. For most disks used in
+ * the United States, the value of this field is 512.
+ */
uint16_t bytesPerSector;
- /**
- * Number of sectors per allocation unit. This value must be a
- * power of 2 that is greater than 0. The legal values are
- * 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
- */
+ /**
+ * Number of sectors per allocation unit. This value must be a
+ * power of 2 that is greater than 0. The legal values are
+ * 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
+ */
uint8_t sectorsPerCluster;
- /**
- * The number of sectors preceding the start of the first FAT,
- * including the boot sector. The value of this field is always 1.
- */
+ /**
+ * The number of sectors preceding the start of the first FAT,
+ * including the boot sector. The value of this field is always 1.
+ */
uint16_t reservedSectorCount;
- /**
- * The number of copies of the FAT on the volume.
- * The value of this field is always 2.
- */
+ /**
+ * The number of copies of the FAT on the volume.
+ * The value of this field is always 2.
+ */
uint8_t fatCount;
- /**
- * For FAT12 and FAT16 volumes, this field contains the count of
- * 32-byte directory entries in the root directory. For FAT32 volumes,
- * this field must be set to 0. For FAT12 and FAT16 volumes, this
- * value should always specify a count that when multiplied by 32
- * results in a multiple of bytesPerSector. FAT16 volumes should
- * use the value 512.
- */
+ /**
+ * For FAT12 and FAT16 volumes, this field contains the count of
+ * 32-byte directory entries in the root directory. For FAT32 volumes,
+ * this field must be set to 0. For FAT12 and FAT16 volumes, this
+ * value should always specify a count that when multiplied by 32
+ * results in a multiple of bytesPerSector. FAT16 volumes should
+ * use the value 512.
+ */
uint16_t rootDirEntryCount;
- /**
- * This field is the old 16-bit total count of sectors on the volume.
- * This count includes the count of all sectors in all four regions
- * of the volume. This field can be 0; if it is 0, then totalSectors32
- * must be nonzero. For FAT32 volumes, this field must be 0. For
- * FAT12 and FAT16 volumes, this field contains the sector count, and
- * totalSectors32 is 0 if the total sector count fits
- * (is less than 0x10000).
- */
+ /**
+ * This field is the old 16-bit total count of sectors on the volume.
+ * This count includes the count of all sectors in all four regions
+ * of the volume. This field can be 0; if it is 0, then totalSectors32
+ * must be nonzero. For FAT32 volumes, this field must be 0. For
+ * FAT12 and FAT16 volumes, this field contains the sector count, and
+ * totalSectors32 is 0 if the total sector count fits
+ * (is less than 0x10000).
+ */
uint16_t totalSectors16;
- /**
- * This dates back to the old MS-DOS 1.x media determination and is
- * no longer usually used for anything. 0xF8 is the standard value
- * for fixed (nonremovable) media. For removable media, 0xF0 is
- * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
- */
+ /**
+ * This dates back to the old MS-DOS 1.x media determination and is
+ * no longer usually used for anything. 0xF8 is the standard value
+ * for fixed (nonremovable) media. For removable media, 0xF0 is
+ * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
+ */
uint8_t mediaType;
- /**
- * Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
- * On FAT32 volumes this field must be 0, and sectorsPerFat32
- * contains the FAT size count.
- */
+ /**
+ * Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
+ * On FAT32 volumes this field must be 0, and sectorsPerFat32
+ * contains the FAT size count.
+ */
uint16_t sectorsPerFat16;
- /** Sectors per track for interrupt 0x13. Not used otherwise. */
- uint16_t sectorsPerTrack;
- /** Number of heads for interrupt 0x13. Not used otherwise. */
- uint16_t headCount;
- /**
- * Count of hidden sectors preceding the partition that contains this
- * FAT volume. This field is generally only relevant for media
- * visible on interrupt 0x13.
- */
+
+ uint16_t sectorsPerTrack; // Sectors per track for interrupt 0x13. Not used otherwise.
+ uint16_t headCount; // Number of heads for interrupt 0x13. Not used otherwise.
+
+ /**
+ * Count of hidden sectors preceding the partition that contains this
+ * FAT volume. This field is generally only relevant for media
+ * visible on interrupt 0x13.
+ */
uint32_t hidddenSectors;
- /**
- * This field is the new 32-bit total count of sectors on the volume.
- * This count includes the count of all sectors in all four regions
- * of the volume. This field can be 0; if it is 0, then
- * totalSectors16 must be nonzero.
- */
+ /**
+ * This field is the new 32-bit total count of sectors on the volume.
+ * This count includes the count of all sectors in all four regions
+ * of the volume. This field can be 0; if it is 0, then
+ * totalSectors16 must be nonzero.
+ */
uint32_t totalSectors32;
- /**
- * Related to the BIOS physical drive number. Floppy drives are
- * identified as 0x00 and physical hard disks are identified as
- * 0x80, regardless of the number of physical disk drives.
- * Typically, this value is set prior to issuing an INT 13h BIOS
- * call to specify the device to access. The value is only
- * relevant if the device is a boot device.
- */
+ /**
+ * Related to the BIOS physical drive number. Floppy drives are
+ * identified as 0x00 and physical hard disks are identified as
+ * 0x80, regardless of the number of physical disk drives.
+ * Typically, this value is set prior to issuing an INT 13h BIOS
+ * call to specify the device to access. The value is only
+ * relevant if the device is a boot device.
+ */
uint8_t driveNumber;
- /** used by Windows NT - should be zero for FAT */
- uint8_t reserved1;
- /** 0x29 if next three fields are valid */
- uint8_t bootSignature;
- /**
- * A random serial number created when formatting a disk,
- * which helps to distinguish between disks.
- * Usually generated by combining date and time.
- */
+
+ uint8_t reserved1; // used by Windows NT - should be zero for FAT
+ uint8_t bootSignature; // 0x29 if next three fields are valid
+
+ /**
+ * A random serial number created when formatting a disk,
+ * which helps to distinguish between disks.
+ * Usually generated by combining date and time.
+ */
uint32_t volumeSerialNumber;
- /**
- * A field once used to store the volume label. The volume label
- * is now stored as a special file in the root directory.
- */
+ /**
+ * A field once used to store the volume label. The volume label
+ * is now stored as a special file in the root directory.
+ */
char volumeLabel[11];
- /**
- * A field with a value of either FAT, FAT12 or FAT16,
- * depending on the disk format.
- */
+ /**
+ * A field with a value of either FAT, FAT12 or FAT16,
+ * depending on the disk format.
+ */
char fileSystemType[8];
- /** X86 boot code */
- uint8_t bootCode[448];
- /** must be 0x55 */
- uint8_t bootSectorSig0;
- /** must be 0xAA */
- uint8_t bootSectorSig1;
+
+ uint8_t bootCode[448]; // X86 boot code
+ uint8_t bootSectorSig0; // must be 0x55
+ uint8_t bootSectorSig1; // must be 0xAA
} PACKED;
-/** Type name for FAT Boot Sector */
-typedef struct fat_boot fat_boot_t;
-//------------------------------------------------------------------------------
+
+typedef struct fat_boot fat_boot_t; // Type name for FAT Boot Sector
+
/**
* \struct fat32_boot
*
* \brief Boot sector for a FAT32 volume.
- *
*/
struct fat32_boot {
- /**
- * The first three bytes of the boot sector must be valid,
- * executable x 86-based CPU instructions. This includes a
- * jump instruction that skips the next nonexecutable bytes.
- */
+ /**
+ * The first three bytes of the boot sector must be valid,
+ * executable x 86-based CPU instructions. This includes a
+ * jump instruction that skips the next nonexecutable bytes.
+ */
uint8_t jump[3];
- /**
- * This is typically a string of characters that identifies
- * the operating system that formatted the volume.
- */
+ /**
+ * This is typically a string of characters that identifies
+ * the operating system that formatted the volume.
+ */
char oemId[8];
- /**
- * The size of a hardware sector. Valid decimal values for this
- * field are 512, 1024, 2048, and 4096. For most disks used in
- * the United States, the value of this field is 512.
- */
+ /**
+ * The size of a hardware sector. Valid decimal values for this
+ * field are 512, 1024, 2048, and 4096. For most disks used in
+ * the United States, the value of this field is 512.
+ */
uint16_t bytesPerSector;
- /**
- * Number of sectors per allocation unit. This value must be a
- * power of 2 that is greater than 0. The legal values are
- * 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
- */
+ /**
+ * Number of sectors per allocation unit. This value must be a
+ * power of 2 that is greater than 0. The legal values are
+ * 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
+ */
uint8_t sectorsPerCluster;
- /**
- * The number of sectors preceding the start of the first FAT,
- * including the boot sector. Must not be zero
- */
+ /**
+ * The number of sectors preceding the start of the first FAT,
+ * including the boot sector. Must not be zero
+ */
uint16_t reservedSectorCount;
- /**
- * The number of copies of the FAT on the volume.
- * The value of this field is always 2.
- */
+ /**
+ * The number of copies of the FAT on the volume.
+ * The value of this field is always 2.
+ */
uint8_t fatCount;
- /**
- * FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0.
- */
+ /**
+ * FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0.
+ */
uint16_t rootDirEntryCount;
- /**
- * For FAT32 volumes, this field must be 0.
- */
+ /**
+ * For FAT32 volumes, this field must be 0.
+ */
uint16_t totalSectors16;
- /**
- * This dates back to the old MS-DOS 1.x media determination and is
- * no longer usually used for anything. 0xF8 is the standard value
- * for fixed (nonremovable) media. For removable media, 0xF0 is
- * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
- */
+ /**
+ * This dates back to the old MS-DOS 1.x media determination and is
+ * no longer usually used for anything. 0xF8 is the standard value
+ * for fixed (nonremovable) media. For removable media, 0xF0 is
+ * frequently used. Legal values are 0xF0 or 0xF8-0xFF.
+ */
uint8_t mediaType;
- /**
- * On FAT32 volumes this field must be 0, and sectorsPerFat32
- * contains the FAT size count.
- */
+ /**
+ * On FAT32 volumes this field must be 0, and sectorsPerFat32
+ * contains the FAT size count.
+ */
uint16_t sectorsPerFat16;
- /** Sectors per track for interrupt 0x13. Not used otherwise. */
- uint16_t sectorsPerTrack;
- /** Number of heads for interrupt 0x13. Not used otherwise. */
- uint16_t headCount;
- /**
- * Count of hidden sectors preceding the partition that contains this
- * FAT volume. This field is generally only relevant for media
- * visible on interrupt 0x13.
- */
+
+ uint16_t sectorsPerTrack; // Sectors per track for interrupt 0x13. Not used otherwise.
+ uint16_t headCount; // Number of heads for interrupt 0x13. Not used otherwise.
+
+ /**
+ * Count of hidden sectors preceding the partition that contains this
+ * FAT volume. This field is generally only relevant for media
+ * visible on interrupt 0x13.
+ */
uint32_t hidddenSectors;
- /**
- * Contains the total number of sectors in the FAT32 volume.
- */
+ /**
+ * Contains the total number of sectors in the FAT32 volume.
+ */
uint32_t totalSectors32;
- /**
- * Count of sectors occupied by one FAT on FAT32 volumes.
- */
+ /**
+ * Count of sectors occupied by one FAT on FAT32 volumes.
+ */
uint32_t sectorsPerFat32;
- /**
- * This field is only defined for FAT32 media and does not exist on
- * FAT12 and FAT16 media.
- * Bits 0-3 -- Zero-based number of active FAT.
- * Only valid if mirroring is disabled.
- * Bits 4-6 -- Reserved.
- * Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs.
- * -- 1 means only one FAT is active; it is the one referenced
- * in bits 0-3.
- * Bits 8-15 -- Reserved.
- */
+ /**
+ * This field is only defined for FAT32 media and does not exist on
+ * FAT12 and FAT16 media.
+ * Bits 0-3 -- Zero-based number of active FAT.
+ * Only valid if mirroring is disabled.
+ * Bits 4-6 -- Reserved.
+ * Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs.
+ * -- 1 means only one FAT is active; it is the one referenced
+ * in bits 0-3.
+ * Bits 8-15 -- Reserved.
+ */
uint16_t fat32Flags;
- /**
- * FAT32 version. High byte is major revision number.
- * Low byte is minor revision number. Only 0.0 define.
- */
+ /**
+ * FAT32 version. High byte is major revision number.
+ * Low byte is minor revision number. Only 0.0 define.
+ */
uint16_t fat32Version;
- /**
- * Cluster number of the first cluster of the root directory for FAT32.
- * This usually 2 but not required to be 2.
- */
+ /**
+ * Cluster number of the first cluster of the root directory for FAT32.
+ * This usually 2 but not required to be 2.
+ */
uint32_t fat32RootCluster;
- /**
- * Sector number of FSINFO structure in the reserved area of the
- * FAT32 volume. Usually 1.
- */
+ /**
+ * Sector number of FSINFO structure in the reserved area of the
+ * FAT32 volume. Usually 1.
+ */
uint16_t fat32FSInfo;
- /**
- * If nonzero, indicates the sector number in the reserved area
- * of the volume of a copy of the boot record. Usually 6.
- * No value other than 6 is recommended.
- */
+ /**
+ * If nonzero, indicates the sector number in the reserved area
+ * of the volume of a copy of the boot record. Usually 6.
+ * No value other than 6 is recommended.
+ */
uint16_t fat32BackBootBlock;
- /**
- * Reserved for future expansion. Code that formats FAT32 volumes
- * should always set all of the bytes of this field to 0.
- */
+ /**
+ * Reserved for future expansion. Code that formats FAT32 volumes
+ * should always set all of the bytes of this field to 0.
+ */
uint8_t fat32Reserved[12];
- /**
- * Related to the BIOS physical drive number. Floppy drives are
- * identified as 0x00 and physical hard disks are identified as
- * 0x80, regardless of the number of physical disk drives.
- * Typically, this value is set prior to issuing an INT 13h BIOS
- * call to specify the device to access. The value is only
- * relevant if the device is a boot device.
- */
+ /**
+ * Related to the BIOS physical drive number. Floppy drives are
+ * identified as 0x00 and physical hard disks are identified as
+ * 0x80, regardless of the number of physical disk drives.
+ * Typically, this value is set prior to issuing an INT 13h BIOS
+ * call to specify the device to access. The value is only
+ * relevant if the device is a boot device.
+ */
uint8_t driveNumber;
- /** used by Windows NT - should be zero for FAT */
- uint8_t reserved1;
- /** 0x29 if next three fields are valid */
- uint8_t bootSignature;
- /**
- * A random serial number created when formatting a disk,
- * which helps to distinguish between disks.
- * Usually generated by combining date and time.
- */
+
+ uint8_t reserved1; // Used by Windows NT - should be zero for FAT
+ uint8_t bootSignature; // 0x29 if next three fields are valid
+
+ /**
+ * A random serial number created when formatting a disk,
+ * which helps to distinguish between disks.
+ * Usually generated by combining date and time.
+ */
uint32_t volumeSerialNumber;
- /**
- * A field once used to store the volume label. The volume label
- * is now stored as a special file in the root directory.
- */
+ /**
+ * A field once used to store the volume label. The volume label
+ * is now stored as a special file in the root directory.
+ */
char volumeLabel[11];
- /**
- * A text field with a value of FAT32.
- */
+ /**
+ * A text field with a value of FAT32.
+ */
char fileSystemType[8];
- /** X86 boot code */
- uint8_t bootCode[420];
- /** must be 0x55 */
- uint8_t bootSectorSig0;
- /** must be 0xAA */
- uint8_t bootSectorSig1;
+
+ uint8_t bootCode[420]; // X86 boot code
+ uint8_t bootSectorSig0; // must be 0x55
+ uint8_t bootSectorSig1; // must be 0xAA
+
} PACKED;
-/** Type name for FAT32 Boot Sector */
-typedef struct fat32_boot fat32_boot_t;
-//------------------------------------------------------------------------------
-/** Lead signature for a FSINFO sector */
-uint32_t const FSINFO_LEAD_SIG = 0x41615252;
-/** Struct signature for a FSINFO sector */
-uint32_t const FSINFO_STRUCT_SIG = 0x61417272;
+
+typedef struct fat32_boot fat32_boot_t; // Type name for FAT32 Boot Sector
+
+uint32_t const FSINFO_LEAD_SIG = 0x41615252, // 'AaRR' Lead signature for a FSINFO sector
+ FSINFO_STRUCT_SIG = 0x61417272; // 'aArr' Struct signature for a FSINFO sector
+
/**
* \struct fat32_fsinfo
*
@@ -427,12 +413,9 @@ uint32_t const FSINFO_STRUCT_SIG = 0x61417272;
*
*/
struct fat32_fsinfo {
- /** must be 0x52, 0x52, 0x61, 0x41 */
- uint32_t leadSignature;
- /** must be zero */
- uint8_t reserved1[480];
- /** must be 0x72, 0x72, 0x41, 0x61 */
- uint32_t structSignature;
+ uint32_t leadSignature; // must be 0x52, 0x52, 0x61, 0x41 'RRaA'
+ uint8_t reserved1[480]; // must be zero
+ uint32_t structSignature; // must be 0x72, 0x72, 0x41, 0x61 'rrAa'
/**
* Contains the last known free cluster count on the volume.
* If the value is 0xFFFFFFFF, then the free count is unknown
@@ -448,30 +431,22 @@ struct fat32_fsinfo {
* should start looking at cluster 2.
*/
uint32_t nextFree;
- /** must be zero */
- uint8_t reserved2[12];
- /** must be 0x00, 0x00, 0x55, 0xAA */
- uint8_t tailSignature[4];
+
+ uint8_t reserved2[12]; // must be zero
+ uint8_t tailSignature[4]; // must be 0x00, 0x00, 0x55, 0xAA
} PACKED;
-/** Type name for FAT32 FSINFO Sector */
-typedef struct fat32_fsinfo fat32_fsinfo_t;
-//------------------------------------------------------------------------------
+
+typedef struct fat32_fsinfo fat32_fsinfo_t; // Type name for FAT32 FSINFO Sector
+
// End Of Chain values for FAT entries
-/** FAT12 end of chain value used by Microsoft. */
-uint16_t const FAT12EOC = 0xFFF;
-/** Minimum value for FAT12 EOC. Use to test for EOC. */
-uint16_t const FAT12EOC_MIN = 0xFF8;
-/** FAT16 end of chain value used by Microsoft. */
-uint16_t const FAT16EOC = 0xFFFF;
-/** Minimum value for FAT16 EOC. Use to test for EOC. */
-uint16_t const FAT16EOC_MIN = 0xFFF8;
-/** FAT32 end of chain value used by Microsoft. */
-uint32_t const FAT32EOC = 0x0FFFFFFF;
-/** Minimum value for FAT32 EOC. Use to test for EOC. */
-uint32_t const FAT32EOC_MIN = 0x0FFFFFF8;
-/** Mask a for FAT32 entry. Entries are 28 bits. */
-uint32_t const FAT32MASK = 0x0FFFFFFF;
-//------------------------------------------------------------------------------
+uint16_t const FAT12EOC = 0xFFF, // FAT12 end of chain value used by Microsoft.
+ FAT12EOC_MIN = 0xFF8, // Minimum value for FAT12 EOC. Use to test for EOC.
+ FAT16EOC = 0xFFFF, // FAT16 end of chain value used by Microsoft.
+ FAT16EOC_MIN = 0xFFF8; // Minimum value for FAT16 EOC. Use to test for EOC.
+uint32_t const FAT32EOC = 0x0FFFFFFF, // FAT32 end of chain value used by Microsoft.
+ FAT32EOC_MIN = 0x0FFFFFF8, // Minimum value for FAT32 EOC. Use to test for EOC.
+ FAT32MASK = 0x0FFFFFFF; // Mask a for FAT32 entry. Entries are 28 bits.
+
/**
* \struct directoryEntry
* \brief FAT short directory entry
@@ -503,54 +478,54 @@ uint32_t const FAT32MASK = 0x0FFFFFFF;
* The valid time range is from Midnight 00:00:00 to 23:59:58.
*/
struct directoryEntry {
- /** Short 8.3 name.
- *
- * The first eight bytes contain the file name with blank fill.
- * The last three bytes contain the file extension with blank fill.
- */
+ /**
+ * Short 8.3 name.
+ *
+ * The first eight bytes contain the file name with blank fill.
+ * The last three bytes contain the file extension with blank fill.
+ */
uint8_t name[11];
- /** Entry attributes.
- *
- * The upper two bits of the attribute byte are reserved and should
- * always be set to 0 when a file is created and never modified or
- * looked at after that. See defines that begin with DIR_ATT_.
- */
+ /**
+ * Entry attributes.
+ *
+ * The upper two bits of the attribute byte are reserved and should
+ * always be set to 0 when a file is created and never modified or
+ * looked at after that. See defines that begin with DIR_ATT_.
+ */
uint8_t attributes;
- /**
- * Reserved for use by Windows NT. Set value to 0 when a file is
- * created and never modify or look at it after that.
- */
+ /**
+ * Reserved for use by Windows NT. Set value to 0 when a file is
+ * created and never modify or look at it after that.
+ */
uint8_t reservedNT;
- /**
- * The granularity of the seconds part of creationTime is 2 seconds
- * so this field is a count of tenths of a second and it's valid
- * value range is 0-199 inclusive. (WHG note - seems to be hundredths)
- */
+ /**
+ * The granularity of the seconds part of creationTime is 2 seconds
+ * so this field is a count of tenths of a second and it's valid
+ * value range is 0-199 inclusive. (WHG note - seems to be hundredths)
+ */
uint8_t creationTimeTenths;
- /** Time file was created. */
- uint16_t creationTime;
- /** Date file was created. */
- uint16_t creationDate;
- /**
- * Last access date. Note that there is no last access time, only
- * a date. This is the date of last read or write. In the case of
- * a write, this should be set to the same date as lastWriteDate.
- */
+
+ uint16_t creationTime; // Time file was created.
+ uint16_t creationDate; // Date file was created.
+
+ /**
+ * Last access date. Note that there is no last access time, only
+ * a date. This is the date of last read or write. In the case of
+ * a write, this should be set to the same date as lastWriteDate.
+ */
uint16_t lastAccessDate;
- /**
- * High word of this entry's first cluster number (always 0 for a
- * FAT12 or FAT16 volume).
- */
+ /**
+ * High word of this entry's first cluster number (always 0 for a
+ * FAT12 or FAT16 volume).
+ */
uint16_t firstClusterHigh;
- /** Time of last write. File creation is considered a write. */
- uint16_t lastWriteTime;
- /** Date of last write. File creation is considered a write. */
- uint16_t lastWriteDate;
- /** Low word of this entry's first cluster number. */
- uint16_t firstClusterLow;
- /** 32-bit unsigned holding this file's size in bytes. */
- uint32_t fileSize;
+
+ uint16_t lastWriteTime; // Time of last write. File creation is considered a write.
+ uint16_t lastWriteDate; // Date of last write. File creation is considered a write.
+ uint16_t firstClusterLow; // Low word of this entry's first cluster number.
+ uint32_t fileSize; // 32-bit unsigned holding this file's size in bytes.
} PACKED;
+
/**
* \struct directoryVFATEntry
* \brief VFAT long filename directory entry
@@ -568,54 +543,36 @@ struct directoryVFATEntry {
* bit 0-4: the position of this long filename block (first block is 1)
*/
uint8_t sequenceNumber;
- /** First set of UTF-16 characters */
- uint16_t name1[5];//UTF-16
- /** attributes (at the same location as in directoryEntry), always 0x0F */
- uint8_t attributes;
- /** Reserved for use by Windows NT. Always 0. */
- uint8_t reservedNT;
- /** Checksum of the short 8.3 filename, can be used to checked if the file system as modified by a not-long-filename aware implementation. */
- uint8_t checksum;
- /** Second set of UTF-16 characters */
- uint16_t name2[6];//UTF-16
- /** firstClusterLow is always zero for longFilenames */
- uint16_t firstClusterLow;
- /** Third set of UTF-16 characters */
- uint16_t name3[2];//UTF-16
+
+ uint16_t name1[5]; // First set of UTF-16 characters
+ uint8_t attributes; // attributes (at the same location as in directoryEntry), always 0x0F
+ uint8_t reservedNT; // Reserved for use by Windows NT. Always 0.
+ uint8_t checksum; // Checksum of the short 8.3 filename, can be used to checked if the file system as modified by a not-long-filename aware implementation.
+ uint16_t name2[6]; // Second set of UTF-16 characters
+ uint16_t firstClusterLow; // firstClusterLow is always zero for longFilenames
+ uint16_t name3[2]; // Third set of UTF-16 characters
} PACKED;
-//------------------------------------------------------------------------------
+
// Definitions for directory entries
//
-/** Type name for directoryEntry */
-typedef struct directoryEntry dir_t;
-/** Type name for directoryVFATEntry */
-typedef struct directoryVFATEntry vfat_t;
-/** escape for name[0] = 0xE5 */
-uint8_t const DIR_NAME_0xE5 = 0x05;
-/** name[0] value for entry that is free after being "deleted" */
-uint8_t const DIR_NAME_DELETED = 0xE5;
-/** name[0] value for entry that is free and no allocated entries follow */
-uint8_t const DIR_NAME_FREE = 0x00;
-/** file is read-only */
-uint8_t const DIR_ATT_READ_ONLY = 0x01;
-/** File should hidden in directory listings */
-uint8_t const DIR_ATT_HIDDEN = 0x02;
-/** Entry is for a system file */
-uint8_t const DIR_ATT_SYSTEM = 0x04;
-/** Directory entry contains the volume label */
-uint8_t const DIR_ATT_VOLUME_ID = 0x08;
-/** Entry is for a directory */
-uint8_t const DIR_ATT_DIRECTORY = 0x10;
-/** Old DOS archive bit for backup support */
-uint8_t const DIR_ATT_ARCHIVE = 0x20;
-/** Test value for long name entry. Test is
- (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
-uint8_t const DIR_ATT_LONG_NAME = 0x0F;
-/** Test mask for long name entry */
-uint8_t const DIR_ATT_LONG_NAME_MASK = 0x3F;
-/** defined attribute bits */
-uint8_t const DIR_ATT_DEFINED_BITS = 0x3F;
-/** Directory entry is part of a long name
+typedef struct directoryEntry dir_t; // Type name for directoryEntry
+typedef struct directoryVFATEntry vfat_t; // Type name for directoryVFATEntry
+
+uint8_t const DIR_NAME_0xE5 = 0x05, // escape for name[0] = 0xE5
+ DIR_NAME_DELETED = 0xE5, // name[0] value for entry that is free after being "deleted"
+ DIR_NAME_FREE = 0x00, // name[0] value for entry that is free and no allocated entries follow
+ DIR_ATT_READ_ONLY = 0x01, // file is read-only
+ DIR_ATT_HIDDEN = 0x02, // File should hidden in directory listings
+ DIR_ATT_SYSTEM = 0x04, // Entry is for a system file
+ DIR_ATT_VOLUME_ID = 0x08, // Directory entry contains the volume label
+ DIR_ATT_DIRECTORY = 0x10, // Entry is for a directory
+ DIR_ATT_ARCHIVE = 0x20, // Old DOS archive bit for backup support
+ DIR_ATT_LONG_NAME = 0x0F, // Test value for long name entry. Test is (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME.
+ DIR_ATT_LONG_NAME_MASK = 0x3F, // Test mask for long name entry
+ DIR_ATT_DEFINED_BITS = 0x3F; // defined attribute bits
+
+/**
+ * Directory entry is part of a long name
* \param[in] dir Pointer to a directory entry.
*
* \return true if the entry is for part of a long name else false.
@@ -623,9 +580,12 @@ uint8_t const DIR_ATT_DEFINED_BITS = 0x3F;
static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {
return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;
}
+
/** Mask for file/subdirectory tests */
uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
-/** Directory entry is for a file
+
+/**
+ * Directory entry is for a file
* \param[in] dir Pointer to a directory entry.
*
* \return true if the entry is for a normal file else false.
@@ -633,7 +593,9 @@ uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
}
-/** Directory entry is for a subdirectory
+
+/**
+ * Directory entry is for a subdirectory
* \param[in] dir Pointer to a directory entry.
*
* \return true if the entry is for a subdirectory else false.
@@ -641,7 +603,9 @@ static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
}
-/** Directory entry is for a file or subdirectory
+
+/**
+ * Directory entry is for a file or subdirectory
* \param[in] dir Pointer to a directory entry.
*
* \return true if the entry is for a normal file or subdirectory else false.
diff --git a/Marlin/src/sd/SdFatUtil.cpp b/Marlin/src/sd/SdFatUtil.cpp
index e54f18ddfc35e6359b73df0834815da2ab4270d3..329a59decc2871e0acb0e32c10a6b809c440d352 100644
--- a/Marlin/src/sd/SdFatUtil.cpp
+++ b/Marlin/src/sd/SdFatUtil.cpp
@@ -33,8 +33,8 @@
#include "SdFatUtil.h"
-//------------------------------------------------------------------------------
-/** Amount of free RAM
+/**
+ * Amount of free RAM
* \return The number of free bytes.
*/
#ifdef __arm__
@@ -46,7 +46,8 @@ int SdFatUtil::FreeRam() {
#else // __arm__
extern char* __brkval;
extern char __bss_end;
-/** Amount of free RAM
+/**
+ * Amount of free RAM
* \return The number of free bytes.
*/
int SdFatUtil::FreeRam() {
@@ -55,8 +56,8 @@ int SdFatUtil::FreeRam() {
}
#endif // __arm
-//------------------------------------------------------------------------------
-/** %Print a string in flash memory.
+/**
+ * %Print a string in flash memory.
*
* \param[in] pr Print object for output.
* \param[in] str Pointer to string stored in flash memory.
@@ -64,31 +65,27 @@ int SdFatUtil::FreeRam() {
void SdFatUtil::print_P(PGM_P str) {
for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.write(c);
}
-//------------------------------------------------------------------------------
-/** %Print a string in flash memory followed by a CR/LF.
+
+/**
+ * %Print a string in flash memory followed by a CR/LF.
*
* \param[in] pr Print object for output.
* \param[in] str Pointer to string stored in flash memory.
*/
-void SdFatUtil::println_P(PGM_P str) {
- print_P(str);
- MYSERIAL.println();
-}
-//------------------------------------------------------------------------------
-/** %Print a string in flash memory to Serial.
+void SdFatUtil::println_P(PGM_P str) { print_P(str); MYSERIAL.println(); }
+
+/**
+ * %Print a string in flash memory to Serial.
*
* \param[in] str Pointer to string stored in flash memory.
*/
-void SdFatUtil::SerialPrint_P(PGM_P str) {
- print_P(str);
-}
-//------------------------------------------------------------------------------
-/** %Print a string in flash memory to Serial followed by a CR/LF.
+void SdFatUtil::SerialPrint_P(PGM_P str) { print_P(str); }
+
+/**
+ * %Print a string in flash memory to Serial followed by a CR/LF.
*
* \param[in] str Pointer to string stored in flash memory.
*/
-void SdFatUtil::SerialPrintln_P(PGM_P str) {
- println_P(str);
-}
+void SdFatUtil::SerialPrintln_P(PGM_P str) { println_P(str); }
#endif // SDSUPPORT
diff --git a/Marlin/src/sd/SdFatUtil.h b/Marlin/src/sd/SdFatUtil.h
index b55460e79fbaf2cfc71da3070191fec4dcd43bbd..825d6d29d6bafbd89afd84b47e0eb60b3900cef8 100644
--- a/Marlin/src/sd/SdFatUtil.h
+++ b/Marlin/src/sd/SdFatUtil.h
@@ -26,8 +26,8 @@
*
* This file is part of the Arduino Sd2Card Library
*/
-#ifndef SDFATUTIL_H
-#define SDFATUTIL_H
+#ifndef _SDFATUTIL_H_
+#define _SDFATUTIL_H_
#include <string.h>
@@ -50,4 +50,4 @@ namespace SdFatUtil {
using namespace SdFatUtil; // NOLINT
-#endif // SDFATUTIL_H
+#endif // _SDFATUTIL_H_
diff --git a/Marlin/src/sd/SdFile.cpp b/Marlin/src/sd/SdFile.cpp
index 0b6147f241c556a561b41de67cf931f143c424d5..18b032400125c116b920f9e9b92dfe173973be94 100644
--- a/Marlin/src/sd/SdFile.cpp
+++ b/Marlin/src/sd/SdFile.cpp
@@ -33,17 +33,18 @@
#include "SdFile.h"
-/** Create a file object and open it in the current working directory.
+/**
+ * Create a file object and open it in the current working directory.
*
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
*
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
* OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t).
*/
-SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) {
-}
-//------------------------------------------------------------------------------
-/** Write data to an open file.
+SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) { }
+
+/**
+ * Write data to an open file.
*
* \note Data is moved to the cache but may not be written to the
* storage device until sync() is called.
@@ -58,41 +59,37 @@ SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) {
* for a read-only file, device is full, a corrupt file system or an I/O error.
*
*/
-int16_t SdFile::write(const void* buf, uint16_t nbyte) {
- return SdBaseFile::write(buf, nbyte);
-}
-//------------------------------------------------------------------------------
-/** Write a byte to a file. Required by the Arduino Print class.
+int16_t SdFile::write(const void* buf, uint16_t nbyte) { return SdBaseFile::write(buf, nbyte); }
+
+/**
+ * Write a byte to a file. Required by the Arduino Print class.
* \param[in] b the byte to be written.
* Use writeError to check for errors.
*/
#if ARDUINO >= 100
- size_t SdFile::write(uint8_t b) {
- return SdBaseFile::write(&b, 1);
- }
+ size_t SdFile::write(uint8_t b) { return SdBaseFile::write(&b, 1); }
#else
- void SdFile::write(uint8_t b) {
- SdBaseFile::write(&b, 1);
- }
+ void SdFile::write(uint8_t b) { SdBaseFile::write(&b, 1); }
#endif
-//------------------------------------------------------------------------------
-/** Write a string to a file. Used by the Arduino Print class.
+
+/**
+ * Write a string to a file. Used by the Arduino Print class.
* \param[in] str Pointer to the string.
* Use writeError to check for errors.
*/
-void SdFile::write(const char* str) {
- SdBaseFile::write(str, strlen(str));
-}
-//------------------------------------------------------------------------------
-/** Write a PROGMEM string to a file.
+void SdFile::write(const char* str) { SdBaseFile::write(str, strlen(str)); }
+
+/**
+ * Write a PROGMEM string to a file.
* \param[in] str Pointer to the PROGMEM string.
* Use writeError to check for errors.
*/
void SdFile::write_P(PGM_P str) {
for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c);
}
-//------------------------------------------------------------------------------
-/** Write a PROGMEM string followed by CR/LF to a file.
+
+/**
+ * Write a PROGMEM string followed by CR/LF to a file.
* \param[in] str Pointer to the PROGMEM string.
* Use writeError to check for errors.
*/
@@ -101,5 +98,4 @@ void SdFile::writeln_P(PGM_P str) {
write_P(PSTR("\r\n"));
}
-
-#endif
+#endif // SDSUPPORT
diff --git a/Marlin/src/sd/SdFile.h b/Marlin/src/sd/SdFile.h
index e2c2e5b0126d73190d88b3a6e04d5832edcf6a6d..dd250110a10727d83ce69d3b70db95e606668ecf 100644
--- a/Marlin/src/sd/SdFile.h
+++ b/Marlin/src/sd/SdFile.h
@@ -20,27 +20,25 @@
*
*/
+/**
+ * \file
+ * \brief SdFile class
+ */
+
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
-
-/**
- * \file
- * \brief SdFile class
- */
-
-#ifndef SDFILE_H
-#define SDFILE_H
+#ifndef _SDFILE_H_
+#define _SDFILE_H_
#include "SdBaseFile.h"
#include <stdint.h>
#include <string.h>
-//------------------------------------------------------------------------------
/**
* \class SdFile
* \brief SdBaseFile with Print.
@@ -61,4 +59,4 @@ class SdFile : public SdBaseFile/*, public Print*/ {
void writeln_P(PGM_P str);
};
-#endif // SDFILE_H
+#endif // _SDFILE_H_
diff --git a/Marlin/src/sd/SdInfo.h b/Marlin/src/sd/SdInfo.h
index 26db00c9a4cbc35a7f9e1888b13eb7d9a8e6f340..9fe121f16825d811f4ff8522725fbe10ec2dceb6 100644
--- a/Marlin/src/sd/SdInfo.h
+++ b/Marlin/src/sd/SdInfo.h
@@ -26,8 +26,8 @@
*
* This file is part of the Arduino Sd2Card Library
*/
-#ifndef SDINFO_H
-#define SDINFO_H
+#ifndef _SDINFO_H_
+#define _SDINFO_H_
#include <stdint.h>
@@ -41,46 +41,26 @@
// May 18, 2010
//
// http://www.sdcard.org/developers/tech/sdcard/pls/simplified_specs
-//------------------------------------------------------------------------------
+
// SD card commands
-/** GO_IDLE_STATE - init card in spi mode if CS low */
-uint8_t const CMD0 = 0x00;
-/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
-uint8_t const CMD8 = 0x08;
-/** SEND_CSD - read the Card Specific Data (CSD register) */
-uint8_t const CMD9 = 0x09;
-/** SEND_CID - read the card identification information (CID register) */
-uint8_t const CMD10 = 0x0A;
-/** STOP_TRANSMISSION - end multiple block read sequence */
-uint8_t const CMD12 = 0x0C;
-/** SEND_STATUS - read the card status register */
-uint8_t const CMD13 = 0x0D;
-/** READ_SINGLE_BLOCK - read a single data block from the card */
-uint8_t const CMD17 = 0x11;
-/** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */
-uint8_t const CMD18 = 0x12;
-/** WRITE_BLOCK - write a single data block to the card */
-uint8_t const CMD24 = 0x18;
-/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */
-uint8_t const CMD25 = 0x19;
-/** ERASE_WR_BLK_START - sets the address of the first block to be erased */
-uint8_t const CMD32 = 0x20;
-/** ERASE_WR_BLK_END - sets the address of the last block of the continuous
- range to be erased*/
-uint8_t const CMD33 = 0x21;
-/** ERASE - erase all previously selected blocks */
-uint8_t const CMD38 = 0x26;
-/** APP_CMD - escape for application specific command */
-uint8_t const CMD55 = 0x37;
-/** READ_OCR - read the OCR register of a card */
-uint8_t const CMD58 = 0x3A;
-/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be
- pre-erased before writing */
-uint8_t const ACMD23 = 0x17;
-/** SD_SEND_OP_COMD - Sends host capacity support information and
- activates the card's initialization process */
-uint8_t const ACMD41 = 0x29;
-//------------------------------------------------------------------------------
+uint8_t const CMD0 = 0x00, // GO_IDLE_STATE - init card in spi mode if CS low
+ CMD8 = 0x08, // SEND_IF_COND - verify SD Memory Card interface operating condition
+ CMD9 = 0x09, // SEND_CSD - read the Card Specific Data (CSD register)
+ CMD10 = 0x0A, // SEND_CID - read the card identification information (CID register)
+ CMD12 = 0x0C, // STOP_TRANSMISSION - end multiple block read sequence
+ CMD13 = 0x0D, // SEND_STATUS - read the card status register
+ CMD17 = 0x11, // READ_SINGLE_BLOCK - read a single data block from the card
+ CMD18 = 0x12, // READ_MULTIPLE_BLOCK - read a multiple data blocks from the card
+ CMD24 = 0x18, // WRITE_BLOCK - write a single data block to the card
+ CMD25 = 0x19, // WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION
+ CMD32 = 0x20, // ERASE_WR_BLK_START - sets the address of the first block to be erased
+ CMD33 = 0x21, // ERASE_WR_BLK_END - sets the address of the last block of the continuous range to be erased*/
+ CMD38 = 0x26, // ERASE - erase all previously selected blocks */
+ CMD55 = 0x37, // APP_CMD - escape for application specific command */
+ CMD58 = 0x3A, // READ_OCR - read the OCR register of a card */
+ ACMD23 = 0x17, // SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be pre-erased before writing */
+ ACMD41 = 0x29; // SD_SEND_OP_COMD - Sends host capacity support information and activates the card's initialization process */
+
/** status for card in the ready state */
uint8_t const R1_READY_STATE = 0x00;
/** status for card in the idle state */
@@ -97,7 +77,7 @@ uint8_t const WRITE_MULTIPLE_TOKEN = 0xFC;
uint8_t const DATA_RES_MASK = 0x1F;
/** write data accepted token */
uint8_t const DATA_RES_ACCEPTED = 0x05;
-//------------------------------------------------------------------------------
+
/** Card IDentification (CID) register */
typedef struct CID {
// byte 0
@@ -133,7 +113,7 @@ typedef struct CID {
/** CRC7 checksum */
unsigned char crc : 7;
} cid_t;
-//------------------------------------------------------------------------------
+
/** CSD for version 1.00 cards */
typedef struct CSDV1 {
// byte 0
@@ -195,7 +175,7 @@ typedef struct CSDV1 {
unsigned char always1 : 1;
unsigned char crc : 7;
} csd1_t;
-//------------------------------------------------------------------------------
+
/** CSD for version 2.00 cards */
typedef struct CSDV2 {
// byte 0
@@ -277,11 +257,11 @@ typedef struct CSDV2 {
/** checksum */
unsigned char crc : 7;
} csd2_t;
-//------------------------------------------------------------------------------
+
/** union of old and new style CSD register */
union csd_t {
csd1_t v1;
csd2_t v2;
};
-#endif // SDINFO_H
+#endif // _SDINFO_H_
diff --git a/Marlin/src/sd/SdVolume.cpp b/Marlin/src/sd/SdVolume.cpp
index 710b67cfffba8c77ba3ba6ba70c74a19a0f70234..f4d562bb2de31b3910457e91c304e0d7508abc3e 100644
--- a/Marlin/src/sd/SdVolume.cpp
+++ b/Marlin/src/sd/SdVolume.cpp
@@ -35,7 +35,6 @@
#include "../Marlin.h"
-//------------------------------------------------------------------------------
#if !USE_MULTIPLE_CARDS
// raw block cache
uint32_t SdVolume::cacheBlockNumber_; // current block number
@@ -44,7 +43,7 @@
bool SdVolume::cacheDirty_; // cacheFlush() will write block if true
uint32_t SdVolume::cacheMirrorBlock_; // mirror block for second FAT
#endif // USE_MULTIPLE_CARDS
-//------------------------------------------------------------------------------
+
// find a contiguous group of clusters
bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
// start of group
@@ -78,14 +77,14 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
// search the FAT for free clusters
for (uint32_t n = 0;; n++, endCluster++) {
// can't find space checked all clusters
- if (n >= clusterCount_) goto FAIL;
+ if (n >= clusterCount_) return false;
// past end - start from beginning of FAT
if (endCluster > fatEnd) {
bgnCluster = endCluster = 2;
}
uint32_t f;
- if (!fatGet(endCluster, &f)) goto FAIL;
+ if (!fatGet(endCluster, &f)) return false;
if (f != 0) {
// cluster in use try next cluster as bgnCluster
@@ -97,16 +96,16 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
}
}
// mark end of chain
- if (!fatPutEOC(endCluster)) goto FAIL;
+ if (!fatPutEOC(endCluster)) return false;
// link clusters
while (endCluster > bgnCluster) {
- if (!fatPut(endCluster - 1, endCluster)) goto FAIL;
+ if (!fatPut(endCluster - 1, endCluster)) return false;
endCluster--;
}
if (*curCluster != 0) {
// connect chains
- if (!fatPut(*curCluster, bgnCluster)) goto FAIL;
+ if (!fatPut(*curCluster, bgnCluster)) return false;
}
// return first cluster number to caller
*curCluster = bgnCluster;
@@ -115,111 +114,94 @@ bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
if (setStart) allocSearchStart_ = bgnCluster + 1;
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
bool SdVolume::cacheFlush() {
if (cacheDirty_) {
- if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
- goto FAIL;
- }
+ if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data))
+ return false;
+
// mirror FAT tables
if (cacheMirrorBlock_) {
- if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
- goto FAIL;
- }
+ if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data))
+ return false;
cacheMirrorBlock_ = 0;
}
cacheDirty_ = 0;
}
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
if (cacheBlockNumber_ != blockNumber) {
- if (!cacheFlush()) goto FAIL;
- if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) goto FAIL;
+ if (!cacheFlush()) return false;
+ if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false;
cacheBlockNumber_ = blockNumber;
}
if (dirty) cacheDirty_ = true;
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
// return the size in bytes of a cluster chain
bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
uint32_t s = 0;
do {
- if (!fatGet(cluster, &cluster)) goto FAIL;
+ if (!fatGet(cluster, &cluster)) return false;
s += 512UL << clusterSizeShift_;
} while (!isEOC(cluster));
*size = s;
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
// Fetch a FAT entry
bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
uint32_t lba;
- if (cluster > (clusterCount_ + 1)) goto FAIL;
+ if (cluster > (clusterCount_ + 1)) return false;
if (FAT12_SUPPORT && fatType_ == 12) {
uint16_t index = cluster;
index += index >> 1;
lba = fatStartBlock_ + (index >> 9);
- if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto FAIL;
+ if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
index &= 0x1FF;
uint16_t tmp = cacheBuffer_.data[index];
index++;
if (index == 512) {
- if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) goto FAIL;
+ if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) return false;
index = 0;
}
tmp |= cacheBuffer_.data[index] << 8;
*value = cluster & 1 ? tmp >> 4 : tmp & 0xFFF;
return true;
}
- if (fatType_ == 16) {
+
+ if (fatType_ == 16)
lba = fatStartBlock_ + (cluster >> 8);
- }
- else if (fatType_ == 32) {
+ else if (fatType_ == 32)
lba = fatStartBlock_ + (cluster >> 7);
- }
- else {
- goto FAIL;
- }
- if (lba != cacheBlockNumber_) {
- if (!cacheRawBlock(lba, CACHE_FOR_READ)) goto FAIL;
- }
- if (fatType_ == 16) {
- *value = cacheBuffer_.fat16[cluster & 0xFF];
- }
- else {
- *value = cacheBuffer_.fat32[cluster & 0x7F] & FAT32MASK;
- }
+ else
+ return false;
+
+ if (lba != cacheBlockNumber_ && !cacheRawBlock(lba, CACHE_FOR_READ))
+ return false;
+
+ *value = (fatType_ == 16) ? cacheBuffer_.fat16[cluster & 0xFF] : (cacheBuffer_.fat32[cluster & 0x7F] & FAT32MASK);
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
// Store a FAT entry
bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
uint32_t lba;
// error if reserved cluster
- if (cluster < 2) goto FAIL;
+ if (cluster < 2) return false;
// error if not in FAT
- if (cluster > (clusterCount_ + 1)) goto FAIL;
+ if (cluster > (clusterCount_ + 1)) return false;
if (FAT12_SUPPORT && fatType_ == 12) {
uint16_t index = cluster;
index += index >> 1;
lba = fatStartBlock_ + (index >> 9);
- if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto FAIL;
+ if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) return false;
// mirror second FAT
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
index &= 0x1FF;
@@ -232,7 +214,7 @@ bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
if (index == 512) {
lba++;
index = 0;
- if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto FAIL;
+ if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) return false;
// mirror second FAT
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
}
@@ -243,51 +225,45 @@ bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
cacheBuffer_.data[index] = tmp;
return true;
}
- if (fatType_ == 16) {
+
+ if (fatType_ == 16)
lba = fatStartBlock_ + (cluster >> 8);
- }
- else if (fatType_ == 32) {
+ else if (fatType_ == 32)
lba = fatStartBlock_ + (cluster >> 7);
- }
- else {
- goto FAIL;
- }
- if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) goto FAIL;
+ else
+ return false;
+
+ if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) return false;
+
// store entry
- if (fatType_ == 16) {
+ if (fatType_ == 16)
cacheBuffer_.fat16[cluster & 0xFF] = value;
- }
- else {
+ else
cacheBuffer_.fat32[cluster & 0x7F] = value;
- }
+
// mirror second FAT
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
// free a cluster chain
bool SdVolume::freeChain(uint32_t cluster) {
- uint32_t next;
-
// clear free cluster location
allocSearchStart_ = 2;
do {
- if (!fatGet(cluster, &next)) goto FAIL;
+ uint32_t next;
+ if (!fatGet(cluster, &next)) return false;
// free cluster
- if (!fatPut(cluster, 0)) goto FAIL;
+ if (!fatPut(cluster, 0)) return false;
cluster = next;
} while (!isEOC(cluster));
return true;
- FAIL:
- return false;
}
-//------------------------------------------------------------------------------
+
/** Volume free space in clusters.
*
* \return Count of free clusters for success or -1 if an error occurs.
@@ -297,34 +273,28 @@ int32_t SdVolume::freeClusterCount() {
uint16_t n;
uint32_t todo = clusterCount_ + 2;
- if (fatType_ == 16) {
+ if (fatType_ == 16)
n = 256;
- }
- else if (fatType_ == 32) {
+ else if (fatType_ == 32)
n = 128;
- }
- else {
- // put FAT12 here
+ else // put FAT12 here
return -1;
- }
for (uint32_t lba = fatStartBlock_; todo; todo -= n, lba++) {
if (!cacheRawBlock(lba, CACHE_FOR_READ)) return -1;
NOMORE(n, todo);
if (fatType_ == 16) {
- for (uint16_t i = 0; i < n; i++) {
+ for (uint16_t i = 0; i < n; i++)
if (cacheBuffer_.fat16[i] == 0) free++;
- }
}
else {
- for (uint16_t i = 0; i < n; i++) {
+ for (uint16_t i = 0; i < n; i++)
if (cacheBuffer_.fat32[i] == 0) free++;
- }
}
}
return free;
}
-//------------------------------------------------------------------------------
+
/** Initialize a FAT volume.
*
* \param[in] dev The SD card where the volume is located.
@@ -334,14 +304,12 @@ int32_t SdVolume::freeClusterCount() {
* a MBR, Master Boot Record, or zero if the device is formatted as
* a super floppy with the FAT boot sector in block zero.
*
- * \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
+ * \return true for success, false for failure.
+ * Reasons for failure include not finding a valid partition, not finding a valid
* FAT file system in the specified partition or an I/O error.
*/
bool SdVolume::init(Sd2Card* dev, uint8_t part) {
- uint32_t totalBlocks;
- uint32_t volumeStartBlock = 0;
+ uint32_t totalBlocks, volumeStartBlock = 0;
fat32_boot_t* fbs;
sdCard_ = dev;
@@ -354,25 +322,21 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
// if part == 0 assume super floppy with FAT boot sector in block zero
// if part > 0 assume mbr volume with partition table
if (part) {
- if (part > 4)goto FAIL;
- if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto FAIL;
+ if (part > 4) return false;
+ if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
part_t* p = &cacheBuffer_.mbr.part[part - 1];
- if ((p->boot & 0x7F) != 0 ||
- p->totalSectors < 100 ||
- p->firstSector == 0) {
- // not a valid partition
- goto FAIL;
- }
+ if ((p->boot & 0x7F) != 0 || p->totalSectors < 100 || p->firstSector == 0)
+ return false; // not a valid partition
volumeStartBlock = p->firstSector;
}
- if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) goto FAIL;
+ if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
fbs = &cacheBuffer_.fbs32;
if (fbs->bytesPerSector != 512 ||
fbs->fatCount == 0 ||
fbs->reservedSectorCount == 0 ||
fbs->sectorsPerCluster == 0) {
// not valid FAT volume
- goto FAIL;
+ return false;
}
fatCount_ = fbs->fatCount;
blocksPerCluster_ = fbs->sectorsPerCluster;
@@ -380,7 +344,7 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
clusterSizeShift_ = 0;
while (blocksPerCluster_ != _BV(clusterSizeShift_)) {
// error if not power of 2
- if (clusterSizeShift_++ > 7) goto FAIL;
+ if (clusterSizeShift_++ > 7) return false;
}
blocksPerFat_ = fbs->sectorsPerFat16 ?
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
@@ -409,18 +373,15 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
// FAT type is determined by cluster count
if (clusterCount_ < 4085) {
fatType_ = 12;
- if (!FAT12_SUPPORT) goto FAIL;
+ if (!FAT12_SUPPORT) return false;
}
- else if (clusterCount_ < 65525) {
+ else if (clusterCount_ < 65525)
fatType_ = 16;
- }
else {
rootDirStart_ = fbs->fat32RootCluster;
fatType_ = 32;
}
return true;
- FAIL:
- return false;
}
#endif // SDSUPPORT
diff --git a/Marlin/src/sd/SdVolume.h b/Marlin/src/sd/SdVolume.h
index 4693e2dfaf8d0f38970123eade8c3992ba82b047..9bb1c7db575346ed1e67cfc7840a53798769228d 100644
--- a/Marlin/src/sd/SdVolume.h
+++ b/Marlin/src/sd/SdVolume.h
@@ -20,19 +20,20 @@
*
*/
+/**
+ * \file
+ * \brief SdVolume class
+ */
+
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
-#ifndef SDVOLUME_H
-#define SDVOLUME_H
+#ifndef _SDVOLUME_H_
+#define _SDVOLUME_H_
-/**
- * \file
- * \brief SdVolume class
- */
#include "SdFatConfig.h"
#include "Sd2Card.h"
#include "SdFatStructs.h"
@@ -45,33 +46,26 @@
* \brief Cache for an SD data block
*/
union cache_t {
- /** Used to access cached file data blocks. */
- uint8_t data[512];
- /** Used to access cached FAT16 entries. */
- uint16_t fat16[256];
- /** Used to access cached FAT32 entries. */
- uint32_t fat32[128];
- /** Used to access cached directory entries. */
- dir_t dir[16];
- /** Used to access a cached Master Boot Record. */
- mbr_t mbr;
- /** Used to access to a cached FAT boot sector. */
- fat_boot_t fbs;
- /** Used to access to a cached FAT32 boot sector. */
- fat32_boot_t fbs32;
- /** Used to access to a cached FAT32 FSINFO sector. */
- fat32_fsinfo_t fsinfo;
+ uint8_t data[512]; // Used to access cached file data blocks.
+ uint16_t fat16[256]; // Used to access cached FAT16 entries.
+ uint32_t fat32[128]; // Used to access cached FAT32 entries.
+ dir_t dir[16]; // Used to access cached directory entries.
+ mbr_t mbr; // Used to access a cached Master Boot Record.
+ fat_boot_t fbs; // Used to access to a cached FAT boot sector.
+ fat32_boot_t fbs32; // Used to access to a cached FAT32 boot sector.
+ fat32_fsinfo_t fsinfo; // Used to access to a cached FAT32 FSINFO sector.
};
-//------------------------------------------------------------------------------
+
/**
* \class SdVolume
* \brief Access FAT16 and FAT32 volumes on SD and SDHC cards.
*/
class SdVolume {
public:
- /** Create an instance of SdVolume */
+ // Create an instance of SdVolume
SdVolume() : fatType_(0) {}
- /** Clear the cache and returns a pointer to the cache. Used by the WaveRP
+ /**
+ * Clear the cache and returns a pointer to the cache. Used by the WaveRP
* recorder to do raw write to the SD card. Not for normal apps.
* \return A pointer to the cache buffer or zero if an error occurs.
*/
@@ -80,54 +74,53 @@ class SdVolume {
cacheBlockNumber_ = 0xFFFFFFFF;
return &cacheBuffer_;
}
- /** Initialize a FAT volume. Try partition one first then try super
+
+ /**
+ * Initialize a FAT volume. Try partition one first then try super
* floppy format.
*
* \param[in] dev The Sd2Card 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.
+ * \return true for success, false for failure.
+ * Reasons for failure include not finding a valid partition, not finding
+ * a valid FAT file system or an I/O error.
*/
- bool init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);}
+ bool init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0); }
bool init(Sd2Card* dev, uint8_t part);
// inline functions that return volume info
- /** \return The volume's cluster size in blocks. */
- uint8_t blocksPerCluster() const {return blocksPerCluster_;}
- /** \return The number of blocks in one FAT. */
- uint32_t blocksPerFat() const {return blocksPerFat_;}
- /** \return The total number of clusters in the volume. */
- uint32_t clusterCount() const {return clusterCount_;}
- /** \return The shift count required to multiply by blocksPerCluster. */
- uint8_t clusterSizeShift() const {return clusterSizeShift_;}
- /** \return The logical block number for the start of file data. */
- uint32_t dataStartBlock() const {return dataStartBlock_;}
- /** \return The number of FAT structures on the volume. */
- uint8_t fatCount() const {return fatCount_;}
- /** \return The logical block number for the start of the first FAT. */
- uint32_t fatStartBlock() const {return fatStartBlock_;}
- /** \return The FAT type of the volume. Values are 12, 16 or 32. */
- uint8_t fatType() const {return fatType_;}
+ uint8_t blocksPerCluster() const { return blocksPerCluster_; } //> \return The volume's cluster size in blocks.
+ uint32_t blocksPerFat() const { return blocksPerFat_; } //> \return The number of blocks in one FAT.
+ uint32_t clusterCount() const { return clusterCount_; } //> \return The total number of clusters in the volume.
+ uint8_t clusterSizeShift() const { return clusterSizeShift_; } //> \return The shift count required to multiply by blocksPerCluster.
+ uint32_t dataStartBlock() const { return dataStartBlock_; } //> \return The logical block number for the start of file data.
+ uint8_t fatCount() const { return fatCount_; } //> \return The number of FAT structures on the volume.
+ uint32_t fatStartBlock() const { return fatStartBlock_; } //> \return The logical block number for the start of the first FAT.
+ uint8_t fatType() const { return fatType_; } //> \return The FAT type of the volume. Values are 12, 16 or 32.
int32_t freeClusterCount();
- /** \return The number of entries in the root directory for FAT16 volumes. */
- uint32_t rootDirEntryCount() const {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() const {return rootDirStart_;}
- /** Sd2Card object for this volume
+ uint32_t rootDirEntryCount() const { return rootDirEntryCount_; } /** \return The number of entries in the root directory for FAT16 volumes. */
+
+ /**
+ * \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() const { return rootDirStart_; }
+
+ /**
+ * Sd2Card object for this volume
* \return pointer to Sd2Card object.
*/
- Sd2Card* sdCard() {return sdCard_;}
- /** Debug access to FAT table
+ Sd2Card* sdCard() { return sdCard_; }
+
+ /**
+ * Debug access to FAT table
*
* \param[in] n cluster number.
* \param[out] v value of entry
* \return true for success or false for failure
*/
- bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);}
- //------------------------------------------------------------------------------
+ bool dbgFat(uint32_t n, uint32_t* v) { return fatGet(n, v); }
+
private:
// Allow SdBaseFile access to SdVolume private data.
friend class SdBaseFile;
@@ -143,13 +136,14 @@ class SdVolume {
Sd2Card* sdCard_; // Sd2Card object for cache
bool cacheDirty_; // cacheFlush() will write block if true
uint32_t cacheMirrorBlock_; // block number for mirror FAT
- #else // USE_MULTIPLE_CARDS
+ #else
static cache_t cacheBuffer_; // 512 byte cache for device blocks
static uint32_t cacheBlockNumber_; // Logical number of block in the cache
static Sd2Card* sdCard_; // Sd2Card object for cache
static bool cacheDirty_; // cacheFlush() will write block if true
static uint32_t cacheMirrorBlock_; // block number for mirror FAT
- #endif // USE_MULTIPLE_CARDS
+ #endif
+
uint32_t allocSearchStart_; // start cluster for alloc search
uint8_t blocksPerCluster_; // cluster size in blocks
uint32_t blocksPerFat_; // FAT size in blocks
@@ -161,68 +155,59 @@ class SdVolume {
uint8_t fatType_; // volume type (12, 16, OR 32)
uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir
uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32
- //----------------------------------------------------------------------------
+
bool allocContiguous(uint32_t count, uint32_t* curCluster);
- uint8_t blockOfCluster(uint32_t position) const {
- return (position >> 9) & (blocksPerCluster_ - 1);
- }
- uint32_t clusterStartBlock(uint32_t cluster) const {
- return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);
- }
- uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
- return clusterStartBlock(cluster) + blockOfCluster(position);
- }
- cache_t* cache() {return &cacheBuffer_;}
- uint32_t cacheBlockNumber() {return cacheBlockNumber_;}
+ uint8_t blockOfCluster(uint32_t position) const { return (position >> 9) & (blocksPerCluster_ - 1); }
+ uint32_t clusterStartBlock(uint32_t cluster) const { return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_); }
+ uint32_t blockNumber(uint32_t cluster, uint32_t position) const { return clusterStartBlock(cluster) + blockOfCluster(position); }
+
+ cache_t* cache() { return &cacheBuffer_; }
+ uint32_t cacheBlockNumber() const { return cacheBlockNumber_; }
+
#if USE_MULTIPLE_CARDS
bool cacheFlush();
bool cacheRawBlock(uint32_t blockNumber, bool dirty);
- #else // USE_MULTIPLE_CARDS
+ #else
static bool cacheFlush();
static bool cacheRawBlock(uint32_t blockNumber, bool dirty);
- #endif // USE_MULTIPLE_CARDS
+ #endif
+
// used by SdBaseFile write to assign cache to SD location
void cacheSetBlockNumber(uint32_t blockNumber, bool dirty) {
cacheDirty_ = dirty;
cacheBlockNumber_ = blockNumber;
}
- void cacheSetDirty() {cacheDirty_ |= CACHE_FOR_WRITE;}
+ void cacheSetDirty() { cacheDirty_ |= CACHE_FOR_WRITE; }
bool chainSize(uint32_t beginCluster, uint32_t* size);
bool fatGet(uint32_t cluster, uint32_t* value);
bool fatPut(uint32_t cluster, uint32_t value);
- bool fatPutEOC(uint32_t cluster) {
- return fatPut(cluster, 0x0FFFFFFF);
- }
+ bool fatPutEOC(uint32_t cluster) { return fatPut(cluster, 0x0FFFFFFF); }
bool freeChain(uint32_t cluster);
bool isEOC(uint32_t cluster) const {
if (FAT12_SUPPORT && fatType_ == 12) return cluster >= FAT12EOC_MIN;
if (fatType_ == 16) return cluster >= FAT16EOC_MIN;
return cluster >= FAT32EOC_MIN;
}
- bool readBlock(uint32_t block, uint8_t* dst) {
- return sdCard_->readBlock(block, dst);
- }
- bool writeBlock(uint32_t block, const uint8_t* dst) {
- return sdCard_->writeBlock(block, dst);
- }
- //------------------------------------------------------------------------------
- // Deprecated functions - suppress cpplint warnings with NOLINT comment
- #if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN)
+ bool readBlock(uint32_t block, uint8_t* dst) { return sdCard_->readBlock(block, dst); }
+ bool writeBlock(uint32_t block, const uint8_t* dst) { return sdCard_->writeBlock(block, dst); }
+
+ // Deprecated functions
+ #if ALLOW_DEPRECATED_FUNCTIONS
public:
- /** \deprecated Use: bool SdVolume::init(Sd2Card* dev);
+ /**
+ * \deprecated Use: bool SdVolume::init(Sd2Card* dev);
* \param[in] dev The SD card where the volume is located.
* \return true for success or false for failure.
*/
- bool init(Sd2Card& dev) {return init(&dev);} // NOLINT
- /** \deprecated Use: bool SdVolume::init(Sd2Card* dev, uint8_t vol);
+ bool init(Sd2Card& dev) { return init(&dev); }
+ /**
+ * \deprecated Use: bool SdVolume::init(Sd2Card* dev, uint8_t vol);
* \param[in] dev The SD card where the volume is located.
* \param[in] part The partition to be used.
* \return true for success or false for failure.
*/
- bool init(Sd2Card& dev, uint8_t part) { // NOLINT
- return init(&dev, part);
- }
+ bool init(Sd2Card& dev, uint8_t part) { return init(&dev, part); }
#endif // ALLOW_DEPRECATED_FUNCTIONS
};
-#endif // SDVOLUME_H
+#endif // _SDVOLUME_H_
diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp
index 88d215ed8f8fd28a942e7b923cab0e38dbeb76b3..663b788321fdd1fff7781d0e0b8fe02987843feb 100644
--- a/Marlin/src/sd/cardreader.cpp
+++ b/Marlin/src/sd/cardreader.cpp
@@ -49,8 +49,9 @@ CardReader::CardReader() {
sdprinting = cardOK = saving = logging = false;
filesize = 0;
sdpos = 0;
- workDirDepth = 0;
file_subcall_ctr = 0;
+
+ workDirDepth = 0;
ZERO(workDirParents);
autostart_stilltocheck = true; //the SD start is delayed, because otherwise the serial cannot answer fast enough to make contact with the host software.
@@ -263,16 +264,7 @@ void CardReader::initsd() {
SERIAL_ECHO_START();
SERIAL_ECHOLNPGM(MSG_SD_CARD_OK);
}
- workDir = root;
- curDir = &root;
- #if ENABLED(SDCARD_SORT_ALPHA)
- presort();
- #endif
- /**
- if (!workDir.openRoot(&volume)) {
- SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
- }
- */
+ setroot();
}
void CardReader::setroot() {
@@ -318,26 +310,33 @@ void CardReader::openLogFile(char* name) {
openFile(name, false);
}
+void appendAtom(SdFile &file, char *& dst, uint8_t &cnt) {
+ file.getFilename(dst);
+ while (*dst && cnt < MAXPATHNAMELENGTH) { dst++; cnt++; }
+ if (cnt < MAXPATHNAMELENGTH) { *dst = '/'; dst++; cnt++; }
+}
+
void CardReader::getAbsFilename(char *t) {
- uint8_t cnt = 0;
- *t = '/'; t++; cnt++;
- for (uint8_t i = 0; i < workDirDepth; i++) {
- workDirParents[i].getFilename(t); //SDBaseFile.getfilename!
- while (*t && cnt < MAXPATHNAMELENGTH) { t++; cnt++; } //crawl counter forward.
+ *t++ = '/'; // Root folder
+ uint8_t cnt = 1;
+
+ for (uint8_t i = 0; i < workDirDepth; i++) // Loop to current work dir
+ appendAtom(workDirParents[i], t, cnt);
+
+ if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH)) {
+ appendAtom(file, t, cnt);
+ --t;
}
- if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH))
- file.getFilename(t);
- else
- t[0] = 0;
+ *t = '\0';
}
-void CardReader::openFile(char* name, bool read, bool push_current/*=false*/) {
+void CardReader::openFile(char* name, const bool read, const bool subcall/*=false*/) {
if (!cardOK) return;
uint8_t doing = 0;
- if (isFileOpen()) { //replacing current file by new file, or subfile call
- if (push_current) {
+ if (isFileOpen()) { // Replacing current file or doing a subroutine
+ if (subcall) {
if (file_subcall_ctr > SD_PROCEDURE_DEPTH - 1) {
SERIAL_ERROR_START();
SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
@@ -346,21 +345,24 @@ void CardReader::openFile(char* name, bool read, bool push_current/*=false*/) {
return;
}
- // Store current filename and position
+ // Store current filename (based on workDirParents) and position
getAbsFilename(proc_filenames[file_subcall_ctr]);
+ filespos[file_subcall_ctr] = sdpos;
SERIAL_ECHO_START();
SERIAL_ECHOPAIR("SUBROUTINE CALL target:\"", name);
SERIAL_ECHOPAIR("\" parent:\"", proc_filenames[file_subcall_ctr]);
SERIAL_ECHOLNPAIR("\" pos", sdpos);
- filespos[file_subcall_ctr] = sdpos;
file_subcall_ctr++;
}
- else {
+ else
doing = 1;
- }
}
- else { // Opening fresh file
+ else if (subcall) { // Returning from a subcall?
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPGM("END SUBROUTINE");
+ }
+ else { // Opening fresh file
doing = 2;
file_subcall_ctr = 0; // Reset procedure depth in case user cancels print while in procedure
}
@@ -368,7 +370,7 @@ void CardReader::openFile(char* name, bool read, bool push_current/*=false*/) {
if (doing) {
SERIAL_ECHO_START();
SERIAL_ECHOPGM("Now ");
- SERIAL_ECHO(doing == 1 ? "doing" : "fresh");
+ serialprintPGM(doing == 1 ? PSTR("doing") : PSTR("fresh"));
SERIAL_ECHOLNPAIR(" file: ", name);
}
@@ -388,8 +390,7 @@ void CardReader::openFile(char* name, bool read, bool push_current/*=false*/) {
if (dirname_end != NULL && dirname_end > dirname_start) {
char subdirname[FILENAME_LENGTH];
strncpy(subdirname, dirname_start, dirname_end - dirname_start);
- subdirname[dirname_end - dirname_start] = 0;
- SERIAL_ECHOLN(subdirname);
+ subdirname[dirname_end - dirname_start] = '\0';
if (!myDir.open(curDir, subdirname, O_READ)) {
SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
SERIAL_PROTOCOL(subdirname);
@@ -411,17 +412,15 @@ void CardReader::openFile(char* name, bool read, bool push_current/*=false*/) {
}
}
}
- else { //relative path
- curDir = &workDir;
- }
+ else
+ curDir = &workDir; // Relative paths start in current directory
if (read) {
if (file.open(curDir, fname, O_READ)) {
filesize = file.fileSize();
+ sdpos = 0;
SERIAL_PROTOCOLPAIR(MSG_SD_FILE_OPENED, fname);
SERIAL_PROTOCOLLNPAIR(MSG_SD_SIZE, filesize);
- sdpos = 0;
-
SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED);
getfilename(0, fname);
lcd_setstatus(longFilename[0] ? longFilename : fname);
@@ -446,14 +445,14 @@ void CardReader::openFile(char* name, bool read, bool push_current/*=false*/) {
}
}
-void CardReader::removeFile(char* name) {
+void CardReader::removeFile(const char * const name) {
if (!cardOK) return;
stopSDPrint();
SdFile myDir;
curDir = &root;
- char *fname = name;
+ const char *fname = name;
char *dirname_start, *dirname_end;
if (name[0] == '/') {
@@ -468,29 +467,23 @@ void CardReader::removeFile(char* name) {
subdirname[dirname_end - dirname_start] = 0;
SERIAL_ECHOLN(subdirname);
if (!myDir.open(curDir, subdirname, O_READ)) {
- SERIAL_PROTOCOLPAIR("open failed, File: ", subdirname);
+ SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, subdirname);
SERIAL_PROTOCOLCHAR('.');
SERIAL_EOL();
return;
}
- else {
- //SERIAL_ECHOLNPGM("dive ok");
- }
curDir = &myDir;
dirname_start = dirname_end + 1;
}
- else { // the remainder after all /fsa/fdsa/ is the filename
+ else {
fname = dirname_start;
- //SERIAL_ECHOLNPGM("remainder");
- //SERIAL_ECHOLN(fname);
break;
}
}
}
- else { // relative path
+ else // Relative paths are rooted in the current directory
curDir = &workDir;
- }
if (file.remove(curDir, fname)) {
SERIAL_PROTOCOLPGM("File deleted:");
@@ -514,14 +507,13 @@ void CardReader::getStatus() {
SERIAL_PROTOCOLCHAR('/');
SERIAL_PROTOCOLLN(filesize);
}
- else {
+ else
SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING);
- }
}
void CardReader::write_command(char *buf) {
char* begin = buf;
- char* npos = 0;
+ char* npos = NULL;
char* end = buf + strlen(buf) - 1;
file.writeError = false;
@@ -619,20 +611,20 @@ uint16_t CardReader::getnrfilenames() {
}
void CardReader::chdir(const char * relpath) {
- SdFile newfile;
+ SdFile newDir;
SdFile *parent = &root;
if (workDir.isOpen()) parent = &workDir;
- if (!newfile.open(*parent, relpath, O_READ)) {
+ if (!newDir.open(*parent, relpath, O_READ)) {
SERIAL_ECHO_START();
SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR);
SERIAL_ECHOLN(relpath);
}
else {
+ workDir = newDir;
if (workDirDepth < MAX_DIR_DEPTH)
- workDirParents[workDirDepth++] = *parent;
- workDir = newfile;
+ workDirParents[workDirDepth++] = workDir;
#if ENABLED(SDCARD_SORT_ALPHA)
presort();
#endif
@@ -640,8 +632,8 @@ void CardReader::chdir(const char * relpath) {
}
void CardReader::updir() {
- if (workDirDepth > 0) {
- workDir = workDirParents[--workDirDepth];
+ if (workDirDepth > 0) { // At least 1 dir has been saved
+ workDir = --workDirDepth ? workDirParents[workDirDepth] : root; // Use parent, or root if none
#if ENABLED(SDCARD_SORT_ALPHA)
presort();
#endif
diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h
index 25a1daff12a38e0be5ead8a72be8d9be2ab1bdfc..5d10e34a68ab9228f78c1fea0d373a0f57267dfa 100644
--- a/Marlin/src/sd/cardreader.h
+++ b/Marlin/src/sd/cardreader.h
@@ -20,8 +20,8 @@
*
*/
-#ifndef CARDREADER_H
-#define CARDREADER_H
+#ifndef _CARDREADER_H_
+#define _CARDREADER_H_
#define MAX_DIR_DEPTH 10 // Maximum folder depth
@@ -35,13 +35,15 @@ public:
void initsd();
void write_command(char *buf);
- //files auto[0-9].g on the sd card are performed in a row
- //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
+ // Files auto[0-9].g on the sd card are performed in sequence.
+ // This is to delay autostart and hence the initialisation of
+ // the sd card to some seconds after the normal init, so the
+ // device is available soon after a reset.
void checkautostart(bool x);
- void openFile(char* name, bool read, bool push_current=false);
+ void openFile(char* name, const bool read, const bool subcall=false);
void openLogFile(char* name);
- void removeFile(char* name);
+ void removeFile(const char * const name);
void closefile(bool store_location=false);
void release();
void openAndPrintFile(const char *name);
@@ -151,8 +153,7 @@ private:
uint8_t file_subcall_ctr;
uint32_t filespos[SD_PROCEDURE_DEPTH];
char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
- uint32_t filesize;
- uint32_t sdpos;
+ uint32_t filesize, sdpos;
millis_t next_autostart_ms;
bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
@@ -188,4 +189,4 @@ private:
extern CardReader card;
-#endif // CARDREADER_H
+#endif // _CARDREADER_H_