From 794d8e36c9ce75616224b55c6451c84dc24a0114 Mon Sep 17 00:00:00 2001 From: Eduard Iten Date: Thu, 12 Feb 2026 11:26:43 +0100 Subject: [PATCH] Added mcumgr/smp v2 commands for listing and deleting files --- firmware/libs/fs_mgmt/Kconfig | 8 ++ firmware/libs/fs_mgmt/src/fs_mgmt.c | 169 +++++++++++++++++++++++++++- 2 files changed, 176 insertions(+), 1 deletion(-) diff --git a/firmware/libs/fs_mgmt/Kconfig b/firmware/libs/fs_mgmt/Kconfig index 169bb59..54f78ac 100644 --- a/firmware/libs/fs_mgmt/Kconfig +++ b/firmware/libs/fs_mgmt/Kconfig @@ -9,6 +9,14 @@ menuconfig FS_MGMT Library for initializing and managing the file system. if FS_MGMT + config FS_MGMT_MCUMGR_HANDLER + bool "Enable Custom MCUMGR FS Handlers" + default y + depends on MCUMGR_GRP_FS + help + Enables the custom MCUMGR group (ID 64) for listing (ls) + and removing (rm) files via SMP. + # Logging configuration for the File System Management module module = FS_MGMT module-str = fs_mgmt diff --git a/firmware/libs/fs_mgmt/src/fs_mgmt.c b/firmware/libs/fs_mgmt/src/fs_mgmt.c index 383b3ed..64288e6 100644 --- a/firmware/libs/fs_mgmt/src/fs_mgmt.c +++ b/firmware/libs/fs_mgmt/src/fs_mgmt.c @@ -15,6 +15,167 @@ static struct fs_mount_t fs_storage_mnt = { .mnt_point = "/lfs", }; +#ifdef CONFIG_FS_MGMT_MCUMGR_HANDLER +#include +#include +#include +#include +#include +#include + +#define CUSTOM_GROUP_ID 64 +#define CMD_LS 0 +#define CMD_RM 1 + +static int custom_ls_handler(struct smp_streamer *ctxt) +{ + struct fs_dir_t dirp; + struct fs_dirent entry; + int file_count = 0; + char path[64] = ""; // Startet leer + + zcbor_state_t *zsd = ctxt->reader->zs; + zcbor_state_t *zse = ctxt->writer->zs; + + /* --- DECODING --- */ + struct zcbor_string res_path = {0}; + bool path_found = false; + + if (zcbor_map_start_decode(zsd)) + { + while (zcbor_tstr_decode(zsd, &res_path)) + { + if (res_path.len == 4 && memcmp(res_path.value, "path", 4) == 0) + { + struct zcbor_string path_val; + if (zcbor_tstr_decode(zsd, &path_val)) + { + int len = MIN(path_val.len, sizeof(path) - 1); + memcpy(path, path_val.value, len); + path[len] = '\0'; + path_found = true; + } + } + else + { + zcbor_any_skip(zsd, NULL); + } + } + zcbor_map_end_decode(zsd); + } + + // Falls kein Pfad gesendet wurde, fange im Root an + if (!path_found || strlen(path) == 0) + { + strcpy(path, "/"); + } + + /* --- PROCESSING & ENCODING --- */ + fs_dir_t_init(&dirp); + if (fs_opendir(&dirp, path) != 0) + return MGMT_ERR_ENOENT; + + // Zählen... + while (fs_readdir(&dirp, &entry) == 0 && entry.name[0] != '\0') + { + file_count++; + } + fs_closedir(&dirp); + + bool ok = zcbor_tstr_put_lit(zse, "files") && zcbor_list_start_encode(zse, file_count); + + if (fs_opendir(&dirp, path) == 0) + { + while (fs_readdir(&dirp, &entry) == 0 && entry.name[0] != '\0') + { + const char *type_char = (entry.type == FS_DIR_ENTRY_DIR) ? "d" : "f"; + ok = ok && zcbor_map_start_encode(zse, 2) && + zcbor_tstr_put_lit(zse, "n") && + zcbor_tstr_encode(zse, &(struct zcbor_string){.value = (const uint8_t *)entry.name, .len = strlen(entry.name)}) && + zcbor_tstr_put_lit(zse, "t") && + zcbor_tstr_encode(zse, &(struct zcbor_string){.value = (const uint8_t *)type_char, .len = 1}) && + zcbor_map_end_encode(zse, 2); + } + fs_closedir(&dirp); + } + ok = ok && zcbor_list_end_encode(zse, file_count); + return ok ? 0 : MGMT_ERR_ENOMEM; +} + +static int custom_rm_handler(struct smp_streamer *ctxt) +{ + char path[64] = {0}; + zcbor_state_t *zsd = ctxt->reader->zs; + zcbor_state_t *zse = ctxt->writer->zs; + bool path_found = false; + struct zcbor_string key; + + /* --- DECODING --- */ + if (!zcbor_map_start_decode(zsd)) + { + return MGMT_ERR_EINVAL; + } + + while (zcbor_tstr_decode(zsd, &key)) + { + if (key.len == 4 && memcmp(key.value, "path", 4) == 0) + { + struct zcbor_string val; + if (zcbor_tstr_decode(zsd, &val)) + { + size_t len = MIN(val.len, sizeof(path) - 1); + memcpy(path, val.value, len); + path[len] = '\0'; + path_found = true; + } + } + else + { + zcbor_any_skip(zsd, NULL); + } + } + zcbor_map_end_decode(zsd); + + if (!path_found) + { + return MGMT_ERR_EINVAL; + } + + /* --- PROCESSING --- */ + int rc = fs_unlink(path); + + /* --- ENCODING RESPONSE --- */ + // Wir senden den Return-Code zurück (0 = Erfolg) + bool ok = zcbor_tstr_put_lit(zse, "rc") && zcbor_int32_put(zse, rc); + + if (rc != 0) + { + LOG_WRN("Failed to remove %s: %d", path, rc); + // Optional: Spezifische mgmt_err Mapping + return (rc == -ENOENT) ? MGMT_ERR_ENOENT : MGMT_ERR_EUNKNOWN; + } + + return ok ? 0 : MGMT_ERR_ENOMEM; +} + +static const struct mgmt_handler custom_handlers[] = { + [CMD_LS] = { + .mh_read = custom_ls_handler, + .mh_write = NULL}, + [CMD_RM] = { + .mh_read = NULL, + .mh_write = custom_rm_handler // Nutzung von WRITE für Löschvorgänge + }, +}; + +static struct mgmt_group custom_group = { + .mg_handlers = custom_handlers, + .mg_handlers_count = ARRAY_SIZE(custom_handlers), + .mg_group_id = CUSTOM_GROUP_ID, +}; + +#endif /* CONFIG_FS_MGMT_MCUMGR_HANDLER */ + int fs_mgmt_init(void) { int rc; @@ -74,5 +235,11 @@ int fs_mgmt_init(void) LOG_WRN("Filesystem statvfs failed (err %d)", rc); } } + +#ifdef CONFIG_FS_MGMT_MCUMGR_HANDLER + mgmt_register_group(&custom_group); + LOG_DBG("Custom MCUMGR group registered with ID %d", CUSTOM_GROUP_ID); +#endif /* CONFIG_FS_MGMT_MCUMGR_HANDLER */ + return 0; -} \ No newline at end of file +}