Browse Source

Added long filename support.

daid 11 years ago
parent
commit
b69e75c89a

+ 0
- 2
Marlin/Marlin.pde View File

1810
   }
1810
   }
1811
 }
1811
 }
1812
 #endif
1812
 #endif
1813
-
1814
-

+ 1
- 3
Marlin/Sd2Card.cpp View File

369
  *
369
  *
370
  * \param[in] blockNumber Logical block to be read.
370
  * \param[in] blockNumber Logical block to be read.
371
  * \param[out] dst Pointer to the location that will receive the data.
371
  * \param[out] dst Pointer to the location that will receive the data.
372
-
373
  * \return The value one, true, is returned for success and
372
  * \return The value one, true, is returned for success and
374
  * the value zero, false, is returned for failure.
373
  * the value zero, false, is returned for failure.
375
  */
374
  */
639
   return false;
638
   return false;
640
 }
639
 }
641
 
640
 
642
-
643
-#endif
641
+#endif

+ 37
- 3
Marlin/SdBaseFile.cpp View File

867
   }
867
   }
868
   // search for parent in '../..'
868
   // search for parent in '../..'
869
   do {
869
   do {
870
-    if (file.readDir(&entry) != 32) goto fail;
870
+    if (file.readDir(&entry, NULL) != 32) goto fail;
871
     c = entry.firstClusterLow;
871
     c = entry.firstClusterLow;
872
     c |= (uint32_t)entry.firstClusterHigh << 16;
872
     c |= (uint32_t)entry.firstClusterHigh << 16;
873
   } while (c != cluster);
873
   } while (c != cluster);
1108
  * readDir() called before a directory has been opened, this is not
1108
  * readDir() called before a directory has been opened, this is not
1109
  * a directory file or an I/O error occurred.
1109
  * a directory file or an I/O error occurred.
1110
  */
1110
  */
