Skip to content

Commit 696f67a

Browse files
koffesalexsven
authored andcommitted
bct: Added autocomplete and tests
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]>
1 parent 099cbba commit 696f67a

File tree

13 files changed

+716
-34
lines changed

13 files changed

+716
-34
lines changed

applications/nrf5340_audio/Kconfig.defaults

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,6 @@ endchoice
124124
config FS_FATFS_EXFAT
125125
default y
126126

127-
# Set the maximum file name length to 255
128-
config FS_FATFS_MAX_LFN
129-
default 255
130-
131127
config WATCHDOG
132128
default y
133129

applications/nrf5340_audio/src/modules/lc3_streamer.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static int stream_loop(struct lc3_stream *stream)
163163

164164
ret = lc3_file_open(&stream->file, stream->filename);
165165
if (ret) {
166-
LOG_ERR("Failed to open file %d", ret);
166+
LOG_ERR("Failed to open file %s: %d", stream->filename, ret);
167167
return ret;
168168
}
169169

@@ -369,8 +369,7 @@ int lc3_streamer_stream_register(const char *const filename, uint8_t *const stre
369369
return ret;
370370
}
371371

372-
strncpy(streams[*streamer_idx].filename, filename,
373-
ARRAY_SIZE(streams[*streamer_idx].filename));
372+
strncpy(streams[*streamer_idx].filename, filename, strlen(filename));
374373

