/* * cmd_sdcard.c * * Copyright (c) 2025 Umber Networks & Robert McMahon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "esp_console.h" #include "argtable3/argtable3.h" #include "app_console.h" #include "sd_card.h" #define SDCARD_READ_BUF_SIZE 4096 static int do_sdcard_status(int argc, char **argv) { (void)argc; (void)argv; printf("SD Card Status:\n"); printf(" CD (Card Detect): "); if (sd_card_cd_available()) { int level = sd_card_cd_get_level(); bool inserted = sd_card_cd_is_inserted(); printf("%s (GPIO=%s)\n", inserted ? "INSERTED" : "REMOVED", level >= 0 ? (level ? "HIGH" : "LOW") : "?"); if (!inserted && sd_card_is_ready()) { printf(" (Card works but CD says REMOVED: wire CD to J1 Pin 12, or menuconfig -> SD Card -> uncheck 'LOW = inserted')\n"); } } else { printf("N/A (pin not configured)\n"); } printf(" Mounted: %s\n", sd_card_is_ready() ? "yes" : "no"); if (sd_card_is_ready()) { uint64_t total = 0, free_bytes = 0; if (sd_card_get_info(&total, &free_bytes) == 0) { printf(" Total: %.2f MB\n", total / (1024.0 * 1024.0)); printf(" Free: %.2f MB\n", free_bytes / (1024.0 * 1024.0)); } } return 0; } static int do_sdcard_write(int argc, char **argv) { if (argc < 3) { printf("Usage: sdcard write \n"); return 1; } const char *filename = argv[1]; if (!sd_card_is_ready()) { printf("Error: SD card not mounted\n"); return 1; } /* Join argv[2]..argv[argc-1] with spaces for multi-word text */ static char text_buf[512]; size_t off = 0; for (int i = 2; i < argc && off < sizeof(text_buf) - 2; i++) { if (i > 2) { text_buf[off++] = ' '; } size_t len = strlen(argv[i]); if (off + len >= sizeof(text_buf)) { len = sizeof(text_buf) - off - 1; } memcpy(text_buf + off, argv[i], len); off += len; } text_buf[off] = '\0'; esp_err_t ret = sd_card_write_file(filename, text_buf, off, false); if (ret != 0) { printf("Write failed: %s\n", esp_err_to_name(ret)); return 1; } printf("Wrote %zu bytes to %s\n", off, filename); return 0; } static int do_sdcard_read(int argc, char **argv) { if (argc < 2) { printf("Usage: sdcard read \n"); return 1; } const char *filename = argv[1]; if (!sd_card_is_ready()) { printf("Error: SD card not mounted\n"); return 1; } if (!sd_card_file_exists(filename)) { printf("Error: File not found: %s\n", filename); return 1; } static uint8_t buf[SDCARD_READ_BUF_SIZE]; size_t bytes_read = 0; esp_err_t ret = sd_card_read_file(filename, buf, sizeof(buf) - 1, &bytes_read); if (ret != 0) { printf("Read failed: %s\n", esp_err_to_name(ret)); return 1; } buf[bytes_read] = '\0'; printf("Read %zu bytes from %s:\n", bytes_read, filename); printf("---\n%s\n---\n", (char *)buf); return 0; } static int cmd_sdcard(int argc, char **argv) { if (argc < 2) { printf("Usage: sdcard [args]\n"); printf(" status - Show CD, mounted, capacity\n"); printf(" write - Write text to file\n"); printf(" read - Read and print file\n"); return 0; } if (strcmp(argv[1], "status") == 0) { return do_sdcard_status(argc - 1, &argv[1]); } if (strcmp(argv[1], "write") == 0) { return do_sdcard_write(argc - 1, &argv[1]); } if (strcmp(argv[1], "read") == 0) { return do_sdcard_read(argc - 1, &argv[1]); } printf("Unknown subcommand '%s'\n", argv[1]); return 1; } void register_sdcard_cmd(void) { const esp_console_cmd_t cmd = { .command = "sdcard", .help = "SD card: status (CD, capacity), write , read ", .hint = "", .func = &cmd_sdcard, }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); }