1111
-int8_t SdBaseFile::readDir(dir_t* dir) {
1111
+int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
1112
   int16_t n;
1112
   int16_t n;
1113
   // if not a directory file or miss-positioned return an error
1113
   // if not a directory file or miss-positioned return an error
1114
   if (!isDir() || (0X1F & curPosition_)) return -1;
1114
   if (!isDir() || (0X1F & curPosition_)) return -1;
1115
+  
1116
+  //If we have a longFilename buffer, mark it as invalid. If we find a long filename it will be filled automaticly.
1117
+  if (longFilename != NULL)
1118
+  {
1119
+  	longFilename[0] = '\0';
1120
+  }
1115
 
1121
 
1116
   while (1) {
1122
   while (1) {
1117
     n = read(dir, sizeof(dir_t));
1123
     n = read(dir, sizeof(dir_t));
1120
     if (dir->name[0] == DIR_NAME_FREE) return 0;
1126
     if (dir->name[0] == DIR_NAME_FREE) return 0;
1121
     // skip empty entries and entry for .  and ..
1127
     // skip empty entries and entry for .  and ..
1122
     if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue;
1128
     if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue;
1129
+    //Fill the long filename if we have a long filename entry,
1130
+	// long filename entries are stored before the actual filename.
1131
+	if (DIR_IS_LONG_NAME(dir) && longFilename != NULL)
1132
+    {
1133
+    	vfat_t *VFAT = (vfat_t*)dir;
1134
+		//Sanity check the VFAT entry. The first cluster is always set to zero. And th esequence number should be higher then 0
1135
+    	if (VFAT->firstClusterLow == 0 && (VFAT->sequenceNumber & 0x1F) > 0 && (VFAT->sequenceNumber & 0x1F) <= MAX_VFAT_ENTRIES)
1136
+    	{
1137
+			//TODO: Store the filename checksum to verify if a none-long filename aware system modified the file table.
1138
+    		n = ((VFAT->sequenceNumber & 0x1F) - 1) * 13;
1139
+			longFilename[n+0] = VFAT->name1[0];
1140
+			longFilename[n+1] = VFAT->name1[1];
1141
+			longFilename[n+2] = VFAT->name1[2];
1142
+			longFilename[n+3] = VFAT->name1[3];
1143
+			longFilename[n+4] = VFAT->name1[4];
1144
+			longFilename[n+5] = VFAT->name2[0];
1145
+			longFilename[n+6] = VFAT->name2[1];
1146
+			longFilename[n+7] = VFAT->name2[2];
1147
+			longFilename[n+8] = VFAT->name2[3];
1148
+			longFilename[n+9] = VFAT->name2[4];
1149
+			longFilename[n+10] = VFAT->name2[5];
1150
+			longFilename[n+11] = VFAT->name3[0];
1151
+			longFilename[n+12] = VFAT->name3[1];
1152
+			//If this VFAT entry is the last one, add a NUL terminator at the end of the string
1153
+			if (VFAT->sequenceNumber & 0x40)
1154
+				longFilename[n+13] = '\0';
1155
+		}
1156
+    }
1123
     // return if normal file or subdirectory
1157
     // return if normal file or subdirectory
1124
     if (DIR_IS_FILE_OR_SUBDIR(dir)) return n;
1158
     if (DIR_IS_FILE_OR_SUBDIR(dir)) return n;
1125
   }
1159
   }
1788
 #endif  // ALLOW_DEPRECATED_FUNCTIONS
1822
 #endif  // ALLOW_DEPRECATED_FUNCTIONS
1789
 
1823
 
1790
 
1824
 
1791
-#endif
1825
+#endif

+ 3
- 3
Marlin/SdBaseFile.h View File

283
   bool printName();
283
   bool printName();
284
   int16_t read();
284
   int16_t read();
285
   int16_t read(void* buf, uint16_t nbyte);
285
   int16_t read(void* buf, uint16_t nbyte);
286
-  int8_t readDir(dir_t* dir);
286
+  int8_t readDir(dir_t* dir, char* longFilename);
287
   static bool remove(SdBaseFile* dirFile, const char* path);
287
   static bool remove(SdBaseFile* dirFile, const char* path);
288
   bool remove();
288
   bool remove();
289
   /** Set the file's current position to zero. */
289
   /** Set the file's current position to zero. */
455
    * \param[out] dir The dir_t struct that will receive the data.
455
    * \param[out] dir The dir_t struct that will receive the data.
456
    * \return bytes read for success zero for eof or -1 for failure.
456
    * \return bytes read for success zero for eof or -1 for failure.
457
    */
457
    */
458
-  int8_t readDir(dir_t& dir) {return readDir(&dir);}  // NOLINT
458
+  int8_t readDir(dir_t& dir, char* longFilename) {return readDir(&dir, longFilename);}  // NOLINT
459
   /** \deprecated Use:
459
   /** \deprecated Use:
460
    * static uint8_t remove(SdBaseFile* dirFile, const char* path);
460
    * static uint8_t remove(SdBaseFile* dirFile, const char* path);
461
    * \param[in] dirFile The directory that contains the file.
461
    * \param[in] dirFile The directory that contains the file.
480
 };
480
 };
481
 
481
 
482
 #endif  // SdBaseFile_h
482
 #endif  // SdBaseFile_h
483
-#endif
483
+#endif

+ 8
- 1
Marlin/SdFatConfig.h View File

108
  * a pure virtual function is called.
108
  * a pure virtual function is called.
109
  */
109
  */
110
 #define USE_CXA_PURE_VIRTUAL 1
110
 #define USE_CXA_PURE_VIRTUAL 1
111
+/**
112
+ * Defines for long (vfat) filenames
113
+ */
114
+/** Number of VFAT entries used. Every entry has 13 UTF-16 characters */
115
+#define MAX_VFAT_ENTRIES (2)
116
+/** Total size of the buffer used to store the long filenames */
117
+#define LONG_FILENAME_LENGTH (13*MAX_VFAT_ENTRIES+1)
111
 #endif  // SdFatConfig_h
118
 #endif  // SdFatConfig_h
112
 
119
 
113
 
120
 
114
-#endif
121
+#endif

+ 43
- 7
Marlin/SdFatStructs.h View File

22
 
22
 
23
 #ifndef SdFatStructs_h
23
 #ifndef SdFatStructs_h
24
 #define SdFatStructs_h
24
 #define SdFatStructs_h
25
+
26
+#define PACKED __attribute__((__packed__))
25
 /**
27
 /**
26
  * \file
28
  * \file
27
  * \brief FAT file structures
29
  * \brief FAT file structures
95
   uint32_t firstSector;
97
   uint32_t firstSector;
96
            /** Length of the partition, in blocks. */
98
            /** Length of the partition, in blocks. */
97
   uint32_t totalSectors;
99
   uint32_t totalSectors;
98
-};
100
+} PACKED;
99
 /** Type name for partitionTable */
101
 /** Type name for partitionTable */
100
 typedef struct partitionTable part_t;
102
 typedef struct partitionTable part_t;
101
 //------------------------------------------------------------------------------
103
 //------------------------------------------------------------------------------
119
   uint8_t  mbrSig0;
121
   uint8_t  mbrSig0;
120
            /** Second MBR signature byte. Must be 0XAA */
122
            /** Second MBR signature byte. Must be 0XAA */