375374
ret = data_fifo_init(&streams[*streamer_idx].fifo);
376375
if (ret) {

applications/nrf5340_audio/src/modules/sd_card.c

Lines changed: 187 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,20 @@
1414
#include <string.h>
1515
#include <zephyr/drivers/gpio.h>
1616
#include <zephyr/devicetree.h>
17+
#include <string.h>
1718

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

21-
#define SD_ROOT_PATH "/SD:/"
22-
/* Maximum length for path support by Windows file system */
23-
#define PATH_MAX_LEN 260
22+
#define SD_ROOT_PATH "/SD:/"
23+
/* Round down to closest 4-byte boundary */
24+
#define PATH_MAX_LEN ROUND_DOWN(CONFIG_FS_FATFS_MAX_LFN, 4)
25+
#define SD_CARD_LEVELS_MAX 8
26+
#define SD_CARD_BUF_SIZE 700
27+
28+
static uint32_t num_files_added;
29+
static struct k_mem_slab slab_A;
30+
static struct k_mem_slab slab_B;
2431

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

34-
int sd_card_list_files(char const *const path, char *buf, size_t *buf_size)
41+
/**
42+
* @brief Replaces first carriage return or line feed with null terminator.
43+
*/
44+
static void cr_lf_remove(char *str)
45+
{
46+
char *p = str;
47+
48+
while (*p != '\0') {
49+
if (*p == '\r' || *p == '\n') {
50+
*p = '\0';
51+
break;
52+
}
53+
p++;
54+
}
55+
}
56+
57+
/**
58+
* @brief Recursively traverse the SD card tree.
59+
*/
60+
static int traverse_down(char const *const path, uint8_t curr_depth, uint16_t result_file_num_max,
61+
uint16_t result_path_len_max, char result[][result_path_len_max],
62+
char const *const search_pattern)
63+
{
64+
int ret = 0;
65+
66+
if (curr_depth > SD_CARD_LEVELS_MAX) {
67+
LOG_WRN("At tree curr_depth %u, greater than %u", curr_depth, SD_CARD_LEVELS_MAX);
68+
return 0;
69+
}
70+
71+
char *slab_A_ptr;
72+
73+
ret = k_mem_slab_alloc(&slab_A, (void **)&slab_A_ptr, K_NO_WAIT);
74+
if (ret) {
75+
LOG_ERR("Failed to alloc slab A: %d", ret);
76+
return ret;
77+
}
78+
79+
char *slab_A_ptr_origin = slab_A_ptr;
80+
char *slab_B_ptr;
81+
82+
ret = k_mem_slab_alloc(&slab_B, (void **)&slab_B_ptr, K_NO_WAIT);
83+
if (ret) {
84+
k_mem_slab_free(&slab_A, (void *)slab_A_ptr_origin);
85+
LOG_ERR("Failed to alloc slab B: %d", ret);
86+
return ret;
87+
}
88+
89+
char *slab_B_ptr_origin = slab_B_ptr;
90+
size_t slab_A_ptr_size = SD_CARD_BUF_SIZE;
91+
92+
/* Search for folders */
93+
ret = sd_card_list_files(path, slab_A_ptr, &slab_A_ptr_size, false);
94+
if (ret == -ENOENT) {
95+
/* Not able to open, hence likely not a folder */
96+
ret = 0;
97+
goto cleanup;
98+
} else if (ret) {
99+
goto cleanup;
100+
}
101+
102+
LOG_DBG("At curr_depth %d tmp_buf is: %s", curr_depth, slab_A_ptr);
103+
104+
char *token = strtok_r(slab_A_ptr, "\r\n", &slab_A_ptr);
105+
106+
while (token != NULL) {
107+
if (strstr(token, "System Volume Information") != NULL) {
108+
/* Skipping System Volume Information */
109+
token = strtok_r(NULL, "\n", &slab_A_ptr);
110+
continue;
111+
}
112+
113+
cr_lf_remove(token);
114+
memset(slab_B_ptr, '\0', PATH_MAX_LEN);
115+
116+
if (path != NULL) {
117+
strcat(slab_B_ptr, path);
118+
cr_lf_remove(slab_B_ptr);
119+
strcat(slab_B_ptr, "/");
120+
}
121+
122+
strcat(slab_B_ptr, token);
123+
124+
if (strstr(token, search_pattern) != NULL) {
125+
if (num_files_added >= result_file_num_max) {
126+
LOG_WRN("Max file count reached %u", result_file_num_max);
127+
ret = -ENOMEM;
128+
goto cleanup;
129+
}
130+
strcpy(result[num_files_added], slab_B_ptr);
131+
num_files_added++;
132+
LOG_DBG("Added file num: %d at: %s", num_files_added, slab_B_ptr);
133+
134+
} else {
135+
ret = traverse_down(slab_B_ptr, curr_depth + 1, result_file_num_max,
136+
result_path_len_max, result, search_pattern);
137+
if (ret) {
138+
LOG_ERR("Failed to traverse down: %d", ret);
139+
}
140+
}
141+
142+
token = strtok_r(NULL, "\n", &slab_A_ptr);
143+
}
144+
145+
cleanup:
146+
k_mem_slab_free(&slab_A, (void *)slab_A_ptr_origin);
147+
k_mem_slab_free(&slab_B, (void *)slab_B_ptr_origin);
148+
return ret;
149+
}
150+
151+
int sd_card_list_files_match(uint16_t result_file_num_max, uint16_t result_path_len_max,
152+
char result[][result_path_len_max], char *path,
153+
char const *const search_pattern)
154+
{
155+
int ret;
156+
157+
num_files_added = 0;
158+
159+
if (result == NULL) {
160+
return -EINVAL;
161+
}
162+
163+
if (result_file_num_max == 0) {
164+
return -EINVAL;
165+
}
166+
167+
if (result_path_len_max == 0 || (result_path_len_max > PATH_MAX_LEN)) {
168+
return -EINVAL;
169+
}
170+
171+
if (search_pattern == NULL) {
172+
return -EINVAL;
173+
}
174+
175+
char __aligned(4) buf_A[SD_CARD_BUF_SIZE * SD_CARD_LEVELS_MAX] = {'\0'};
176+
char __aligned(4) buf_B[PATH_MAX_LEN * SD_CARD_LEVELS_MAX] = {'\0'};
177+
178+
ret = k_mem_slab_init(&slab_A, buf_A, SD_CARD_BUF_SIZE, SD_CARD_LEVELS_MAX);
179+
if (ret) {
180+
LOG_ERR("Failed to init slab: %d", ret);
181+
return ret;
182+
}
183+
184+
ret = k_mem_slab_init(&slab_B, buf_B, PATH_MAX_LEN, SD_CARD_LEVELS_MAX);
185+
if (ret) {
186+
LOG_ERR("Failed to init slab: %d", ret);
187+
return ret;
188+
}
189+
190+
ret = traverse_down(path, 0, result_file_num_max, result_path_len_max, result,
191+
search_pattern);
192+
if (ret) {
193+
return ret;
194+
}
195+
196+
return num_files_added;
197+
}
198+
199+
int sd_card_list_files(char const *const path, char *buf, size_t *buf_size, bool extra_info)
35200
{
36201
int ret;
37202
struct fs_dir_t dirp;
@@ -44,7 +209,6 @@ int sd_card_list_files(char const *const path, char *buf, size_t *buf_size)
44209
}
45210

46211
fs_dir_t_init(&dirp);
47-
48212
if (path == NULL) {
49213
ret = fs_opendir(&dirp, sd_root_path);
50214
if (ret) {
@@ -59,9 +223,14 @@ int sd_card_list_files(char const *const path, char *buf, size_t *buf_size)
59223

60224
strcat(abs_path_name, path);
61225

226+
if (strchr(abs_path_name, '.')) {
227+
/* Path contains a dot. Regarded as not a folder*/
228+
return -ENOENT;
229+
}
230+
62231
ret = fs_opendir(&dirp, abs_path_name);
63232
if (ret) {
64-
LOG_ERR("Open assigned path failed");
233+
LOG_ERR("Open assigned path failed %d. %s", ret, abs_path_name);
65234
return ret;
66235
}
67236
}
@@ -78,9 +247,17 @@ int sd_card_list_files(char const *const path, char *buf, size_t *buf_size)
78247

79248
if (buf != NULL) {
80249
size_t remaining_buf_size = *buf_size - used_buf_size;
81-
ssize_t len = snprintk(
82-
&buf[used_buf_size], remaining_buf_size, "[%s]\t%s\n",
83-
entry.type == FS_DIR_ENTRY_DIR ? "DIR " : "FILE", entry.name);
250+
ssize_t len;
251+
252+
if (extra_info) {
253+
len = snprintk(&buf[used_buf_size], remaining_buf_size,
254+
"[%s]\t%s\r\n",
255+
entry.type == FS_DIR_ENTRY_DIR ? "DIR " : "FILE",
256+
entry.name);
257+
} else {
258+
len = snprintk(&buf[used_buf_size], remaining_buf_size, "%s\r\n",
259+
entry.name);
260+
}
84261

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

291468
sd_card_size_bytes = (uint64_t)sector_count * sector_size;
292469

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

295472
mnt_pt.mnt_point = sd_root_path;
296473

applications/nrf5340_audio/src/modules/sd_card.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,40 @@
1010
#include <stddef.h>
1111
#include <zephyr/fs/fs.h>
1212

13+
/**
14+
* @brief Finds all files on SD card that match the given pattern.
15+
*
16+
* @note The function uses a recursive approach with internal buffers. Memory intensive.
17+
*
18+
* @param[in] result_file_num_max Maximum number of files to be found.
19+
* @param[in] result_file_len_max Maximum length of each file name including total path length
20+
* @param[out] result Pointer to the result array of dimension result_file_num_max
21+
* * result_file_len_max.
22+
* @param[in] path NULL, search from root, otherwise search from the given path.
23+
* Note not to add an ending "/"
24+
* @param[in] pattern Null terminated pattern to find, e.g. *.lc3 or *.wav
25+
* @retval Number of files found.
26+
* @retval -EINVAL invalid parameters.
27+
* @retval -ENOMEM out of memory.
28+
* @retval -ENODEV SD init failed. SD likely not inserted.
29+
* @retval -EPERM SD card operation is ongoing somewhere else.
30+
* @retval -Other, error from underlying drivers.
31+
*/
32+
int sd_card_list_files_match(uint16_t result_file_num_max, uint16_t result_file_len_max,
33+
char result[][result_file_len_max], char *path,
34+
char const *const pattern);
35+
1336
/**
1437
* @brief Print out the contents under SD card root path and write the content to buffer.
1538
*
1639
* @param[in] path Path of the folder which is going to be listed.
17-
* If assigned path is null, then listing the contents under
40+
* If assigned path is NULL, then listing the contents under
1841
* root. If assigned path doesn't exist, an error will be
1942
* returned.
2043
* @param[out] buf Buffer where data is written. If set to NULL, it will be
2144
* ignored.
2245
* @param[in, out] buf_size Buffer size.
46+
* @param[in] extra_info Will append DIR/FILE info to string.
2347
*
2448
* @retval 0 on success.
2549
* @retval -EPERM SD card operation is ongoing somewhere else.
@@ -28,7 +52,7 @@
2852
* @retval -FR_INVALID_NAME Path is too long.
2953
* @retval Otherwise, error from underlying drivers.
3054
*/
31-
int sd_card_list_files(char const *const path, char *buf, size_t *buf_size);
55+
int sd_card_list_files(char const *const path, char *buf, size_t *buf_size, bool extra_info);
3256

3357
/**
3458
* @brief Write data from buffer into the file.

applications/nrf5340_audio/src/modules/sd_card_playback.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ static int cmd_list_files(const struct shell *shell, size_t argc, char **argv)
564564
char buf[LIST_FILES_BUF_SIZE];
565565
size_t buf_size = LIST_FILES_BUF_SIZE;
566566

567-
ret = sd_card_list_files(playback_file_path, buf, &buf_size);
567+
ret = sd_card_list_files(playback_file_path, buf, &buf_size, true);
568568
if (ret) {
569569
shell_error(shell, "List files err: %d", ret);
570570
return ret;

samples/bluetooth/broadcast_config_tool/prj.conf

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ CONFIG_THREAD_RUNTIME_STATS=y
1515
CONFIG_MAIN_THREAD_PRIORITY=10
1616
CONFIG_STACK_SENTINEL=y
1717
CONFIG_INIT_STACKS=y
18-
CONFIG_MAIN_STACK_SIZE=1800
18+
CONFIG_MAIN_STACK_SIZE=12000
1919
CONFIG_THREAD_NAME=y
2020
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1200
2121

@@ -27,9 +27,11 @@ CONFIG_LOG=y
2727
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
2828
CONFIG_LOG_TAG_MAX_LEN=2
2929
CONFIG_LOG_TAG_DEFAULT="--"
30-
CONFIG_USE_SEGGER_RTT=y
31-
CONFIG_LOG_BACKEND_RTT=y
30+
3231
CONFIG_LOG_BUFFER_SIZE=4096
32+
CONFIG_USE_SEGGER_RTT=n
33+
CONFIG_LOG_BACKEND_RTT=n
34+
3335
CONFIG_SOC_NRF53_CPUNET_ENABLE=y
3436

3537
CONFIG_ZBUS=y
@@ -94,7 +96,7 @@ CONFIG_KERNEL_SHELL=y
9496
CONFIG_SHELL_BACKEND_SERIAL=y
9597
CONFIG_SHELL_VT100_COMMANDS=y
9698
CONFIG_SHELL_VT100_COLORS=y
97-
CONFIG_SHELL_STACK_SIZE=4096
99+
CONFIG_SHELL_STACK_SIZE=8096
98100
CONFIG_SHELL_CMD_BUFF_SIZE=128
99101
## Reduce shell memory usage
100102
CONFIG_SHELL_WILDCARD=n
@@ -148,6 +150,7 @@ CONFIG_SW_CODEC_LC3=n
148150
CONFIG_NRF5340_AUDIO_SD_CARD_MODULE=y
149151
CONFIG_NRF5340_AUDIO_SD_CARD_LC3_FILE=y
150152
CONFIG_NRF5340_AUDIO_SD_CARD_LC3_STREAMER=y
151-
CONFIG_SD_CARD_LC3_STREAMER_STACK_SIZE=3000
153+
154+
CONFIG_SD_CARD_LC3_STREAMER_STACK_SIZE=8000
152155

153156
CONFIG_MODULE_SD_CARD_LOG_LEVEL_WRN=y

0 commit comments

Comments
 (0)