Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LFN lookup - do not skip LFN entries longer than what we can display #25598

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Marlin/src/inc/Conditionals_post.h
Original file line number Diff line number Diff line change
Expand Up @@ -3262,10 +3262,11 @@

// Number of VFAT entries used. Each entry has 13 UTF-16 characters
#if ANY(SCROLL_LONG_FILENAMES, HAS_DWIN_E3V2, TFT_COLOR_UI)
#define MAX_VFAT_ENTRIES 5
#define VFAT_ENTRIES_LIMIT 5
#else
#define MAX_VFAT_ENTRIES 2
#define VFAT_ENTRIES_LIMIT 2
#endif
#define MAX_VFAT_ENTRIES 20 // by VFAT specs to fit LFN of length 255
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that VFAT_ENTRIES_LIMIT is related to the number of characters that can be displayed on LCD and the methods that return the truncated filename to be displayed on LCD. So it should not necessarily be applied to the selection of files by long pathname with M23 or to M20 where we can use a smaller buffer to do the character comparisons. Once we have the selected file's ID and/or short pathname/filename, that is the only piece of data needed to refer to the selected file from that point onward, where we only need to store the complete long name of the selected file for reporting and display.

Meanwhile, the size of the buffer used by SDCARD_SORT_ALPHA is determined by SDSORT_CACHE_VFATS, where we might even store the sorted names in RAM. That might be optimized by just storing the sorted names in one contiguous buffer with a separate index into the buffer for each filename, rather than the current scheme of storing an index into an array of filenames (which mirrors the index into the directory structure used for the non-cached-filename sorting index).


// Nozzle park for Delta
#if BOTH(NOZZLE_PARK_FEATURE, DELTA)
Expand Down
4 changes: 2 additions & 2 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -1048,9 +1048,9 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#if ENABLED(SDSORT_CACHE_NAMES) && DISABLED(SDSORT_DYNAMIC_RAM)
#if SDSORT_CACHE_VFATS < 2
#error "SDSORT_CACHE_VFATS must be 2 or greater!"
#elif SDSORT_CACHE_VFATS > MAX_VFAT_ENTRIES
#elif SDSORT_CACHE_VFATS > VFAT_ENTRIES_LIMIT
#undef SDSORT_CACHE_VFATS
#define SDSORT_CACHE_VFATS MAX_VFAT_ENTRIES
#define SDSORT_CACHE_VFATS VFAT_ENTRIES_LIMIT
#define SDSORT_CACHE_VFATS_WARNING 1
#endif
#endif
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/inc/Warnings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@
#endif

#if SDSORT_CACHE_VFATS_WARNING
#warning "SDSORT_CACHE_VFATS has been reduced to MAX_VFAT_ENTRIES."
#warning "SDSORT_CACHE_VFATS has been reduced to VFAT_ENTRIES_LIMIT."
#endif
#if SDSORT_CACHE_LPC1768_WARNING
#warning "SDCARD_SORT_ALPHA sub-options overridden for LPC1768 with DOGM LCD SCK overlap."
Expand Down
7 changes: 4 additions & 3 deletions Marlin/src/sd/SdBaseFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,8 @@ bool SdBaseFile::openNext(SdBaseFile *dirFile, uint8_t oflag) {
bool SdBaseFile::isDirLFN(const dir_t* dir) {
if (DIR_IS_LONG_NAME(dir)) {
vfat_t *VFAT = (vfat_t*)dir;
// Sanity-check the VFAT entry. The first cluster is always set to zero. And the sequence number should be higher than 0
// Sanity-check the VFAT entry. The first cluster is always set to zero.
// The sequence number should be higher than 0 and lower than maximum allowed by VFAT spec
if ((VFAT->firstClusterLow == 0) && WITHIN((VFAT->sequenceNumber & 0x1F), 1, MAX_VFAT_ENTRIES)) return true;
}
return false;
Expand Down Expand Up @@ -1463,7 +1464,7 @@ int8_t SdBaseFile::readDir(dir_t *dir, char * const longFilename) {
// Sanity-check the VFAT entry. The first cluster is always set to zero. And the sequence number should be higher than 0
if (VFAT->firstClusterLow == 0) {
const uint8_t seq = VFAT->sequenceNumber & 0x1F;
if (WITHIN(seq, 1, MAX_VFAT_ENTRIES)) {
if (WITHIN(seq, 1, VFAT_ENTRIES_LIMIT)) {
if (seq == 1) {
checksum = VFAT->checksum;
checksum_error = 0;
Expand Down Expand Up @@ -1627,7 +1628,7 @@ bool SdBaseFile::remove() {
// Check if the entry has a LFN
bool lastEntry = false;
// loop back to search for any LFN entries related to this file
LOOP_S_LE_N(sequenceNumber, 1, MAX_VFAT_ENTRIES) {
LOOP_S_LE_N(sequenceNumber, 1, VFAT_ENTRIES_LIMIT) {
dirIndex_ = (dirIndex_ - 1) & 0xF;
if (dirBlock_ == 0) break;
if (dirIndex_ == 0xF) dirBlock_--;
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/sd/SdFatConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,4 @@
#define LONG_FILENAME_CHARSIZE TERN(UTF_FILENAME_SUPPORT, 2, 1)

// Total bytes needed to store a single long filename
#define LONG_FILENAME_LENGTH (FILENAME_LENGTH * LONG_FILENAME_CHARSIZE * MAX_VFAT_ENTRIES + 1)
#define LONG_FILENAME_LENGTH (FILENAME_LENGTH * LONG_FILENAME_CHARSIZE * VFAT_ENTRIES_LIMIT + 1)