121
   uint8_t  mbrSig1;
123
   uint8_t  mbrSig1;
122
-};
124
+} PACKED;
123
 /** Type name for masterBootRecord */
125
 /** Type name for masterBootRecord */
124
 typedef struct masterBootRecord mbr_t;
126
 typedef struct masterBootRecord mbr_t;
125
 //------------------------------------------------------------------------------
127
 //------------------------------------------------------------------------------
247
   uint8_t  bootSectorSig0;
249
   uint8_t  bootSectorSig0;
248
            /** must be 0XAA */
250
            /** must be 0XAA */
249
   uint8_t  bootSectorSig1;
251
   uint8_t  bootSectorSig1;
250
-};
252
+} PACKED;
251
 /** Type name for FAT Boot Sector */
253
 /** Type name for FAT Boot Sector */
252
 typedef struct fat_boot fat_boot_t;
254
 typedef struct fat_boot fat_boot_t;
253
 //------------------------------------------------------------------------------
255
 //------------------------------------------------------------------------------
401
   uint8_t  bootSectorSig0;
403
   uint8_t  bootSectorSig0;
402
            /** must be 0XAA */
404
            /** must be 0XAA */
403
   uint8_t  bootSectorSig1;
405
   uint8_t  bootSectorSig1;
404
-};
406
+} PACKED;
405
 /** Type name for FAT32 Boot Sector */
407
 /** Type name for FAT32 Boot Sector */
406
 typedef struct fat32_boot fat32_boot_t;
408
 typedef struct fat32_boot fat32_boot_t;
407
 //------------------------------------------------------------------------------
409
 //------------------------------------------------------------------------------
441
   uint8_t  reserved2[12];
443
   uint8_t  reserved2[12];
442
            /** must be 0X00, 0X00, 0X55, 0XAA */
444
            /** must be 0X00, 0X00, 0X55, 0XAA */
443
   uint8_t  tailSignature[4];
445
   uint8_t  tailSignature[4];
444
-};
446
+} PACKED;
445
 /** Type name for FAT32 FSINFO Sector */
447
 /** Type name for FAT32 FSINFO Sector */
446
 typedef struct fat32_fsinfo fat32_fsinfo_t;
448
 typedef struct fat32_fsinfo fat32_fsinfo_t;
447
 //------------------------------------------------------------------------------
449
 //------------------------------------------------------------------------------
539
   uint16_t firstClusterLow;
541
   uint16_t firstClusterLow;
540
            /** 32-bit unsigned holding this file's size in bytes. */
542
            /** 32-bit unsigned holding this file's size in bytes. */
541
   uint32_t fileSize;
543
   uint32_t fileSize;
542
-};
544
+} PACKED;
545
+/**
546
+ * \struct directoryVFATEntry
547
+ * \brief VFAT long filename directory entry
548
+ *
549
+ * directoryVFATEntries are found in the same list as normal directoryEntry.
550
+ * But have the attribute field set to DIR_ATT_LONG_NAME.
551
+ * 
552
+ * Long filenames are saved in multiple directoryVFATEntries.
553
+ * Each entry containing 13 UTF-16 characters.
554
+ */
555
+struct directoryVFATEntry {
556
+  /**
557
+   * Sequence number. Consists of 2 parts:
558
+   *  bit 6:   indicates first long filename block for the next file
559
+   *  bit 0-4: the position of this long filename block (first block is 1)
560
+   */
561
+  uint8_t  sequenceNumber;
562
+  /** First set of UTF-16 characters */
563
+  uint16_t name1[5];//UTF-16
564
+  /** attributes (at the same location as in directoryEntry), always 0x0F */
565
+  uint8_t  attributes;
566
+  /** Reserved for use by Windows NT. Always 0. */
567
+  uint8_t  reservedNT;
568
+  /** 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. */
569
+  uint8_t  checksum;
570
+  /** Second set of UTF-16 characters */
571
+  uint16_t name2[6];//UTF-16
572
+  /** firstClusterLow is always zero for longFilenames */
573
+  uint16_t firstClusterLow;
574
+  /** Third set of UTF-16 characters */
575
+  uint16_t name3[2];//UTF-16
576
+} PACKED;
543
 //------------------------------------------------------------------------------
577
 //------------------------------------------------------------------------------
544
 // Definitions for directory entries
578
 // Definitions for directory entries
545
 //
579
 //
546
 /** Type name for directoryEntry */
580
 /** Type name for directoryEntry */
547
 typedef struct directoryEntry dir_t;
581
 typedef struct directoryEntry dir_t;
582
+/** Type name for directoryVFATEntry */
583
+typedef struct directoryVFATEntry vfat_t;
548
 /** escape for name[0] = 0XE5 */
