ESP32/components/app_console/cmd_sdcard.c

169 lines
5.5 KiB
C

/*
* 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 <stdio.h>
#include <string.h>
#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 <file> <text...>\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 <file>\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 <status|write|read> [args]\n");
printf(" status - Show CD, mounted, capacity\n");
printf(" write <f> <t> - Write text to file\n");
printf(" read <f> - 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 <file> <text>, read <file>",
.hint = "<status|write|read>",
.func = &cmd_sdcard,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
}