FatFS driver templates.
@@ -43,6 +43,7 @@ | ||
43 | 43 | |
44 | 44 | static NullStream null; |
45 | 45 | |
46 | +/* Stream to be exposed under /dev as files.*/ | |
46 | 47 | static const drv_stream_element_t streams[] = { |
47 | 48 | {"VSD1", (BaseSequentialStream *)&PORTAB_SD1}, |
48 | 49 | {"null", (BaseSequentialStream *)&null}, |
@@ -0,0 +1,400 @@ | ||
1 | +/* | |
2 | + ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | |
3 | + 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | |
4 | + | |
5 | + This file is part of ChibiOS. | |
6 | + | |
7 | + ChibiOS is free software; you can redistribute it and/or modify | |
8 | + it under the terms of the GNU General Public License as published by | |
9 | + the Free Software Foundation version 3 of the License. | |
10 | + | |
11 | + ChibiOS is distributed in the hope that it will be useful, | |
12 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + GNU General Public License for more details. | |
15 | + | |
16 | + You should have received a copy of the GNU General Public License | |
17 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | +*/ | |
19 | + | |
20 | +/** | |
21 | + * @file vfs/drivers/drvfatfs.c | |
22 | + * @brief HAL FatFS VFS driver code. | |
23 | + * | |
24 | + * @addtogroup VFS_DRV_FATFS | |
25 | + * @{ | |
26 | + */ | |
27 | + | |
28 | +#include <string.h> | |
29 | + | |
30 | +#include "vfs.h" | |
31 | +#include "drvfatfs.h" | |
32 | + | |
33 | +#include "ff.h" | |
34 | + | |
35 | +/*===========================================================================*/ | |
36 | +/* Module local definitions. */ | |
37 | +/*===========================================================================*/ | |
38 | + | |
39 | +/** | |
40 | + * @brief Number of directory nodes pre-allocated in the pool. | |
41 | + */ | |
42 | +#define DRV_DIR_NODES_NUM 1 | |
43 | + | |
44 | +/** | |
45 | + * @brief Number of file nodes pre-allocated in the pool. | |
46 | + */ | |
47 | +#define DRV_FILE_NODES_NUM 2 | |
48 | + | |
49 | +/** | |
50 | + * @brief @p vfs_fatfs_driver_t specific methods. | |
51 | + */ | |
52 | +#define __vfs_fatfs_driver_methods \ | |
53 | + __vfs_driver_methods | |
54 | + | |
55 | +/** | |
56 | + * @brief @p vfs_fatfs_driver_t specific data. | |
57 | + */ | |
58 | +#define __vfs_fatfs_driver_data \ | |
59 | + __vfs_driver_data \ | |
60 | + memory_pool_t file_nodes_pool; \ | |
61 | + memory_pool_t dir_nodes_pool; | |
62 | + | |
63 | +/** | |
64 | + * @brief @p vfs_fatfs_dir_node_t specific methods. | |
65 | + */ | |
66 | +#define __vfs_fatfs_dir_node_methods \ | |
67 | + __vfs_directory_node_methods | |
68 | + | |
69 | +/** | |
70 | + * @brief @p vfs_fatfs_dir_node_t specific data. | |
71 | + */ | |
72 | +#define __vfs_fatfs_dir_node_data \ | |
73 | + __vfs_directory_node_data \ | |
74 | + unsigned index; | |
75 | + | |
76 | +/** | |
77 | + * @brief @p vfs_fatfs_file_node_t specific methods. | |
78 | + */ | |
79 | +#define __vfs_fatfs_file_node_methods \ | |
80 | + __vfs_file_node_methods | |
81 | + | |
82 | +/** | |
83 | + * @brief @p vfs_fatfs_file_node_t specific data. | |
84 | + */ | |
85 | +#define __vfs_fatfs_file_node_data \ | |
86 | + __vfs_file_node_data \ | |
87 | + BaseSequentialStream *stream; | |
88 | + | |
89 | +/*===========================================================================*/ | |
90 | +/* Module exported variables. */ | |
91 | +/*===========================================================================*/ | |
92 | + | |
93 | +/*===========================================================================*/ | |
94 | +/* Module local types. */ | |
95 | +/*===========================================================================*/ | |
96 | + | |
97 | +/** | |
98 | + * @brief @p vfs_fatfs_driver_t virtual methods table. | |
99 | + */ | |
100 | +struct vfs_fatfs_driver_vmt { | |
101 | + __vfs_fatfs_driver_methods | |
102 | +}; | |
103 | + | |
104 | +/** | |
105 | + * @brief Type of a structure representing a VFS FatFS driver. | |
106 | + */ | |
107 | +typedef struct vfs_drv_streams { | |
108 | + /** | |
109 | + * @brief Virtual Methods Table. | |
110 | + */ | |
111 | + const struct vfs_fatfs_driver_vmt *vmt; | |
112 | + __vfs_fatfs_driver_data | |
113 | +} vfs_fatfs_driver_t; | |
114 | + | |
115 | +/** | |
116 | + * @brief @p vfs_fatfs_dir_node_t virtual methods table. | |
117 | + */ | |
118 | +struct vfs_fatfs_dir_node_vmt { | |
119 | + __vfs_fatfs_dir_node_methods | |
120 | +}; | |
121 | + | |
122 | +/** | |
123 | + * @brief Type of a structure representing a FatFS directory VFS node. | |
124 | + */ | |
125 | +typedef struct vfs_fatfs_dir_node { | |
126 | + /** | |
127 | + * @brief Virtual Methods Table. | |
128 | + */ | |
129 | + const struct vfs_fatfs_dir_node_vmt *vmt; | |
130 | + __vfs_fatfs_dir_node_data | |
131 | +} vfs_fatfs_dir_node_t; | |
132 | + | |
133 | +/** | |
134 | + * @brief @p vfs_fatfs_file_node_t virtual methods table. | |
135 | + */ | |
136 | +struct vfs_fatfs_file_node_vmt { | |
137 | + __vfs_fatfs_file_node_methods | |
138 | +}; | |
139 | + | |
140 | +/** | |
141 | + * @brief Type of a structure representing a FatFS file VFS node. | |
142 | + */ | |
143 | +typedef struct vfs_fatfs_file_node { | |
144 | + /** | |
145 | + * @brief Virtual Methods Table. | |
146 | + */ | |
147 | + const struct vfs_fatfs_file_node_vmt *vmt; | |
148 | + __vfs_fatfs_file_node_data | |
149 | +} vfs_fatfs_file_node_t; | |
150 | + | |
151 | +/*===========================================================================*/ | |
152 | +/* Module local variables. */ | |
153 | +/*===========================================================================*/ | |
154 | + | |
155 | +static msg_t drv_open_dir(void *instance, | |
156 | + const char *path, | |
157 | + vfs_directory_node_t **vdnpp); | |
158 | +static msg_t drv_open_file(void *instance, | |
159 | + const char *path, | |
160 | + vfs_file_node_t **vfnpp); | |
161 | + | |
162 | +static const struct vfs_fatfs_driver_vmt driver_vmt = { | |
163 | + .open_dir = drv_open_dir, | |
164 | + .open_file = drv_open_file | |
165 | +}; | |
166 | + | |
167 | +static void node_dir_release(void *instance); | |
168 | +static msg_t node_dir_first(void *instance, vfs_node_info_t *nip); | |
169 | +static msg_t node_dir_next(void *instance, vfs_node_info_t *nip); | |
170 | + | |
171 | +static const struct vfs_fatfs_dir_node_vmt dir_node_vmt = { | |
172 | + .release = node_dir_release, | |
173 | + .dir_first = node_dir_first, | |
174 | + .dir_next = node_dir_next | |
175 | +}; | |
176 | + | |
177 | +static void node_file_release(void *instance); | |
178 | +static BaseSequentialStream *node_file_get_stream(void *instance); | |
179 | +static ssize_t node_file_read(void *instance, uint8_t *buf, size_t n); | |
180 | +static ssize_t node_file_write(void *instance, const uint8_t *buf, size_t n); | |
181 | +static msg_t node_file_setpos(void *instance, vfs_offset_t offset); | |
182 | +static vfs_offset_t node_file_getpos(void *instance); | |
183 | +static vfs_offset_t node_file_getsize(void *instance); | |
184 | + | |
185 | +static const struct vfs_fatfs_file_node_vmt file_node_vmt = { | |
186 | + .release = node_file_release, | |
187 | + .get_stream = node_file_get_stream, | |
188 | + .file_read = node_file_read, | |
189 | + .file_write = node_file_write, | |
190 | + .file_setpos = node_file_setpos, | |
191 | + .file_getpos = node_file_getpos, | |
192 | + .file_getsize = node_file_getsize | |
193 | +}; | |
194 | + | |
195 | +static vfs_fatfs_dir_node_t drv_dir_nodes[DRV_DIR_NODES_NUM]; | |
196 | +static vfs_fatfs_file_node_t drv_file_nodes[DRV_FILE_NODES_NUM]; | |
197 | + | |
198 | +static vfs_fatfs_driver_t drv_streams; | |
199 | + | |
200 | +/*===========================================================================*/ | |
201 | +/* Module local functions. */ | |
202 | +/*===========================================================================*/ | |
203 | + | |
204 | +static msg_t drv_open_dir(void *instance, | |
205 | + const char *path, | |
206 | + vfs_directory_node_t **vdnpp) { | |
207 | + vfs_fatfs_driver_t *drvp = (vfs_fatfs_driver_t *)instance; | |
208 | + msg_t err; | |
209 | + | |
210 | + do { | |
211 | + vfs_fatfs_dir_node_t *ffdnp; | |
212 | + | |
213 | + err = vfs_parse_match_separator(&path); | |
214 | + VFS_BREAK_ON_ERROR(err); | |
215 | + | |
216 | + err = vfs_parse_match_end(&path); | |
217 | + VFS_BREAK_ON_ERROR(err); | |
218 | + | |
219 | + ffdnp = chPoolAlloc(&drv_streams.dir_nodes_pool); | |
220 | + if (ffdnp != NULL) { | |
221 | + | |
222 | + /* Node object initialization.*/ | |
223 | + ffdnp->vmt = &dir_node_vmt; | |
224 | + ffdnp->refs = 1U; | |
225 | + ffdnp->driver = (vfs_driver_t *)drvp; | |
226 | + ffdnp->index = 0U; | |
227 | + | |
228 | + *vdnpp = (vfs_directory_node_t *)ffdnp; | |
229 | + return VFS_RET_SUCCESS; | |
230 | + } | |
231 | + | |
232 | + err = VFS_RET_NO_RESOURCE; | |
233 | + } | |
234 | + while (false); | |
235 | + | |
236 | + return err; | |
237 | +} | |
238 | + | |
239 | +static msg_t drv_open_file(void *instance, | |
240 | + const char *path, | |
241 | + vfs_file_node_t **vfnpp) { | |
242 | + vfs_fatfs_driver_t *drvp = (vfs_fatfs_driver_t *)instance; | |
243 | + const drv_stream_element_t *dsep; | |
244 | + msg_t err; | |
245 | + | |
246 | + do { | |
247 | + char fname[VFS_CFG_MAX_NAMELEN + 1]; | |
248 | + | |
249 | + err = vfs_parse_match_separator(&path); | |
250 | + VFS_BREAK_ON_ERROR(err); | |
251 | + | |
252 | + err = vfs_parse_filename(&path, fname); | |
253 | + VFS_BREAK_ON_ERROR(err); | |
254 | + | |
255 | + err = vfs_parse_match_end(&path); | |
256 | + VFS_BREAK_ON_ERROR(err); | |
257 | + | |
258 | + dsep = &drvp->streams[0]; | |
259 | + while (dsep->name != NULL) { | |
260 | + if (strncmp(fname, dsep->name, VFS_CFG_MAX_NAMELEN) == 0) { | |
261 | + vfs_fatfs_file_node_t *fffnp; | |
262 | + | |
263 | + fffnp = chPoolAlloc(&drv_streams.file_nodes_pool); | |
264 | + if (fffnp != NULL) { | |
265 | + | |
266 | + /* Node object initialization.*/ | |
267 | + fffnp->vmt = &file_node_vmt; | |
268 | + fffnp->refs = 1U; | |
269 | + fffnp->driver = (vfs_driver_t *)drvp; | |
270 | + fffnp->stream = dsep->stream; | |
271 | + | |
272 | + *vfnpp = (vfs_file_node_t *)fffnp; | |
273 | + return VFS_RET_SUCCESS; | |
274 | + } | |
275 | + | |
276 | + return VFS_RET_NO_RESOURCE; | |
277 | + } | |
278 | + | |
279 | + dsep++; | |
280 | + } | |
281 | + | |
282 | + err = VFS_RET_NOT_FOUND; | |
283 | + } | |
284 | + while (false); | |
285 | + | |
286 | + return err; | |
287 | +} | |
288 | + | |
289 | +static void node_dir_release(void *instance) { | |
290 | + vfs_fatfs_dir_node_t *ffdnp = (vfs_fatfs_dir_node_t *)instance; | |
291 | + | |
292 | + if (--ffdnp->refs == 0U) { | |
293 | + | |
294 | + chPoolFree(&((vfs_fatfs_driver_t *)ffdnp->driver)->dir_nodes_pool, | |
295 | + (void *)ffdnp); | |
296 | + } | |
297 | +} | |
298 | + | |
299 | +static msg_t node_dir_first(void *instance, vfs_node_info_t *nip) { | |
300 | + vfs_fatfs_dir_node_t *ffdnp = (vfs_fatfs_dir_node_t *)instance; | |
301 | + | |
302 | + ffdnp->index = 0U; | |
303 | + | |
304 | + return node_dir_next(instance, nip); | |
305 | +} | |
306 | + | |
307 | +static msg_t node_dir_next(void *instance, vfs_node_info_t *nip) { | |
308 | + vfs_fatfs_dir_node_t *ffdnp = (vfs_fatfs_dir_node_t *)instance; | |
309 | + | |
310 | + if (drv_streams.streams[ffdnp->index].name != NULL) { | |
311 | + | |
312 | + nip->attr = VFS_NODE_ATTR_ISSTREAM; | |
313 | + nip->size = (vfs_offset_t)0; | |
314 | + strcpy(nip->name, drv_streams.streams[ffdnp->index].name); | |
315 | + | |
316 | + ffdnp->index++; | |
317 | + | |
318 | + return VFS_RET_SUCCESS; | |
319 | + } | |
320 | + | |
321 | + return VFS_RET_EOF; | |
322 | +} | |
323 | + | |
324 | +static void node_file_release(void *instance) { | |
325 | + vfs_fatfs_file_node_t *fffnp = (vfs_fatfs_file_node_t *)instance; | |
326 | + | |
327 | + if (--fffnp->refs == 0U) { | |
328 | + | |
329 | + chPoolFree(&((vfs_fatfs_driver_t *)fffnp->driver)->file_nodes_pool, | |
330 | + (void *)fffnp); | |
331 | + } | |
332 | +} | |
333 | + | |
334 | +static BaseSequentialStream *node_file_get_stream(void *instance) { | |
335 | + vfs_fatfs_file_node_t *fffnp = (vfs_fatfs_file_node_t *)instance; | |
336 | + | |
337 | + return fffnp->stream; | |
338 | +} | |
339 | + | |
340 | +static ssize_t node_file_read(void *instance, uint8_t *buf, size_t n) { | |
341 | + vfs_fatfs_file_node_t *fffnp = (vfs_fatfs_file_node_t *)instance; | |
342 | + | |
343 | + return streamRead(fffnp->stream, buf, n); | |
344 | +} | |
345 | + | |
346 | +static ssize_t node_file_write(void *instance, const uint8_t *buf, size_t n) { | |
347 | + vfs_fatfs_file_node_t *fffnp = (vfs_fatfs_file_node_t *)instance; | |
348 | + | |
349 | + return streamWrite(fffnp->stream, buf, n); | |
350 | +} | |
351 | + | |
352 | +static msg_t node_file_setpos(void *instance, vfs_offset_t offset) { | |
353 | + | |
354 | + (void)instance; | |
355 | + (void)offset; | |
356 | + | |
357 | + return VFS_RET_NOT_IMPLEMENTED; | |
358 | +} | |
359 | + | |
360 | +static vfs_offset_t node_file_getpos(void *instance) { | |
361 | + | |
362 | + (void)instance; | |
363 | + | |
364 | + return 0U; | |
365 | +} | |
366 | + | |
367 | +static vfs_offset_t node_file_getsize(void *instance) { | |
368 | + | |
369 | + (void)instance; | |
370 | + | |
371 | + return 0U; | |
372 | +} | |
373 | + | |
374 | +/*===========================================================================*/ | |
375 | +/* Module exported functions. */ | |
376 | +/*===========================================================================*/ | |
377 | + | |
378 | +vfs_driver_t *drvStreamsInit(const char *rootname, | |
379 | + const drv_stream_element_t *streams) { | |
380 | + | |
381 | + drv_streams.vmt = &driver_vmt; | |
382 | + drv_streams.rootname = rootname; | |
383 | + drv_streams.streams = streams; | |
384 | + chPoolObjectInit(&drv_streams.dir_nodes_pool, | |
385 | + sizeof (vfs_fatfs_dir_node_t), | |
386 | + chCoreAllocAligned); | |
387 | + chPoolLoadArray(&drv_streams.dir_nodes_pool, | |
388 | + drv_dir_nodes, | |
389 | + DRV_DIR_NODES_NUM); | |
390 | + chPoolObjectInit(&drv_streams.file_nodes_pool, | |
391 | + sizeof (vfs_fatfs_file_node_t), | |
392 | + chCoreAllocAligned); | |
393 | + chPoolLoadArray(&drv_streams.file_nodes_pool, | |
394 | + drv_file_nodes, | |
395 | + DRV_FILE_NODES_NUM); | |
396 | + | |
397 | + return (vfs_driver_t *)&drv_streams; | |
398 | +} | |
399 | + | |
400 | +/** @} */ |
@@ -0,0 +1,71 @@ | ||
1 | +/* | |
2 | + ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014, | |
3 | + 2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio. | |
4 | + | |
5 | + This file is part of ChibiOS. | |
6 | + | |
7 | + ChibiOS is free software; you can redistribute it and/or modify | |
8 | + it under the terms of the GNU General Public License as published by | |
9 | + the Free Software Foundation version 3 of the License. | |
10 | + | |
11 | + ChibiOS is distributed in the hope that it will be useful, | |
12 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + GNU General Public License for more details. | |
15 | + | |
16 | + You should have received a copy of the GNU General Public License | |
17 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | +*/ | |
19 | +/** | |
20 | + * @file vfs/drivers/drvfatfs.h | |
21 | + * @brief HAL FatFS VFS driver header. | |
22 | + * | |
23 | + * @addtogroup VFS_DRV_FATFS | |
24 | + * @details Exposes HAL FatFS as VFS files. | |
25 | + * @{ | |
26 | + */ | |
27 | + | |
28 | +#ifndef DRVFATFS_H | |
29 | +#define DRVFATFS_H | |
30 | + | |
31 | +#include "vfs.h" | |
32 | + | |
33 | +/*===========================================================================*/ | |
34 | +/* Module constants. */ | |
35 | +/*===========================================================================*/ | |
36 | + | |
37 | +/*===========================================================================*/ | |
38 | +/* Module pre-compile time settings. */ | |
39 | +/*===========================================================================*/ | |
40 | + | |
41 | +/*===========================================================================*/ | |
42 | +/* Derived constants and error checks. */ | |
43 | +/*===========================================================================*/ | |
44 | + | |
45 | +/*===========================================================================*/ | |
46 | +/* Module data structures and types. */ | |
47 | +/*===========================================================================*/ | |
48 | + | |
49 | +/*===========================================================================*/ | |
50 | +/* Module macros. */ | |
51 | +/*===========================================================================*/ | |
52 | + | |
53 | +/*===========================================================================*/ | |
54 | +/* External declarations. */ | |
55 | +/*===========================================================================*/ | |
56 | + | |
57 | +#ifdef __cplusplus | |
58 | +extern "C" { | |
59 | +#endif | |
60 | + vfs_driver_t *drvFatFSInit(const char *rootname); | |
61 | +#ifdef __cplusplus | |
62 | +} | |
63 | +#endif | |
64 | + | |
65 | +/*===========================================================================*/ | |
66 | +/* Module inline functions. */ | |
67 | +/*===========================================================================*/ | |
68 | + | |
69 | +#endif /* DRVFATFS_H */ | |
70 | + | |
71 | +/** @} */ |