1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  * Copyright (c) 2019-2020 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <sample_usbd.h>
9 
10 #include <zephyr/kernel.h>
11 #include <zephyr/logging/log.h>
12 #include <zephyr/usb/usbd.h>
13 #include <zephyr/usb/class/usbd_msc.h>
14 #include <zephyr/fs/fs.h>
15 #include <stdio.h>
16 
17 LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);
18 
19 #if CONFIG_DISK_DRIVER_FLASH
20 #include <zephyr/storage/flash_map.h>
21 #endif
22 
23 #if CONFIG_FAT_FILESYSTEM_ELM
24 #include <ff.h>
25 #endif
26 
27 #if CONFIG_FILE_SYSTEM_LITTLEFS
28 #include <zephyr/fs/littlefs.h>
29 FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage);
30 #endif
31 
32 #if !defined(CONFIG_DISK_DRIVER_FLASH) && \
33 	!defined(CONFIG_DISK_DRIVER_RAM) && \
34 	!defined(CONFIG_DISK_DRIVER_SDMMC)
35 #error No supported disk driver enabled
36 #endif
37 
38 #define STORAGE_PARTITION		storage_partition
39 #define STORAGE_PARTITION_ID		FIXED_PARTITION_ID(STORAGE_PARTITION)
40 
41 static struct fs_mount_t fs_mnt;
42 
43 static struct usbd_context *sample_usbd;
44 
45 #if CONFIG_DISK_DRIVER_RAM
46 USBD_DEFINE_MSC_LUN(ram, "RAM", "Zephyr", "RAMDisk", "0.00");
47 #endif
48 
49 #if CONFIG_DISK_DRIVER_FLASH
50 USBD_DEFINE_MSC_LUN(nand, "NAND", "Zephyr", "FlashDisk", "0.00");
51 #endif
52 
53 #if CONFIG_DISK_DRIVER_SDMMC
54 USBD_DEFINE_MSC_LUN(sd, "SD", "Zephyr", "SD", "0.00");
55 #endif
56 
setup_flash(struct fs_mount_t * mnt)57 static int setup_flash(struct fs_mount_t *mnt)
58 {
59 	int rc = 0;
60 #if CONFIG_DISK_DRIVER_FLASH
61 	unsigned int id;
62 	const struct flash_area *pfa;
63 
64 	mnt->storage_dev = (void *)STORAGE_PARTITION_ID;
65 	id = STORAGE_PARTITION_ID;
66 
67 	rc = flash_area_open(id, &pfa);
68 	printk("Area %u at 0x%x on %s for %u bytes\n",
69 	       id, (unsigned int)pfa->fa_off, pfa->fa_dev->name,
70 	       (unsigned int)pfa->fa_size);
71 
72 	if (rc < 0 && IS_ENABLED(CONFIG_APP_WIPE_STORAGE)) {
73 		printk("Erasing flash area ... ");
74 		rc = flash_area_flatten(pfa, 0, pfa->fa_size);
75 		printk("%d\n", rc);
76 	}
77 
78 	if (rc < 0) {
79 		flash_area_close(pfa);
80 	}
81 #endif
82 	return rc;
83 }
84 
mount_app_fs(struct fs_mount_t * mnt)85 static int mount_app_fs(struct fs_mount_t *mnt)
86 {
87 	int rc;
88 
89 #if CONFIG_FAT_FILESYSTEM_ELM
90 	static FATFS fat_fs;
91 
92 	mnt->type = FS_FATFS;
93 	mnt->fs_data = &fat_fs;
94 	if (IS_ENABLED(CONFIG_DISK_DRIVER_RAM)) {
95 		mnt->mnt_point = "/RAM:";
96 	} else if (IS_ENABLED(CONFIG_DISK_DRIVER_SDMMC)) {
97 		mnt->mnt_point = "/SD:";
98 	} else {
99 		mnt->mnt_point = "/NAND:";
100 	}
101 
102 #elif CONFIG_FILE_SYSTEM_LITTLEFS
103 	mnt->type = FS_LITTLEFS;
104 	mnt->mnt_point = "/lfs";
105 	mnt->fs_data = &storage;
106 #endif
107 	rc = fs_mount(mnt);
108 
109 	return rc;
110 }
111 
setup_disk(void)112 static void setup_disk(void)
113 {
114 	struct fs_mount_t *mp = &fs_mnt;
115 	struct fs_dir_t dir;
116 	struct fs_statvfs sbuf;
117 	int rc;
118 
119 	fs_dir_t_init(&dir);
120 
121 	if (IS_ENABLED(CONFIG_DISK_DRIVER_FLASH)) {
122 		rc = setup_flash(mp);
123 		if (rc < 0) {
124 			LOG_ERR("Failed to setup flash area");
125 			return;
126 		}
127 	}
128 
129 	if (!IS_ENABLED(CONFIG_FILE_SYSTEM_LITTLEFS) &&
130 	    !IS_ENABLED(CONFIG_FAT_FILESYSTEM_ELM)) {
131 		LOG_INF("No file system selected");
132 		return;
133 	}
134 
135 	rc = mount_app_fs(mp);
136 	if (rc < 0) {
137 		LOG_ERR("Failed to mount filesystem");
138 		return;
139 	}
140 
141 	/* Allow log messages to flush to avoid interleaved output */
142 	k_sleep(K_MSEC(50));
143 
144 	printk("Mount %s: %d\n", fs_mnt.mnt_point, rc);
145 
146 	rc = fs_statvfs(mp->mnt_point, &sbuf);
147 	if (rc < 0) {
148 		printk("FAIL: statvfs: %d\n", rc);
149 		return;
150 	}
151 
152 	printk("%s: bsize = %lu ; frsize = %lu ;"
153 	       " blocks = %lu ; bfree = %lu\n",
154 	       mp->mnt_point,
155 	       sbuf.f_bsize, sbuf.f_frsize,
156 	       sbuf.f_blocks, sbuf.f_bfree);
157 
158 	rc = fs_opendir(&dir, mp->mnt_point);
159 	printk("%s opendir: %d\n", mp->mnt_point, rc);
160 
161 	if (rc < 0) {
162 		LOG_ERR("Failed to open directory");
163 	}
164 
165 	while (rc >= 0) {
166 		struct fs_dirent ent = { 0 };
167 
168 		rc = fs_readdir(&dir, &ent);
169 		if (rc < 0) {
170 			LOG_ERR("Failed to read directory entries");
171 			break;
172 		}
173 		if (ent.name[0] == 0) {
174 			printk("End of files\n");
175 			break;
176 		}
177 		printk("  %c %zu %s\n",
178 		       (ent.type == FS_DIR_ENTRY_FILE) ? 'F' : 'D',
179 		       ent.size,
180 		       ent.name);
181 	}
182 
183 	(void)fs_closedir(&dir);
184 
185 	return;
186 }
187 
main(void)188 int main(void)
189 {
190 	int ret;
191 
192 	setup_disk();
193 
194 	sample_usbd = sample_usbd_init_device(NULL);
195 	if (sample_usbd == NULL) {
196 		LOG_ERR("Failed to initialize USB device");
197 		return -ENODEV;
198 	}
199 
200 	ret = usbd_enable(sample_usbd);
201 	if (ret) {
202 		LOG_ERR("Failed to enable device support");
203 		return ret;
204 	}
205 
206 	if (ret != 0) {
207 		LOG_ERR("Failed to enable USB");
208 		return 0;
209 	}
210 
211 	LOG_INF("The device is put in USB mass storage mode");
212 
213 	return 0;
214 }
215