Skip to content

Commit

Permalink
bct: Added autocomplete and tests
Browse files Browse the repository at this point in the history
OCT-3137
Working autocomplete with test for the broadcaster tester tool.

Signed-off-by: Kristoffer Rist Skøien <[email protected]>
Co-authored-by: Alexander Svensen <[email protected]>
  • Loading branch information
koffes and alexsven committed Oct 23, 2024
1 parent 07697de commit 54e4384
Show file tree
Hide file tree
Showing 13 changed files with 716 additions and 34 deletions.
4 changes: 0 additions & 4 deletions applications/nrf5340_audio/Kconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,6 @@ endchoice
config FS_FATFS_EXFAT
default y

# Set the maximum file name length to 255
config FS_FATFS_MAX_LFN
default 255

config WATCHDOG
default y

Expand Down
5 changes: 2 additions & 3 deletions applications/nrf5340_audio/src/modules/lc3_streamer.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ static int stream_loop(struct lc3_stream *stream)

ret = lc3_file_open(&stream->file, stream->filename);
if (ret) {
LOG_ERR("Failed to open file %d", ret);
LOG_ERR("Failed to open file %s: %d", stream->filename, ret);
return ret;
}

Expand Down Expand Up @@ -369,8 +369,7 @@ int lc3_streamer_stream_register(const char *const filename, uint8_t *const stre
return ret;
}

strncpy(streams[*streamer_idx].filename, filename,
ARRAY_SIZE(streams[*streamer_idx].filename));
strncpy(streams[*streamer_idx].filename, filename, strlen(filename));

