1 /*
2 * Copyright (c) 2019 Tavish Naruka <tavishnaruka@gmail.com>
3 * Copyright (c) 2023 Nordic Semiconductor ASA
4 * Copyright (c) 2023 Antmicro <www.antmicro.com>
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 /* Sample which uses the filesystem API and SDHC driver */
10
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <zephyr/storage/disk_access.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/fs/fs.h>
16
17 #if defined(CONFIG_FAT_FILESYSTEM_ELM)
18
19 #include <ff.h>
20
21 /*
22 * Note the fatfs library is able to mount only strings inside _VOLUME_STRS
23 * in ffconf.h
24 */
25 #define DISK_DRIVE_NAME "SD"
26 #define DISK_MOUNT_PT "/"DISK_DRIVE_NAME":"
27
28 static FATFS fat_fs;
29 /* mounting info */
30 static struct fs_mount_t mp = {
31 .type = FS_FATFS,
32 .fs_data = &fat_fs,
33 };
34
35 #elif defined(CONFIG_FILE_SYSTEM_EXT2)
36
37 #include <zephyr/fs/ext2.h>
38
39 #define DISK_DRIVE_NAME "SDMMC"
40 #define DISK_MOUNT_PT "/ext"
41
42 static struct fs_mount_t mp = {
43 .type = FS_EXT2,
44 .flags = FS_MOUNT_FLAG_NO_FORMAT,
45 .storage_dev = (void *)DISK_DRIVE_NAME,
46 .mnt_point = "/ext",
47 };
48
49 #endif
50
51 LOG_MODULE_REGISTER(main);
52
53 #define MAX_PATH 128
54 #define SOME_FILE_NAME "some.dat"
55 #define SOME_DIR_NAME "some"
56 #define SOME_REQUIRED_LEN MAX(sizeof(SOME_FILE_NAME), sizeof(SOME_DIR_NAME))
57
58 static int lsdir(const char *path);
59 #ifdef CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES
create_some_entries(const char * base_path)60 static bool create_some_entries(const char *base_path)
61 {
62 char path[MAX_PATH];
63 struct fs_file_t file;
64 int base = strlen(base_path);
65
66 fs_file_t_init(&file);
67
68 if (base >= (sizeof(path) - SOME_REQUIRED_LEN)) {
69 LOG_ERR("Not enough concatenation buffer to create file paths");
70 return false;
71 }
72
73 LOG_INF("Creating some dir entries in %s", base_path);
74 strncpy(path, base_path, sizeof(path));
75
76 path[base++] = '/';
77 path[base] = 0;
78 strcat(&path[base], SOME_FILE_NAME);
79
80 if (fs_open(&file, path, FS_O_CREATE) != 0) {
81 LOG_ERR("Failed to create file %s", path);
82 return false;
83 }
84 fs_close(&file);
85
86 path[base] = 0;
87 strcat(&path[base], SOME_DIR_NAME);
88
89 if (fs_mkdir(path) != 0) {
90 LOG_ERR("Failed to create dir %s", path);
91 /* If code gets here, it has at least successes to create the
92 * file so allow function to return true.
93 */
94 }
95 return true;
96 }
97 #endif
98
99 static const char *disk_mount_pt = DISK_MOUNT_PT;
100
main(void)101 int main(void)
102 {
103 /* raw disk i/o */
104 do {
105 static const char *disk_pdrv = DISK_DRIVE_NAME;
106 uint64_t memory_size_mb;
107 uint32_t block_count;
108 uint32_t block_size;
109
110 if (disk_access_init(disk_pdrv) != 0) {
111 LOG_ERR("Storage init ERROR!");
112 break;
113 }
114
115 if (disk_access_ioctl(disk_pdrv,
116 DISK_IOCTL_GET_SECTOR_COUNT, &block_count)) {
117 LOG_ERR("Unable to get sector count");
118 break;
119 }
120 LOG_INF("Block count %u", block_count);
121
122 if (disk_access_ioctl(disk_pdrv,
123 DISK_IOCTL_GET_SECTOR_SIZE, &block_size)) {
124 LOG_ERR("Unable to get sector size");
125 break;
126 }
127 printk("Sector size %u\n", block_size);
128
129 memory_size_mb = (uint64_t)block_count * block_size;
130 printk("Memory Size(MB) %u\n", (uint32_t)(memory_size_mb >> 20));
131 } while (0);
132
133 mp.mnt_point = disk_mount_pt;
134
135 int res = fs_mount(&mp);
136
137 #if defined(CONFIG_FAT_FILESYSTEM_ELM)
138 if (res == FR_OK) {
139 #else
140 if (res == 0) {
141 #endif
142 printk("Disk mounted.\n");
143 if (lsdir(disk_mount_pt) == 0) {
144 #ifdef CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES
145 if (create_some_entries(disk_mount_pt)) {
146 lsdir(disk_mount_pt);
147 }
148 #endif
149 }
150 } else {
151 printk("Error mounting disk.\n");
152 }
153
154 fs_unmount(&mp);
155
156 while (1) {
157 k_sleep(K_MSEC(1000));
158 }
159 return 0;
160 }
161
162 /* List dir entry by path
163 *
164 * @param path Absolute path to list
165 *
166 * @return Negative errno code on error, number of listed entries on
167 * success.
168 */
169 static int lsdir(const char *path)
170 {
171 int res;
172 struct fs_dir_t dirp;
173 static struct fs_dirent entry;
174 int count = 0;
175
176 fs_dir_t_init(&dirp);
177
178 /* Verify fs_opendir() */
179 res = fs_opendir(&dirp, path);
180 if (res) {
181 printk("Error opening dir %s [%d]\n", path, res);
182 return res;
183 }
184
185 printk("\nListing dir %s ...\n", path);
186 for (;;) {
187 /* Verify fs_readdir() */
188 res = fs_readdir(&dirp, &entry);
189
190 /* entry.name[0] == 0 means end-of-dir */
191 if (res || entry.name[0] == 0) {
192 break;
193 }
194
195 if (entry.type == FS_DIR_ENTRY_DIR) {
196 printk("[DIR ] %s\n", entry.name);
197 } else {
198 printk("[FILE] %s (size = %zu)\n",
199 entry.name, entry.size);
200 }
201 count++;
202 }
203
204 /* Verify fs_closedir() */
205 fs_closedir(&dirp);
206 if (res == 0) {
207 res = count;
208 }
209
210 return res;
211 }
212