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 #if defined(CONFIG_DISK_DRIVER_MMC)
26 #define DISK_DRIVE_NAME "SD2"
27 #else
28 #define DISK_DRIVE_NAME "SD"
29 #endif
30
31 #define DISK_MOUNT_PT "/"DISK_DRIVE_NAME":"
32
33 static FATFS fat_fs;
34 /* mounting info */
35 static struct fs_mount_t mp = {
36 .type = FS_FATFS,
37 .fs_data = &fat_fs,
38 };
39
40 #elif defined(CONFIG_FILE_SYSTEM_EXT2)
41
42 #include <zephyr/fs/ext2.h>
43
44 #define DISK_DRIVE_NAME "SD"
45 #define DISK_MOUNT_PT "/ext"
46
47 static struct fs_mount_t mp = {
48 .type = FS_EXT2,
49 .flags = FS_MOUNT_FLAG_NO_FORMAT,
50 .storage_dev = (void *)DISK_DRIVE_NAME,
51 .mnt_point = "/ext",
52 };
53
54 #endif
55
56 #if defined(CONFIG_FAT_FILESYSTEM_ELM)
57 #define FS_RET_OK FR_OK
58 #else
59 #define FS_RET_OK 0
60 #endif
61
62 LOG_MODULE_REGISTER(main);
63
64 #define MAX_PATH 128
65 #define SOME_FILE_NAME "some.dat"
66 #define SOME_DIR_NAME "some"
67 #define SOME_REQUIRED_LEN MAX(sizeof(SOME_FILE_NAME), sizeof(SOME_DIR_NAME))
68
69 static int lsdir(const char *path);
70 #ifdef CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES
create_some_entries(const char * base_path)71 static bool create_some_entries(const char *base_path)
72 {
73 char path[MAX_PATH];
74 struct fs_file_t file;
75 int base = strlen(base_path);
76
77 fs_file_t_init(&file);
78
79 if (base >= (sizeof(path) - SOME_REQUIRED_LEN)) {
80 LOG_ERR("Not enough concatenation buffer to create file paths");
81 return false;
82 }
83
84 LOG_INF("Creating some dir entries in %s", base_path);
85 strncpy(path, base_path, sizeof(path));
86
87 path[base++] = '/';
88 path[base] = 0;
89 strcat(&path[base], SOME_FILE_NAME);
90
91 if (fs_open(&file, path, FS_O_CREATE) != 0) {
92 LOG_ERR("Failed to create file %s", path);
93 return false;
94 }
95 fs_close(&file);
96
97 path[base] = 0;
98 strcat(&path[base], SOME_DIR_NAME);
99
100 if (fs_mkdir(path) != 0) {
101 LOG_ERR("Failed to create dir %s", path);
102 /* If code gets here, it has at least successes to create the
103 * file so allow function to return true.
104 */
105 }
106 return true;
107 }
108 #endif
109
110 static const char *disk_mount_pt = DISK_MOUNT_PT;
111
main(void)112 int main(void)
113 {
114 /* raw disk i/o */
115 do {
116 static const char *disk_pdrv = DISK_DRIVE_NAME;
117 uint64_t memory_size_mb;
118 uint32_t block_count;
119 uint32_t block_size;
120
121 if (disk_access_ioctl(disk_pdrv,
122 DISK_IOCTL_CTRL_INIT, NULL) != 0) {
123 LOG_ERR("Storage init ERROR!");
124 break;
125 }
126
127 if (disk_access_ioctl(disk_pdrv,
128 DISK_IOCTL_GET_SECTOR_COUNT, &block_count)) {
129 LOG_ERR("Unable to get sector count");
130 break;
131 }
132 LOG_INF("Block count %u", block_count);
133
134 if (disk_access_ioctl(disk_pdrv,
135 DISK_IOCTL_GET_SECTOR_SIZE, &block_size)) {
136 LOG_ERR("Unable to get sector size");
137 break;
138 }
139 printk("Sector size %u\n", block_size);
140
141 memory_size_mb = (uint64_t)block_count * block_size;
142 printk("Memory Size(MB) %u\n", (uint32_t)(memory_size_mb >> 20));
143
144 if (disk_access_ioctl(disk_pdrv,
145 DISK_IOCTL_CTRL_DEINIT, NULL) != 0) {
146 LOG_ERR("Storage deinit ERROR!");
147 break;
148 }
149 } while (0);
150
151 mp.mnt_point = disk_mount_pt;
152
153 int res = fs_mount(&mp);
154
155 if (res == FS_RET_OK) {
156 printk("Disk mounted.\n");
157 /* Try to unmount and remount the disk */
158 res = fs_unmount(&mp);
159 if (res != FS_RET_OK) {
160 printk("Error unmounting disk\n");
161 return res;
162 }
163 res = fs_mount(&mp);
164 if (res != FS_RET_OK) {
165 printk("Error remounting disk\n");
166 return res;
167 }
168
169 if (lsdir(disk_mount_pt) == 0) {
170 #ifdef CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES
171 if (create_some_entries(disk_mount_pt)) {
172 lsdir(disk_mount_pt);
173 }
174 #endif
175 }
176 } else {
177 printk("Error mounting disk.\n");
178 }
179
180 fs_unmount(&mp);
181
182 while (1) {
183 k_sleep(K_MSEC(1000));
184 }
185 return 0;
186 }
187
188 /* List dir entry by path
189 *
190 * @param path Absolute path to list
191 *
192 * @return Negative errno code on error, number of listed entries on
193 * success.
194 */
lsdir(const char * path)195 static int lsdir(const char *path)
196 {
197 int res;
198 struct fs_dir_t dirp;
199 static struct fs_dirent entry;
200 int count = 0;
201
202 fs_dir_t_init(&dirp);
203
204 /* Verify fs_opendir() */
205 res = fs_opendir(&dirp, path);
206 if (res) {
207 printk("Error opening dir %s [%d]\n", path, res);
208 return res;
209 }
210
211 printk("\nListing dir %s ...\n", path);
212 for (;;) {
213 /* Verify fs_readdir() */
214 res = fs_readdir(&dirp, &entry);
215
216 /* entry.name[0] == 0 means end-of-dir */
217 if (res || entry.name[0] == 0) {
218 break;
219 }
220
221 if (entry.type == FS_DIR_ENTRY_DIR) {
222 printk("[DIR ] %s\n", entry.name);
223 } else {
224 printk("[FILE] %s (size = %zu)\n",
225 entry.name, entry.size);
226 }
227 count++;
228 }
229
230 /* Verify fs_closedir() */
231 fs_closedir(&dirp);
232 if (res == 0) {
233 res = count;
234 }
235
236 return res;
237 }
238