ret = data_fifo_init(&streams[*streamer_idx].fifo);
if (ret) {
Expand Down
197 changes: 187 additions & 10 deletions applications/nrf5340_audio/src/modules/sd_card.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,20 @@
#include <string.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/devicetree.h>
#include <string.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(sd_card, CONFIG_MODULE_SD_CARD_LOG_LEVEL);

#define SD_ROOT_PATH "/SD:/"
/* Maximum length for path support by Windows file system */
#define PATH_MAX_LEN 260
#define SD_ROOT_PATH "/SD:/"
/* Round down to closest 4-byte boundary */
#define PATH_MAX_LEN ROUND_DOWN(CONFIG_FS_FATFS_MAX_LFN, 4)
#define SD_CARD_LEVELS_MAX 8
#define SD_CARD_BUF_SIZE 700

static uint32_t num_files_added;
static struct k_mem_slab slab_A;
static struct k_mem_slab slab_B;

static const char *sd_root_path = "/SD:";
static FATFS fat_fs;
Expand All @@ -31,7 +38,165 @@ static struct fs_mount_t mnt_pt = {
.fs_data = &fat_fs,
};

int sd_card_list_files(char const *const path, char *buf, size_t *buf_size)
/**
* @brief Replaces first carriage return or line feed with null terminator.
*/
static void cr_lf_remove(char *str)
{
char *p = str;

while (*p != '\0') {
if (*p == '\r' || *p == '\n') {
*p = '\0';
break;
}
p++;
}
}

/**
* @brief Recursively traverse the SD card tree.
*/
static int traverse_down(char const *const path, uint8_t curr_depth, uint16_t result_file_num_max,
uint16_t result_path_len_max, char result[][result_path_len_max],
char const *const search_pattern)
{
int ret = 0;

if (curr_depth > SD_CARD_LEVELS_MAX) {
LOG_WRN("At tree curr_depth %u, greater than %u", curr_depth, SD_CARD_LEVELS_MAX);
return 0;
}

char *slab_A_ptr;

ret = k_mem_slab_alloc(&slab_A, (void **)&slab_A_ptr, K_NO_WAIT);
if (ret) {
LOG_ERR("Failed to alloc slab A: %d", ret);
return ret;
}

char *slab_A_ptr_origin = slab_A_ptr;
char *slab_B_ptr;

ret = k_mem_slab_alloc(&slab_B, (void **)&slab_B_ptr, K_NO_WAIT);
if (ret) {
k_mem_slab_free(&slab_A, (void *)slab_A_ptr_origin);
LOG_ERR("Failed to alloc slab B: %d", ret);
return ret;
}

char *slab_B_ptr_origin = slab_B_ptr;
size_t slab_A_ptr_size = SD_CARD_BUF_SIZE;

/* Search for folders */
ret = sd_card_list_files(path, slab_A_ptr, &slab_A_ptr_size, false);
if (ret == -ENOENT) {
/* Not able to open, hence likely not a folder */
ret = 0;
goto cleanup;
} else if (ret) {
goto cleanup;
}

LOG_DBG("At curr_depth %d tmp_buf is: %s", curr_depth, slab_A_ptr);

char *token = strtok_r(slab_A_ptr, "\r\n", &slab_A_ptr);

while (token != NULL) {
if (strstr(token, "System Volume Information") != NULL) {
/* Skipping System Volume Information */
token = strtok_r(NULL, "\n", &slab_A_ptr);
continue;
}

cr_lf_remove(token);
memset(slab_B_ptr, '\0', PATH_MAX_LEN);

if (path != NULL) {
strcat(slab_B_ptr, path);
cr_lf_remove(slab_B_ptr);
strcat(slab_B_ptr, "/");
}

strcat(slab_B_ptr, token);

if (strstr(token, search_pattern) != NULL) {
if (num_files_added >= result_file_num_max) {
LOG_WRN("Max file count reached %u", result_file_num_max);
ret = -ENOMEM;
goto cleanup;
}
strcpy(result[num_files_added], slab_B_ptr);
num_files_added++;
LOG_DBG("Added file num: %d at: %s", num_files_added, slab_B_ptr);

} else {
ret = traverse_down(slab_B_ptr, curr_depth + 1, result_file_num_max,
result_path_len_max, result, search_pattern);
if (ret) {
LOG_ERR("Failed to traverse down: %d", ret);
}
}

token = strtok_r(NULL, "\n", &slab_A_ptr);
}

cleanup:
k_mem_slab_free(&slab_A, (void *)slab_A_ptr_origin);
k_mem_slab_free(&slab_B, (void *)slab_B_ptr_origin);
return ret;
}

int sd_card_list_files_match(uint16_t result_file_num_max, uint16_t result_path_len_max,
char result[][result_path_len_max], char *path,
char const *const search_pattern)
{
int ret;

num_files_added = 0;

if (result == NULL) {
return -EINVAL;
}

if (result_file_num_max == 0) {
return -EINVAL;
}

if (result_path_len_max == 0 || (result_path_len_max > PATH_MAX_LEN)) {
return -EINVAL;
}

if (search_pattern == NULL) {
return -EINVAL;
}

char __aligned(4) buf_A[SD_CARD_BUF_SIZE * SD_CARD_LEVELS_MAX] = {'\0'};
char __aligned(4) buf_B[PATH_MAX_LEN * SD_CARD_LEVELS_MAX] = {'\0'};

ret = k_mem_slab_init(&slab_A, buf_A, SD_CARD_BUF_SIZE, SD_CARD_LEVELS_MAX);
if (ret) {
LOG_ERR("Failed to init slab: %d", ret);
return ret;
}

ret = k_mem_slab_init(&slab_B, buf_B, PATH_MAX_LEN, SD_CARD_LEVELS_MAX);
if (ret) {
LOG_ERR("Failed to init slab: %d", ret);
return ret;
}

ret = traverse_down(path, 0, result_file_num_max, result_path_len_max, result,
search_pattern);
if (ret) {
return ret;
}

return num_files_added;
}

int sd_card_list_files(char const *const path, char *buf, size_t *buf_size, bool extra_info)
{
int ret;
struct fs_dir_t dirp;
Expand All @@ -44,7 +209,6 @@ int sd_card_list_files(char const *const path, char *buf, size_t *buf_size)
}

fs_dir_t_init(&dirp);

if (path == NULL) {
ret = fs_opendir(&dirp, sd_root_path);
if (ret) {
Expand All @@ -59,9 +223,14 @@ int sd_card_list_files(char const *const path, char *buf, size_t *buf_size)

strcat(abs_path_name, path);

if (strchr(abs_path_name, '.')) {
/* Path contains a dot. Regarded as not a folder*/
return -ENOENT;
}

ret = fs_opendir(&dirp, abs_path_name);
if (ret) {
LOG_ERR("Open assigned path failed");
LOG_ERR("Open assigned path failed %d. %s", ret, abs_path_name);
return ret;
}
}
Expand All @@ -78,9 +247,17 @@ int sd_card_list_files(char const *const path, char *buf, size_t *buf_size)

if (buf != NULL) {
size_t remaining_buf_size = *buf_size - used_buf_size;
ssize_t len = snprintk(
&buf[used_buf_size], remaining_buf_size, "[%s]\t%s\n",
entry.type == FS_DIR_ENTRY_DIR ? "DIR " : "FILE", entry.name);
ssize_t len;

if (extra_info) {
len = snprintk(&buf[used_buf_size], remaining_buf_size,
"[%s]\t%s\r\n",
entry.type == FS_DIR_ENTRY_DIR ? "DIR " : "FILE",
entry.name);
} else {
len = snprintk(&buf[used_buf_size], remaining_buf_size, "%s\r\n",
entry.name);
}

if (len >= remaining_buf_size) {
LOG_ERR("Failed to append to buffer, error: %d", len);
Expand Down Expand Up @@ -290,7 +467,7 @@ int sd_card_init(void)

sd_card_size_bytes = (uint64_t)sector_count * sector_size;

LOG_INF("SD card volume size: %d MB", (uint32_t)(sd_card_size_bytes >> 20));
LOG_INF("SD card volume size: %lld B", sd_card_size_bytes);

mnt_pt.mnt_point = sd_root_path;

Expand Down
28 changes: 26 additions & 2 deletions applications/nrf5340_audio/src/modules/sd_card.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,40 @@
#include <stddef.h>
#include <zephyr/fs/fs.h>

/**
* @brief Finds all files on SD card that match the given pattern.
*
* @note The function uses a recursive approach with internal buffers. Memory intensive.
*
* @param[in] result_file_num_max Maximum number of files to be found.
* @param[in] result_file_len_max Maximum length of each file name including total path length
* @param[out] result Pointer to the result array of dimension result_file_num_max
* * result_file_len_max.
* @param[in] path NULL, search from root, otherwise search from the given path.
* Note not to add an ending "/"
* @param[in] pattern Null terminated pattern to find, e.g. *.lc3 or *.wav
* @retval Number of files found.
* @retval -EINVAL invalid parameters.
* @retval -ENOMEM out of memory.
* @retval -ENODEV SD init failed. SD likely not inserted.
* @retval -EPERM SD card operation is ongoing somewhere else.
* @retval -Other, error from underlying drivers.
*/
int sd_card_list_files_match(uint16_t result_file_num_max, uint16_t result_file_len_max,
char result[][result_file_len_max], char *path,
char const *const pattern);

/**
* @brief Print out the contents under SD card root path and write the content to buffer.
*
* @param[in] path Path of the folder which is going to be listed.
* If assigned path is null, then listing the contents under
* If assigned path is NULL, then listing the contents under
* root. If assigned path doesn't exist, an error will be
* returned.
* @param[out] buf Buffer where data is written. If set to NULL, it will be
* ignored.
* @param[in, out] buf_size Buffer size.
* @param[in] extra_info Will append DIR/FILE info to string.
*
* @retval 0 on success.
* @retval -EPERM SD card operation is ongoing somewhere else.
Expand All @@ -28,7 +52,7 @@
* @retval -FR_INVALID_NAME Path is too long.
* @retval Otherwise, error from underlying drivers.
*/
int sd_card_list_files(char const *const path, char *buf, size_t *buf_size);
int sd_card_list_files(char const *const path, char *buf, size_t *buf_size, bool extra_info);

/**
* @brief Write data from buffer into the file.
Expand Down
2 changes: 1 addition & 1 deletion applications/nrf5340_audio/src/modules/sd_card_playback.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ static int cmd_list_files(const struct shell *shell, size_t argc, char **argv)
char buf[LIST_FILES_BUF_SIZE];
size_t buf_size = LIST_FILES_BUF_SIZE;

ret = sd_card_list_files(playback_file_path, buf, &buf_size);
ret = sd_card_list_files(playback_file_path, buf, &buf_size, true);
if (ret) {
shell_error(shell, "List files err: %d", ret);
return ret;
Expand Down
13 changes: 8 additions & 5 deletions samples/bluetooth/broadcast_config_tool/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ CONFIG_THREAD_RUNTIME_STATS=y
CONFIG_MAIN_THREAD_PRIORITY=10
CONFIG_STACK_SENTINEL=y
CONFIG_INIT_STACKS=y
CONFIG_MAIN_STACK_SIZE=1800
CONFIG_MAIN_STACK_SIZE=12000
CONFIG_THREAD_NAME=y
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1200

Expand All @@ -27,9 +27,11 @@ CONFIG_LOG=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
CONFIG_LOG_TAG_MAX_LEN=2
CONFIG_LOG_TAG_DEFAULT="--"
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=y

CONFIG_LOG_BUFFER_SIZE=4096
CONFIG_USE_SEGGER_RTT=n
CONFIG_LOG_BACKEND_RTT=n

CONFIG_SOC_NRF53_CPUNET_ENABLE=y

CONFIG_ZBUS=y
Expand Down Expand Up @@ -94,7 +96,7 @@ CONFIG_KERNEL_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_SHELL_VT100_COMMANDS=y
CONFIG_SHELL_VT100_COLORS=y
CONFIG_SHELL_STACK_SIZE=4096
CONFIG_SHELL_STACK_SIZE=8096
CONFIG_SHELL_CMD_BUFF_SIZE=128
## Reduce shell memory usage
CONFIG_SHELL_WILDCARD=n
Expand Down Expand Up @@ -148,6 +150,7 @@ CONFIG_SW_CODEC_LC3=n
CONFIG_NRF5340_AUDIO_SD_CARD_MODULE=y
CONFIG_NRF5340_AUDIO_SD_CARD_LC3_FILE=y
CONFIG_NRF5340_AUDIO_SD_CARD_LC3_STREAMER=y
CONFIG_SD_CARD_LC3_STREAMER_STACK_SIZE=3000

CONFIG_SD_CARD_LC3_STREAMER_STACK_SIZE=8000

CONFIG_MODULE_SD_CARD_LOG_LEVEL_WRN=y
Loading

0 comments on commit 54e4384

Please sign in to comment.