From e38da17f6b39283957d1473e56884bca09e7d4e4 Mon Sep 17 00:00:00 2001 From: Bjoern Kerler Date: Sun, 18 Feb 2024 19:08:50 +0100 Subject: [PATCH] Update gcode M20 to fit common marlin behaviour --- src/marlin_stubs/host/M115.cpp | 3 + src/marlin_stubs/sdcard/M20-M30_M32-M34.cpp | 68 +++++++++++++++++++-- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/marlin_stubs/host/M115.cpp b/src/marlin_stubs/host/M115.cpp index dfade61623..7f3df434f0 100644 --- a/src/marlin_stubs/host/M115.cpp +++ b/src/marlin_stubs/host/M115.cpp @@ -214,5 +214,8 @@ void GcodeSuite::M115() { #endif ); + // PARSE FILES ON USB (M20) + cap_line(PSTR("EXTENDED_M20"), true); + #endif // EXTENDED_CAPABILITIES_REPORT } diff --git a/src/marlin_stubs/sdcard/M20-M30_M32-M34.cpp b/src/marlin_stubs/sdcard/M20-M30_M32-M34.cpp index 56b018f3f4..67fb4e8b5f 100644 --- a/src/marlin_stubs/sdcard/M20-M30_M32-M34.cpp +++ b/src/marlin_stubs/sdcard/M20-M30_M32-M34.cpp @@ -1,22 +1,80 @@ #include #include "../../lib/Marlin/Marlin/src/gcode/gcode.h" +#include "libs/hex_print_routines.h" #include "marlin_server.hpp" #include "media.h" #include "marlin_vars.hpp" -// M20 - List SD card -void GcodeSuite::M20() { - SERIAL_ECHOLNPGM(MSG_BEGIN_FILE_LIST); +struct TimeFlags { + bool print_lfn : 1; + bool print_timestamps : 1; +}; + +static void time_to_m20(const struct stat stat_buf, uint16_t *m20_date, uint16_t *m20_time) { + time_t t = stat_buf.st_mtim.tv_sec; + struct tm lt; + localtime_r(&t, <); + *m20_date = (lt.tm_year + 1900 - 1980) << 9 | (lt.tm_mon + 1) << 5 | lt.tm_mday; + *m20_time = lt.tm_hour << 11 | lt.tm_min << 5; + *m20_time |= int((lt.tm_sec - (lt.tm_sec % 2)) / 2); +} + +static void print_file_info(const char *const path, const char *const long_path, const struct TimeFlags tf) { + // &path[5] and &long_path[5], because we skip the /usb/ prefix on print as it is only used internally + SERIAL_ECHO(&path[5]); + SERIAL_CHAR(' '); + struct stat stat_buf; + int rc = stat(path, &stat_buf); + if (rc == 0) { + SERIAL_ECHO(stat_buf.st_size); + if (tf.print_timestamps) { + uint16_t m20_date; + uint16_t m20_time; + time_to_m20(stat_buf, &m20_date, &m20_time); + SERIAL_ECHOPGM(" 0x"); + print_hex_word(m20_date); + print_hex_word(m20_time); + } + if (tf.print_lfn) { + SERIAL_CHAR(' '); + SERIAL_CHAR('"'); + SERIAL_ECHO(&long_path[5]); + SERIAL_CHAR('"'); + } + } + SERIAL_EOL(); +} + +static void print_listing(const char *const prefix, const char *const prefix_long, const struct TimeFlags tf) { DIR *dir; - dir = opendir("/usb/"); + dir = opendir(prefix); if (dir != NULL) { struct dirent *entry; while ((entry = readdir(dir)) != NULL && entry->d_name[0]) { - SERIAL_ECHOLN(entry->d_name); + char path[5 + sizeof(entry->d_name) * 2]; + snprintf(path, sizeof(path), "%s/%s", prefix, entry->d_name); + char long_path[5 + sizeof(entry->lfn) * 2]; + snprintf(long_path, sizeof(long_path), "%s/%s", prefix_long, entry->lfn); + if (entry->d_type != DT_DIR) { + print_file_info(path, long_path, tf); + } } closedir(dir); } +} + +// M20 - List SD card +void GcodeSuite::M20() { + TimeFlags tf; + if (parser.seen('L')) { + tf.print_lfn = 1; + } + if (parser.seen('T')) { + tf.print_timestamps = 1; + } + SERIAL_ECHOLNPGM(MSG_BEGIN_FILE_LIST); + print_listing("/usb", "/usb", tf); SERIAL_ECHOLNPGM(MSG_END_FILE_LIST); }