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