584
 /** escape for name[0] = 0XE5 */
549
 uint8_t const DIR_NAME_0XE5 = 0X05;
585
 uint8_t const DIR_NAME_0XE5 = 0X05;
550
 /** name[0] value for entry that is free after being "deleted" */
586
 /** name[0] value for entry that is free after being "deleted" */
607
 #endif  // SdFatStructs_h
643
 #endif  // SdFatStructs_h
608
 
644
 
609
 
645
 
610
-#endif
646
+#endif

+ 4
- 4
Marlin/cardreader.cpp View File

51
   dir_t p;
51
   dir_t p;
52
  uint8_t cnt=0;
52
  uint8_t cnt=0;
53
  
53
  
54
-  while (parent.readDir(p) > 0)
54
+  while (parent.readDir(p, longFilename) > 0)
55
   {
55
   {
56
     if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint
56
     if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint
57
     {
57
     {
429
   
429
   
430
   char autoname[30];
430
   char autoname[30];
431
   sprintf(autoname,"auto%i.g",lastnr);
431
   sprintf(autoname,"auto%i.g",lastnr);
432
-  for(int8_t i=0;i<(int)strlen(autoname);i++)
432
+  for(int8_t i=0;i<(int8_t)strlen(autoname);i++)
433
     autoname[i]=tolower(autoname[i]);
433
     autoname[i]=tolower(autoname[i]);
434
   dir_t p;
434
   dir_t p;
435
 
435
 
436
   root.rewind();
436
   root.rewind();
437
   
437
   
438
   bool found=false;
438
   bool found=false;
439
-  while (root.readDir(p) > 0) 
439
+  while (root.readDir(p, NULL) > 0) 
440
   {
440
   {
441
-    for(int8_t i=0;i<(int)strlen((char*)p.name);i++)
441
+    for(int8_t i=0;i<(int8_t)strlen((char*)p.name);i++)
442
     p.name[i]=tolower(p.name[i]);
442
     p.name[i]=tolower(p.name[i]);
443
     //Serial.print((char*)p.name);
443
     //Serial.print((char*)p.name);
444
     //Serial.print(" ");
444
     //Serial.print(" ");

+ 3
- 2
Marlin/cardreader.h View File

45
   bool saving;
45
   bool saving;
46
   bool sdprinting ;  
46
   bool sdprinting ;  
47
   bool cardOK ;
47
   bool cardOK ;
48
-  char filename[12];
48
+  char filename[13];
49
+  char longFilename[LONG_FILENAME_LENGTH];
49
   bool filenameIsDir;
50
   bool filenameIsDir;
50
   int lastnr; //last number of the autostart;
51
   int lastnr; //last number of the autostart;
51
 private:
52
 private:
72
 #define IS_SD_PRINTING (false)
73
 #define IS_SD_PRINTING (false)
73
 
74
 
74
 #endif //SDSUPPORT
75
 #endif //SDSUPPORT
75
-#endif
76
+#endif

+ 18
- 2
Marlin/ultralcd.pde View File

2304
           //Serial.print("Filenr:");Serial.println(i-2);
2304
           //Serial.print("Filenr:");Serial.println(i-2);
2305
           lcd.setCursor(0,line);lcdprintPGM(" ");
2305
           lcd.setCursor(0,line);lcdprintPGM(" ");
2306
           if(card.filenameIsDir) lcd.print("\005");
2306
           if(card.filenameIsDir) lcd.print("\005");
2307
-          lcd.print(card.filename);
2307
+          if (card.longFilename[0])
2308
+          {
2309
+            card.longFilename[LCD_WIDTH-1] = '\0';
2310
+            lcd.print(card.longFilename);
2311
+          }
2312
+          else
2313
+          {
2314
+            lcd.print(card.filename);
2315
+          }
2308
         }
2316
         }
2309
         if((activeline==line) && CLICKED)
2317
         if((activeline==line) && CLICKED)
2310
         {
2318
         {
2329
             enquecommand("M24");
2337
             enquecommand("M24");
2330
             beep(); 
2338
             beep(); 
2331
             status=Main_Status;
2339
             status=Main_Status;
2332
-            lcd_status(card.filename);
2340
+            if (card.longFilename[0])
2341
+            {
2342
+              card.longFilename[LCD_WIDTH-1] = '\0';
2343
+              lcd_status(card.longFilename);
2344
+            }
2345
+            else
2346
+            {
2347
+              lcd_status(card.filename);
2348
+            }
2333
           }
2349
           }
2334
         } 
2350
         } 
2335
       }
2351
       }

Loading…
Cancel
Save