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