esp_vfs.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifndef __ESP_VFS_H__
  15. #define __ESP_VFS_H__
  16. #include <stdint.h>
  17. #include <stddef.h>
  18. #include <stdarg.h>
  19. #include <unistd.h>
  20. #include <utime.h>
  21. #include "freertos/FreeRTOS.h"
  22. #include "freertos/semphr.h"
  23. #include "esp_err.h"
  24. #include <sys/types.h>
  25. #include <sys/reent.h>
  26. #include <sys/stat.h>
  27. #include <sys/time.h>
  28. #include <sys/termios.h>
  29. #include <dirent.h>
  30. #include <string.h>
  31. #include "sdkconfig.h"
  32. #ifdef __cplusplus
  33. extern "C" {
  34. #endif
  35. #ifndef _SYS_TYPES_FD_SET
  36. #error "VFS should be used with FD_SETSIZE and FD_SET from sys/types.h"
  37. #endif
  38. /**
  39. * Maximum number of (global) file descriptors.
  40. */
  41. #define MAX_FDS FD_SETSIZE /* for compatibility with fd_set and select() */
  42. /**
  43. * Maximum length of path prefix (not including zero terminator)
  44. */
  45. #define ESP_VFS_PATH_MAX 15
  46. /**
  47. * Default value of flags member in esp_vfs_t structure.
  48. */
  49. #define ESP_VFS_FLAG_DEFAULT 0
  50. /**
  51. * Flag which indicates that FS needs extra context pointer in syscalls.
  52. */
  53. #define ESP_VFS_FLAG_CONTEXT_PTR 1
  54. /*
  55. * @brief VFS identificator used for esp_vfs_register_with_id()
  56. */
  57. typedef int esp_vfs_id_t;
  58. /**
  59. * @brief VFS definition structure
  60. *
  61. * This structure should be filled with pointers to corresponding
  62. * FS driver functions.
  63. *
  64. * VFS component will translate all FDs so that the filesystem implementation
  65. * sees them starting at zero. The caller sees a global FD which is prefixed
  66. * with an pre-filesystem-implementation.
  67. *
  68. * Some FS implementations expect some state (e.g. pointer to some structure)
  69. * to be passed in as a first argument. For these implementations,
  70. * populate the members of this structure which have _p suffix, set
  71. * flags member to ESP_VFS_FLAG_CONTEXT_PTR and provide the context pointer
  72. * to esp_vfs_register function.
  73. * If the implementation doesn't use this extra argument, populate the
  74. * members without _p suffix and set flags member to ESP_VFS_FLAG_DEFAULT.
  75. *
  76. * If the FS driver doesn't provide some of the functions, set corresponding
  77. * members to NULL.
  78. */
  79. typedef struct
  80. {
  81. int flags; /*!< ESP_VFS_FLAG_CONTEXT_PTR or ESP_VFS_FLAG_DEFAULT */
  82. union {
  83. ssize_t (*write_p)(void* p, int fd, const void * data, size_t size);
  84. ssize_t (*write)(int fd, const void * data, size_t size);
  85. };
  86. union {
  87. off_t (*lseek_p)(void* p, int fd, off_t size, int mode);
  88. off_t (*lseek)(int fd, off_t size, int mode);
  89. };
  90. union {
  91. ssize_t (*read_p)(void* ctx, int fd, void * dst, size_t size);
  92. ssize_t (*read)(int fd, void * dst, size_t size);
  93. };
  94. union {
  95. int (*open_p)(void* ctx, const char * path, int flags, int mode);
  96. int (*open)(const char * path, int flags, int mode);
  97. };
  98. union {
  99. int (*close_p)(void* ctx, int fd);
  100. int (*close)(int fd);
  101. };
  102. union {
  103. int (*fstat_p)(void* ctx, int fd, struct stat * st);
  104. int (*fstat)(int fd, struct stat * st);
  105. };
  106. union {
  107. int (*stat_p)(void* ctx, const char * path, struct stat * st);
  108. int (*stat)(const char * path, struct stat * st);
  109. };
  110. union {
  111. int (*link_p)(void* ctx, const char* n1, const char* n2);
  112. int (*link)(const char* n1, const char* n2);
  113. };
  114. union {
  115. int (*unlink_p)(void* ctx, const char *path);
  116. int (*unlink)(const char *path);
  117. };
  118. union {
  119. int (*rename_p)(void* ctx, const char *src, const char *dst);
  120. int (*rename)(const char *src, const char *dst);
  121. };
  122. union {
  123. DIR* (*opendir_p)(void* ctx, const char* name);
  124. DIR* (*opendir)(const char* name);
  125. };
  126. union {
  127. struct dirent* (*readdir_p)(void* ctx, DIR* pdir);
  128. struct dirent* (*readdir)(DIR* pdir);
  129. };
  130. union {
  131. int (*readdir_r_p)(void* ctx, DIR* pdir, struct dirent* entry, struct dirent** out_dirent);
  132. int (*readdir_r)(DIR* pdir, struct dirent* entry, struct dirent** out_dirent);
  133. };
  134. union {
  135. long (*telldir_p)(void* ctx, DIR* pdir);
  136. long (*telldir)(DIR* pdir);
  137. };
  138. union {
  139. void (*seekdir_p)(void* ctx, DIR* pdir, long offset);
  140. void (*seekdir)(DIR* pdir, long offset);
  141. };
  142. union {
  143. int (*closedir_p)(void* ctx, DIR* pdir);
  144. int (*closedir)(DIR* pdir);
  145. };
  146. union {
  147. int (*mkdir_p)(void* ctx, const char* name, mode_t mode);
  148. int (*mkdir)(const char* name, mode_t mode);
  149. };
  150. union {
  151. int (*rmdir_p)(void* ctx, const char* name);
  152. int (*rmdir)(const char* name);
  153. };
  154. union {
  155. int (*fcntl_p)(void* ctx, int fd, int cmd, va_list args);
  156. int (*fcntl)(int fd, int cmd, va_list args);
  157. };
  158. union {
  159. int (*ioctl_p)(void* ctx, int fd, int cmd, va_list args);
  160. int (*ioctl)(int fd, int cmd, va_list args);
  161. };
  162. union {
  163. int (*fsync_p)(void* ctx, int fd);
  164. int (*fsync)(int fd);
  165. };
  166. union {
  167. int (*access_p)(void* ctx, const char *path, int amode);
  168. int (*access)(const char *path, int amode);
  169. };
  170. union {
  171. int (*truncate_p)(void* ctx, const char *path, off_t length);
  172. int (*truncate)(const char *path, off_t length);
  173. };
  174. union {
  175. int (*utime_p)(void* ctx, const char *path, const struct utimbuf *times);
  176. int (*utime)(const char *path, const struct utimbuf *times);
  177. };
  178. #ifdef CONFIG_SUPPORT_TERMIOS
  179. union {
  180. int (*tcsetattr_p)(void *ctx, int fd, int optional_actions, const struct termios *p);
  181. int (*tcsetattr)(int fd, int optional_actions, const struct termios *p);
  182. };
  183. union {
  184. int (*tcgetattr_p)(void *ctx, int fd, struct termios *p);
  185. int (*tcgetattr)(int fd, struct termios *p);
  186. };
  187. union {
  188. int (*tcdrain_p)(void *ctx, int fd);
  189. int (*tcdrain)(int fd);
  190. };
  191. union {
  192. int (*tcflush_p)(void *ctx, int fd, int select);
  193. int (*tcflush)(int fd, int select);
  194. };
  195. union {
  196. int (*tcflow_p)(void *ctx, int fd, int action);
  197. int (*tcflow)(int fd, int action);
  198. };
  199. union {
  200. pid_t (*tcgetsid_p)(void *ctx, int fd);
  201. pid_t (*tcgetsid)(int fd);
  202. };
  203. union {
  204. int (*tcsendbreak_p)(void *ctx, int fd, int duration);
  205. int (*tcsendbreak)(int fd, int duration);
  206. };
  207. #endif // CONFIG_SUPPORT_TERMIOS
  208. /** start_select is called for setting up synchronous I/O multiplexing of the desired file descriptors in the given VFS */
  209. esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, SemaphoreHandle_t *signal_sem);
  210. /** socket select function for socket FDs with the functionality of POSIX select(); this should be set only for the socket VFS */
  211. int (*socket_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
  212. /** called by VFS to interrupt the socket_select call when select is activated from a non-socket VFS driver; set only for the socket driver */
  213. void (*stop_socket_select)();
  214. /** stop_socket_select which can be called from ISR; set only for the socket driver */
  215. void (*stop_socket_select_isr)(BaseType_t *woken);
  216. /** end_select is called to stop the I/O multiplexing and deinitialize the environment created by start_select for the given VFS */
  217. void (*end_select)();
  218. } esp_vfs_t;
  219. /**
  220. * Register a virtual filesystem for given path prefix.
  221. *
  222. * @param base_path file path prefix associated with the filesystem.
  223. * Must be a zero-terminated C string, up to ESP_VFS_PATH_MAX
  224. * characters long, and at least 2 characters long.
  225. * Name must start with a "/" and must not end with "/".
  226. * For example, "/data" or "/dev/spi" are valid.
  227. * These VFSes would then be called to handle file paths such as
  228. * "/data/myfile.txt" or "/dev/spi/0".
  229. * @param vfs Pointer to esp_vfs_t, a structure which maps syscalls to
  230. * the filesystem driver functions. VFS component doesn't
  231. * assume ownership of this pointer.
  232. * @param ctx If vfs->flags has ESP_VFS_FLAG_CONTEXT_PTR set, a pointer
  233. * which should be passed to VFS functions. Otherwise, NULL.
  234. *
  235. * @return ESP_OK if successful, ESP_ERR_NO_MEM if too many VFSes are
  236. * registered.
  237. */
  238. esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ctx);
  239. /**
  240. * Special case function for registering a VFS that uses a method other than
  241. * open() to open new file descriptors from the interval <min_fd; max_fd).
  242. *
  243. * This is a special-purpose function intended for registering LWIP sockets to VFS.
  244. *
  245. * @param vfs Pointer to esp_vfs_t. Meaning is the same as for esp_vfs_register().
  246. * @param ctx Pointer to context structure. Meaning is the same as for esp_vfs_register().
  247. * @param min_fd The smallest file descriptor this VFS will use.
  248. * @param max_fd Upper boundary for file descriptors this VFS will use (the biggest file descriptor plus one).
  249. *
  250. * @return ESP_OK if successful, ESP_ERR_NO_MEM if too many VFSes are
  251. * registered, ESP_ERR_INVALID_ARG if the file descriptor boundaries
  252. * are incorrect.
  253. */
  254. esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, int max_fd);
  255. /**
  256. * Special case function for registering a VFS that uses a method other than
  257. * open() to open new file descriptors. In comparison with
  258. * esp_vfs_register_fd_range, this function doesn't pre-registers an interval
  259. * of file descriptors. File descriptors can be registered later, by using
  260. * esp_vfs_register_fd.
  261. *
  262. * @param vfs Pointer to esp_vfs_t. Meaning is the same as for esp_vfs_register().
  263. * @param ctx Pointer to context structure. Meaning is the same as for esp_vfs_register().
  264. * @param vfs_id Here will be written the VFS ID which can be passed to
  265. * esp_vfs_register_fd for registering file descriptors.
  266. *
  267. * @return ESP_OK if successful, ESP_ERR_NO_MEM if too many VFSes are
  268. * registered, ESP_ERR_INVALID_ARG if the file descriptor boundaries
  269. * are incorrect.
  270. */
  271. esp_err_t esp_vfs_register_with_id(const esp_vfs_t *vfs, void *ctx, esp_vfs_id_t *vfs_id);
  272. /**
  273. * Unregister a virtual filesystem for given path prefix
  274. *
  275. * @param base_path file prefix previously used in esp_vfs_register call
  276. * @return ESP_OK if successful, ESP_ERR_INVALID_STATE if VFS for given prefix
  277. * hasn't been registered
  278. */
  279. esp_err_t esp_vfs_unregister(const char* base_path);
  280. /**
  281. * Special function for registering another file descriptor for a VFS registered
  282. * by esp_vfs_register_with_id.
  283. *
  284. * @param vfs_id VFS identificator returned by esp_vfs_register_with_id.
  285. * @param fd The registered file descriptor will be written to this address.
  286. *
  287. * @return ESP_OK if the registration is successful,
  288. * ESP_ERR_NO_MEM if too many file descriptors are registered,
  289. * ESP_ERR_INVALID_ARG if the arguments are incorrect.
  290. */
  291. esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd);
  292. /**
  293. * Special function for unregistering a file descriptor belonging to a VFS
  294. * registered by esp_vfs_register_with_id.
  295. *
  296. * @param vfs_id VFS identificator returned by esp_vfs_register_with_id.
  297. * @param fd File descriptor which should be unregistered.
  298. *
  299. * @return ESP_OK if the registration is successful,
  300. * ESP_ERR_INVALID_ARG if the arguments are incorrect.
  301. */
  302. esp_err_t esp_vfs_unregister_fd(esp_vfs_id_t vfs_id, int fd);
  303. /**
  304. * These functions are to be used in newlib syscall table. They will be called by
  305. * newlib when it needs to use any of the syscalls.
  306. */
  307. /**@{*/
  308. ssize_t esp_vfs_write(struct _reent *r, int fd, const void * data, size_t size);
  309. off_t esp_vfs_lseek(struct _reent *r, int fd, off_t size, int mode);
  310. ssize_t esp_vfs_read(struct _reent *r, int fd, void * dst, size_t size);
  311. int esp_vfs_open(struct _reent *r, const char * path, int flags, int mode);
  312. int esp_vfs_close(struct _reent *r, int fd);
  313. int esp_vfs_fstat(struct _reent *r, int fd, struct stat * st);
  314. int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st);
  315. int esp_vfs_link(struct _reent *r, const char* n1, const char* n2);
  316. int esp_vfs_unlink(struct _reent *r, const char *path);
  317. int esp_vfs_rename(struct _reent *r, const char *src, const char *dst);
  318. int esp_vfs_utime(const char *path, const struct utimbuf *times);
  319. /**@}*/
  320. /**
  321. * @brief Synchronous I/O multiplexing which implements the functionality of POSIX select() for VFS
  322. * @param nfds Specifies the range of descriptors which should be checked.
  323. * The first nfds descriptors will be checked in each set.
  324. * @param readfds If not NULL, then points to a descriptor set that on input
  325. * specifies which descriptors should be checked for being
  326. * ready to read, and on output indicates which descriptors
  327. * are ready to read.
  328. * @param writefds If not NULL, then points to a descriptor set that on input
  329. * specifies which descriptors should be checked for being
  330. * ready to write, and on output indicates which descriptors
  331. * are ready to write.
  332. * @param errorfds If not NULL, then points to a descriptor set that on input
  333. * specifies which descriptors should be checked for error
  334. * conditions, and on output indicates which descriptors
  335. * have error conditions.
  336. * @param timeout If not NULL, then points to timeval structure which
  337. * specifies the time period after which the functions should
  338. * time-out and return. If it is NULL, then the function will
  339. * not time-out.
  340. *
  341. * @return The number of descriptors set in the descriptor sets, or -1
  342. * when an error (specified by errno) have occurred.
  343. */
  344. int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
  345. /**
  346. * @brief Notification from a VFS driver about a read/write/error condition
  347. *
  348. * This function is called when the VFS driver detects a read/write/error
  349. * condition as it was requested by the previous call to start_select.
  350. *
  351. * @param signal_sem semaphore handle which was passed to the driver by the start_select call
  352. */
  353. void esp_vfs_select_triggered(SemaphoreHandle_t *signal_sem);
  354. /**
  355. * @brief Notification from a VFS driver about a read/write/error condition (ISR version)
  356. *
  357. * This function is called when the VFS driver detects a read/write/error
  358. * condition as it was requested by the previous call to start_select.
  359. *
  360. * @param signal_sem semaphore handle which was passed to the driver by the start_select call
  361. * @param woken is set to pdTRUE if the function wakes up a task with higher priority
  362. */
  363. void esp_vfs_select_triggered_isr(SemaphoreHandle_t *signal_sem, BaseType_t *woken);
  364. #ifdef __cplusplus
  365. } // extern "C"
  366. #endif
  367. #endif //__ESP_VFS_H__