From 129641321455de64fc2dc858a88f3a77f5443679 Mon Sep 17 00:00:00 2001
From: mcaldwelva <mcaldwelva@gmail.com>
Date: Mon, 12 Oct 2020 00:19:24 -0400
Subject: [PATCH 1/4] support extended ASCII filenames, handle hidden/system
 files

---
 src/utility/FatStructs.h | 2 +-
 src/utility/SdFat.h      | 2 +-
 src/utility/SdFile.cpp   | 8 ++++----
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/utility/FatStructs.h b/src/utility/FatStructs.h
index 84c1cc7..35789fd 100644
--- a/src/utility/FatStructs.h
+++ b/src/utility/FatStructs.h
@@ -413,6 +413,6 @@ static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
 }
 /** Directory entry is for a file or subdirectory */
 static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {
-  return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
+  return (dir->attributes & (DIR_ATT_VOLUME_ID | DIR_ATT_SYSTEM | DIR_ATT_HIDDEN)) == 0;
 }
 #endif  // FatStructs_h
diff --git a/src/utility/SdFat.h b/src/utility/SdFat.h
index 46b880b..3c1edee 100644
--- a/src/utility/SdFat.h
+++ b/src/utility/SdFat.h
@@ -437,7 +437,7 @@ class SdFile : public Print {
 
     // private data
     uint8_t   flags_;         // See above for definition of flags_ bits
-    uint8_t   type_;          // type of file see above for values
+    uint8_t   volatile type_; // type of file see above for values
     uint32_t  curCluster_;    // cluster for current file position
     uint32_t  curPosition_;   // current file position in bytes from beginning
     uint32_t  dirBlock_;      // SD block that contains directory entry for file
diff --git a/src/utility/SdFile.cpp b/src/utility/SdFile.cpp
index 18a1db6..b433fa2 100644
--- a/src/utility/SdFile.cpp
+++ b/src/utility/SdFile.cpp
@@ -303,19 +303,19 @@ uint8_t SdFile::make83Name(const char* str, uint8_t* name) {
       // illegal FAT characters
       uint8_t b;
       #if defined(__AVR__)
-      PGM_P p = PSTR("|<>^+=?/[];,*\"\\");
+      PGM_P p = PSTR("|<>:+=?/[];,*\"\\");
       while ((b = pgm_read_byte(p++))) if (b == c) {
           return false;
         }
       #elif defined(__arm__)
-      const uint8_t valid[] = "|<>^+=?/[];,*\"\\";
+      const uint8_t valid[] = "|<>:+=?/[];,*\"\\";
       const uint8_t *p = valid;
       while ((b = *p++)) if (b == c) {
           return false;
         }
       #endif
       // check size and only allow ASCII printable characters
-      if (i > n || c < 0X21 || c > 0X7E) {
+      if (i > n || c < 0x20 || c == 0x7F) {
         return false;
       }
       // only upper case allowed in 8.3 names - convert lower to upper
@@ -1041,7 +1041,7 @@ uint8_t SdFile::rmRfStar(void) {
     }
 
     // skip if part of long file name or volume label in root
-    if (!DIR_IS_FILE_OR_SUBDIR(p)) {
+    if (p->attributes & DIR_ATT_VOLUME_ID) {
       continue;
     }
 

From 16acc15aa436f09338f3bba9754ee8ec21e69902 Mon Sep 17 00:00:00 2001
From: mcaldwelva <mcaldwelva@gmail.com>
Date: Tue, 3 Nov 2020 12:13:28 -0500
Subject: [PATCH 2/4] improved support for <space> and 0xE5 in filenames

---
 src/utility/SdFile.cpp | 46 +++++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/src/utility/SdFile.cpp b/src/utility/SdFile.cpp
index b433fa2..aabbbda 100644
--- a/src/utility/SdFile.cpp
+++ b/src/utility/SdFile.cpp
@@ -203,16 +203,20 @@ uint8_t SdFile::dirEntry(dir_t* dir) {
    \param[out] name A 13 byte char array for the formatted name.
 */
 void SdFile::dirName(const dir_t& dir, char* name) {
-  uint8_t j = 0;
-  for (uint8_t i = 0; i < 11; i++) {
-    if (dir.name[i] == ' ') {
-      continue;
-    }
+  uint8_t i = 0, j = 0;
+  // unescape first character
+  if ((uint8_t) dir.name[i] == DIR_NAME_0XE5) {
+    name[j++] = 0xE5;
+    i++;
+  }
+  for (; i < 11; i++) {
     if (i == 8) {
+      while (j > 0 && name[j-1] == ' ') j--;
       name[j++] = '.';
     }
     name[j++] = dir.name[i];
   }
+  while (name[j-1] == ' ') j--;
   name[j] = 0;
 }
 //------------------------------------------------------------------------------
@@ -288,10 +292,12 @@ uint8_t SdFile::make83Name(const char* str, uint8_t* name) {
   uint8_t n = 7;  // max index for part before dot
   uint8_t i = 0;
   // blank fill name and extension
-  while (i < 11) {
-    name[i++] = ' ';
+  memset(name, ' ', 11);
+  // escape first character
+  if ((uint8_t) *str == 0xE5) {
+    name[i++] = DIR_NAME_0XE5;
+    str++;
   }
-  i = 0;
   while ((c = *str++) != '\0') {
     if (c == '.') {
       if (n == 10) {
@@ -301,16 +307,12 @@ uint8_t SdFile::make83Name(const char* str, uint8_t* name) {
       i = 8;   // place for extension
     } else {
       // illegal FAT characters
-      uint8_t b;
       #if defined(__AVR__)
-      PGM_P p = PSTR("|<>:+=?/[];,*\"\\");
-      while ((b = pgm_read_byte(p++))) if (b == c) {
+      if (strchr_P(PSTR("|<>:+=?/[];,*\"\\"), c)) {
           return false;
         }
-      #elif defined(__arm__)
-      const uint8_t valid[] = "|<>:+=?/[];,*\"\\";
-      const uint8_t *p = valid;
-      while ((b = *p++)) if (b == c) {
+      #else
+      if (strchr("|<>:+=?/[];,*\"\\", c)) {
           return false;
         }
       #endif
@@ -323,7 +325,7 @@ uint8_t SdFile::make83Name(const char* str, uint8_t* name) {
     }
   }
   // must have a file name, extension is optional
-  return name[0] != ' ';
+  return i > 0;
 }
 //------------------------------------------------------------------------------
 /** Make a new directory.
@@ -690,11 +692,13 @@ uint8_t SdFile::openRoot(SdVolume* vol) {
    \param[in] width Blank fill name if length is less than \a width.
 */
 void SdFile::printDirName(const dir_t& dir, uint8_t width) {
-  uint8_t w = 0;
-  for (uint8_t i = 0; i < 11; i++) {
-    if (dir.name[i] == ' ') {
-      continue;
-    }
+  uint8_t i = 0, w = 0;
+  // unescape first character
+  if ((uint8_t) dir.name[i] == DIR_NAME_0XE5) {
+    Serial.write(0xE5);
+    i++; w++;
+  }
+  for (; i < 11; i++) {
     if (i == 8) {
       Serial.print('.');
       w++;

From a9b2d4ba5c388449f6f2b497ac05e4421b028ba8 Mon Sep 17 00:00:00 2001
From: mcaldwelva <mcaldwelva@gmail.com>
Date: Mon, 10 May 2021 22:32:48 -0400
Subject: [PATCH 3/4] release pins/deref SPI when done

---
 src/SD.cpp              |  1 +
 src/utility/Sd2Card.cpp | 26 ++++++++++++++++++++++++++
 src/utility/Sd2Card.h   |  1 +
 3 files changed, 28 insertions(+)

diff --git a/src/SD.cpp b/src/SD.cpp
index 24fcb2e..8006f38 100644
--- a/src/SD.cpp
+++ b/src/SD.cpp
@@ -367,6 +367,7 @@ namespace SDLib {
   //call this when a card is removed. It will allow you to insert and initialise a new card.
   void SDClass::end() {
     root.close();
+    card.done();
   }
 
   // this little helper is used to traverse paths
diff --git a/src/utility/Sd2Card.cpp b/src/utility/Sd2Card.cpp
index 7cfbe73..1de0c4a 100644
--- a/src/utility/Sd2Card.cpp
+++ b/src/utility/Sd2Card.cpp
@@ -358,6 +358,32 @@ uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
   return false;
 }
 //------------------------------------------------------------------------------
+/**
+   Return initialized pins to floating and dereference SPI lib.
+*/
+void Sd2Card::done() {
+  pinMode(chipSelectPin_, INPUT);
+  digitalWrite(chipSelectPin_, LOW);
+
+  #ifndef USE_SPI_LIB
+  pinMode(SPI_MISO_PIN, INPUT);
+  digitalWrite(SPI_MISO_PIN, LOW);
+  pinMode(SPI_MOSI_PIN, INPUT);
+  digitalWrite(SPI_MOSI_PIN, LOW);
+  pinMode(SPI_SCK_PIN, INPUT);
+  digitalWrite(SPI_SCK_PIN, LOW);
+  #endif
+
+  #ifndef SOFTWARE_SPI
+  #ifndef USE_SPI_LIB
+  pinMode(SS_PIN, INPUT);
+  digitalWrite(SS_PIN, LOW);
+  #else // USE_SPI_LIB
+  SDCARD_SPI.end();
+  #endif // USE_SPI_LIB
+  #endif // SOFTWARE_SPI
+}
+//------------------------------------------------------------------------------
 /**
    Enable or disable partial block reads.
 
diff --git a/src/utility/Sd2Card.h b/src/utility/Sd2Card.h
index 5d91ebf..fe09839 100644
--- a/src/utility/Sd2Card.h
+++ b/src/utility/Sd2Card.h
@@ -206,6 +206,7 @@ class Sd2Card {
       return init(sckRateID, SD_CHIP_SELECT_PIN);
     }
     uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin);
+    void done();
     void partialBlockRead(uint8_t value);
     /** Returns the current value, true or false, for partial block read. */
     uint8_t partialBlockRead(void) const {

From 58bcbb6af1afe36a26ff11fa46803ae7d78e73e8 Mon Sep 17 00:00:00 2001
From: mcaldwelva <mcaldwelva@gmail.com>
Date: Tue, 13 Sep 2022 23:38:30 -0400
Subject: [PATCH 4/4] implement pr #97

---
 src/SD.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/SD.cpp b/src/SD.cpp
index 544c94d..88d52eb 100644
--- a/src/SD.cpp
+++ b/src/SD.cpp
@@ -616,7 +616,8 @@ namespace SDLib {
       //Serial.print("try to open file ");
       //Serial.println(name);
 
-      if (f.open(_file, name, mode)) {
+      uint16_t index = _file->curPosition() / sizeof(dir_t) - 1;
+      if (f.open(_file, index, mode)) {
         //Serial.println("OK!");
         return File(f, name);
       } else {