forked from espressif/esp-idf
vfs: introduce options to turn off some features
CONFIG_VFS_SUPPORT_IO: for basic I/O functions support CONFIG_VFS_SUPPORT_DIR: for file/directory functions support CONFIG_VFS_SUPPORT_SELECT: for select support
This commit is contained in:
@@ -1,7 +1,56 @@
|
|||||||
menu "Virtual file system"
|
menu "Virtual file system"
|
||||||
|
|
||||||
|
config VFS_SUPPORT_IO
|
||||||
|
bool "Provide basic I/O functions"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
If enabled, the following functions are provided by the VFS component.
|
||||||
|
|
||||||
|
open, close, read, write, pread, pwrite, lseek, fstat, fsync, ioctl, fcntl
|
||||||
|
|
||||||
|
Filesystem drivers can then be registered to handle these functions
|
||||||
|
for specific paths.
|
||||||
|
|
||||||
|
Disabling this option can save memory when the support for these functions
|
||||||
|
is not required.
|
||||||
|
|
||||||
|
config VFS_SUPPORT_DIR
|
||||||
|
bool "Provide directory related functions"
|
||||||
|
default y
|
||||||
|
# If some filesystem is used, adding I/O support is probably needed and
|
||||||
|
# is not a big overhead, compared to code size of the filesystem,
|
||||||
|
# so make this depend on IO.
|
||||||
|
depends on VFS_SUPPORT_IO
|
||||||
|
help
|
||||||
|
If enabled, the following functions are provided by the VFS component.
|
||||||
|
|
||||||
|
stat, link, unlink, rename, utime, access, truncate, rmdir, mkdir,
|
||||||
|
opendir, closedir, readdir, readdir_r, seekdir, telldir, rewinddir
|
||||||
|
|
||||||
|
Filesystem drivers can then be registered to handle these functions
|
||||||
|
for specific paths.
|
||||||
|
|
||||||
|
Disabling this option can save memory when the support for these functions
|
||||||
|
is not required.
|
||||||
|
|
||||||
|
config VFS_SUPPORT_SELECT
|
||||||
|
bool "Provide select function"
|
||||||
|
default y
|
||||||
|
# Dependency on !LWIP_USE_ONLY_LWIP_SELECT is for compatibility
|
||||||
|
depends on VFS_SUPPORT_IO && !LWIP_USE_ONLY_LWIP_SELECT
|
||||||
|
help
|
||||||
|
If enabled, select function is provided by the VFS component, and can be used
|
||||||
|
on peripheral file descriptors (such as UART) and sockets at the same time.
|
||||||
|
|
||||||
|
If disabled, the default select implementation will be provided by LWIP for
|
||||||
|
sockets only.
|
||||||
|
|
||||||
|
Disabling this option can reduce code size if support for "select" on UART file
|
||||||
|
descriptors is not required.
|
||||||
|
|
||||||
config VFS_SUPPRESS_SELECT_DEBUG_OUTPUT
|
config VFS_SUPPRESS_SELECT_DEBUG_OUTPUT
|
||||||
bool "Suppress select() related debug outputs"
|
bool "Suppress select() related debug outputs"
|
||||||
|
depends on VFS_SUPPORT_SELECT
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Select() related functions might produce an unconveniently lot of
|
Select() related functions might produce an unconveniently lot of
|
||||||
@@ -10,12 +59,16 @@ menu "Virtual file system"
|
|||||||
option.
|
option.
|
||||||
|
|
||||||
config VFS_SUPPORT_TERMIOS
|
config VFS_SUPPORT_TERMIOS
|
||||||
bool "Add support for termios.h"
|
bool "Provide termios.h functions"
|
||||||
default y
|
default y
|
||||||
|
# Very likely, only makes sense for UART VFS driver, which itself depends on VFS_SUPPORT_IO
|
||||||
|
depends on VFS_SUPPORT_IO
|
||||||
help
|
help
|
||||||
Disabling this option can save memory when the support for termios.h is not required.
|
Disabling this option can save memory when the support for termios.h is not required.
|
||||||
|
|
||||||
menu "Host File System I/O (Semihosting)"
|
menu "Host File System I/O (Semihosting)"
|
||||||
|
depends on VFS_SUPPORT_IO
|
||||||
|
|
||||||
config SEMIHOSTFS_MAX_MOUNT_POINTS
|
config SEMIHOSTFS_MAX_MOUNT_POINTS
|
||||||
int "Maximum number of the host filesystem mount points"
|
int "Maximum number of the host filesystem mount points"
|
||||||
default 1
|
default 1
|
||||||
|
@@ -132,6 +132,7 @@ typedef struct
|
|||||||
int (*fstat_p)(void* ctx, int fd, struct stat * st); /*!< fstat with context pointer */
|
int (*fstat_p)(void* ctx, int fd, struct stat * st); /*!< fstat with context pointer */
|
||||||
int (*fstat)(int fd, struct stat * st); /*!< fstat without context pointer */
|
int (*fstat)(int fd, struct stat * st); /*!< fstat without context pointer */
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
union {
|
union {
|
||||||
int (*stat_p)(void* ctx, const char * path, struct stat * st); /*!< stat with context pointer */
|
int (*stat_p)(void* ctx, const char * path, struct stat * st); /*!< stat with context pointer */
|
||||||
int (*stat)(const char * path, struct stat * st); /*!< stat without context pointer */
|
int (*stat)(const char * path, struct stat * st); /*!< stat without context pointer */
|
||||||
@@ -180,6 +181,7 @@ typedef struct
|
|||||||
int (*rmdir_p)(void* ctx, const char* name); /*!< rmdir with context pointer */
|
int (*rmdir_p)(void* ctx, const char* name); /*!< rmdir with context pointer */
|
||||||
int (*rmdir)(const char* name); /*!< rmdir without context pointer */
|
int (*rmdir)(const char* name); /*!< rmdir without context pointer */
|
||||||
};
|
};
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
union {
|
union {
|
||||||
int (*fcntl_p)(void* ctx, int fd, int cmd, int arg); /*!< fcntl with context pointer */
|
int (*fcntl_p)(void* ctx, int fd, int cmd, int arg); /*!< fcntl with context pointer */
|
||||||
int (*fcntl)(int fd, int cmd, int arg); /*!< fcntl without context pointer */
|
int (*fcntl)(int fd, int cmd, int arg); /*!< fcntl without context pointer */
|
||||||
@@ -192,6 +194,7 @@ typedef struct
|
|||||||
int (*fsync_p)(void* ctx, int fd); /*!< fsync with context pointer */
|
int (*fsync_p)(void* ctx, int fd); /*!< fsync with context pointer */
|
||||||
int (*fsync)(int fd); /*!< fsync without context pointer */
|
int (*fsync)(int fd); /*!< fsync without context pointer */
|
||||||
};
|
};
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
union {
|
union {
|
||||||
int (*access_p)(void* ctx, const char *path, int amode); /*!< access with context pointer */
|
int (*access_p)(void* ctx, const char *path, int amode); /*!< access with context pointer */
|
||||||
int (*access)(const char *path, int amode); /*!< access without context pointer */
|
int (*access)(const char *path, int amode); /*!< access without context pointer */
|
||||||
@@ -204,6 +207,7 @@ typedef struct
|
|||||||
int (*utime_p)(void* ctx, const char *path, const struct utimbuf *times); /*!< utime with context pointer */
|
int (*utime_p)(void* ctx, const char *path, const struct utimbuf *times); /*!< utime with context pointer */
|
||||||
int (*utime)(const char *path, const struct utimbuf *times); /*!< utime without context pointer */
|
int (*utime)(const char *path, const struct utimbuf *times); /*!< utime without context pointer */
|
||||||
};
|
};
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
union {
|
union {
|
||||||
int (*tcsetattr_p)(void *ctx, int fd, int optional_actions, const struct termios *p); /*!< tcsetattr with context pointer */
|
int (*tcsetattr_p)(void *ctx, int fd, int optional_actions, const struct termios *p); /*!< tcsetattr with context pointer */
|
||||||
@@ -234,7 +238,7 @@ typedef struct
|
|||||||
int (*tcsendbreak)(int fd, int duration); /*!< tcsendbreak without context pointer */
|
int (*tcsendbreak)(int fd, int duration); /*!< tcsendbreak without context pointer */
|
||||||
};
|
};
|
||||||
#endif // CONFIG_VFS_SUPPORT_TERMIOS
|
#endif // CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
/** start_select is called for setting up synchronous I/O multiplexing of the desired file descriptors in the given VFS */
|
/** start_select is called for setting up synchronous I/O multiplexing of the desired file descriptors in the given VFS */
|
||||||
esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, esp_vfs_select_sem_t sem, void **end_select_args);
|
esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, esp_vfs_select_sem_t sem, void **end_select_args);
|
||||||
/** socket select function for socket FDs with the functionality of POSIX select(); this should be set only for the socket VFS */
|
/** socket select function for socket FDs with the functionality of POSIX select(); this should be set only for the socket VFS */
|
||||||
@@ -247,6 +251,7 @@ typedef struct
|
|||||||
void* (*get_socket_select_semaphore)(void);
|
void* (*get_socket_select_semaphore)(void);
|
||||||
/** get_socket_select_semaphore returns semaphore allocated in the socket driver; set only for the socket driver */
|
/** get_socket_select_semaphore returns semaphore allocated in the socket driver; set only for the socket driver */
|
||||||
esp_err_t (*end_select)(void *end_select_args);
|
esp_err_t (*end_select)(void *end_select_args);
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
} esp_vfs_t;
|
} esp_vfs_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -406,23 +411,6 @@ void esp_vfs_select_triggered(esp_vfs_select_sem_t sem);
|
|||||||
*/
|
*/
|
||||||
void esp_vfs_select_triggered_isr(esp_vfs_select_sem_t sem, BaseType_t *woken);
|
void esp_vfs_select_triggered_isr(esp_vfs_select_sem_t sem, BaseType_t *woken);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Implements the VFS layer for synchronous I/O multiplexing by poll()
|
|
||||||
*
|
|
||||||
* The implementation is based on esp_vfs_select. The parameters and return values are compatible with POSIX poll().
|
|
||||||
*
|
|
||||||
* @param fds Pointer to the array containing file descriptors and events poll() should consider.
|
|
||||||
* @param nfds Number of items in the array fds.
|
|
||||||
* @param timeout Poll() should wait at least timeout milliseconds. If the value is 0 then it should return
|
|
||||||
* immediately. If the value is -1 then it should wait (block) until the event occurs.
|
|
||||||
*
|
|
||||||
* @return A positive return value indicates the number of file descriptors that have been selected. The 0
|
|
||||||
* return value indicates a timed-out poll. -1 is return on failure and errno is set accordingly.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int esp_vfs_poll(struct pollfd *fds, nfds_t nfds, int timeout);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Implements the VFS layer of POSIX pread()
|
* @brief Implements the VFS layer of POSIX pread()
|
||||||
|
@@ -507,6 +507,52 @@ int esp_vfs_fstat(struct _reent *r, int fd, struct stat * st)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int esp_vfs_fcntl_r(struct _reent *r, int fd, int cmd, int arg)
|
||||||
|
{
|
||||||
|
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
||||||
|
const int local_fd = get_local_fd(vfs, fd);
|
||||||
|
if (vfs == NULL || local_fd < 0) {
|
||||||
|
__errno_r(r) = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int ret;
|
||||||
|
CHECK_AND_CALL(ret, r, vfs, fcntl, local_fd, cmd, arg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_vfs_ioctl(int fd, int cmd, ...)
|
||||||
|
{
|
||||||
|
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
||||||
|
const int local_fd = get_local_fd(vfs, fd);
|
||||||
|
struct _reent* r = __getreent();
|
||||||
|
if (vfs == NULL || local_fd < 0) {
|
||||||
|
__errno_r(r) = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int ret;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, cmd);
|
||||||
|
CHECK_AND_CALL(ret, r, vfs, ioctl, local_fd, cmd, args);
|
||||||
|
va_end(args);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_vfs_fsync(int fd)
|
||||||
|
{
|
||||||
|
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
||||||
|
const int local_fd = get_local_fd(vfs, fd);
|
||||||
|
struct _reent* r = __getreent();
|
||||||
|
if (vfs == NULL || local_fd < 0) {
|
||||||
|
__errno_r(r) = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int ret;
|
||||||
|
CHECK_AND_CALL(ret, r, vfs, fsync, local_fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st)
|
int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
||||||
@@ -520,6 +566,20 @@ int esp_vfs_stat(struct _reent *r, const char * path, struct stat * st)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int esp_vfs_utime(const char *path, const struct utimbuf *times)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
||||||
|
struct _reent* r = __getreent();
|
||||||
|
if (vfs == NULL) {
|
||||||
|
__errno_r(r) = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const char* path_within_vfs = translate_path(vfs, path);
|
||||||
|
CHECK_AND_CALL(ret, r, vfs, utime, path_within_vfs, times);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int esp_vfs_link(struct _reent *r, const char* n1, const char* n2)
|
int esp_vfs_link(struct _reent *r, const char* n1, const char* n2)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(n1);
|
const vfs_entry_t* vfs = get_vfs_for_path(n1);
|
||||||
@@ -712,50 +772,6 @@ int rmdir(const char* name)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _fcntl_r(struct _reent *r, int fd, int cmd, int arg)
|
|
||||||
{
|
|
||||||
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
|
||||||
const int local_fd = get_local_fd(vfs, fd);
|
|
||||||
if (vfs == NULL || local_fd < 0) {
|
|
||||||
__errno_r(r) = EBADF;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int ret;
|
|
||||||
CHECK_AND_CALL(ret, r, vfs, fcntl, local_fd, cmd, arg);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ioctl(int fd, int cmd, ...)
|
|
||||||
{
|
|
||||||
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
|
||||||
const int local_fd = get_local_fd(vfs, fd);
|
|
||||||
struct _reent* r = __getreent();
|
|
||||||
if (vfs == NULL || local_fd < 0) {
|
|
||||||
__errno_r(r) = EBADF;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int ret;
|
|
||||||
va_list args;
|
|
||||||
va_start(args, cmd);
|
|
||||||
CHECK_AND_CALL(ret, r, vfs, ioctl, local_fd, cmd, args);
|
|
||||||
va_end(args);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fsync(int fd)
|
|
||||||
{
|
|
||||||
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
|
||||||
const int local_fd = get_local_fd(vfs, fd);
|
|
||||||
struct _reent* r = __getreent();
|
|
||||||
if (vfs == NULL || local_fd < 0) {
|
|
||||||
__errno_r(r) = EBADF;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int ret;
|
|
||||||
CHECK_AND_CALL(ret, r, vfs, fsync, local_fd);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int access(const char *path, int amode)
|
int access(const char *path, int amode)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@@ -784,6 +800,10 @@ int truncate(const char *path, off_t length)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
static void call_end_selects(int end_index, const fds_triple_t *vfs_fds_triple, void **driver_args)
|
static void call_end_selects(int end_index, const fds_triple_t *vfs_fds_triple, void **driver_args)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < end_index; ++i) {
|
for (int i = 0; i < end_index; ++i) {
|
||||||
@@ -1074,7 +1094,10 @@ void esp_vfs_select_triggered_isr(esp_vfs_select_sem_t sem, BaseType_t *woken)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
|
|
||||||
int tcgetattr(int fd, struct termios *p)
|
int tcgetattr(int fd, struct termios *p)
|
||||||
{
|
{
|
||||||
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
|
||||||
@@ -1174,95 +1197,10 @@ int tcsendbreak(int fd, int duration)
|
|||||||
}
|
}
|
||||||
#endif // CONFIG_VFS_SUPPORT_TERMIOS
|
#endif // CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
|
|
||||||
int esp_vfs_utime(const char *path, const struct utimbuf *times)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
const vfs_entry_t* vfs = get_vfs_for_path(path);
|
|
||||||
struct _reent* r = __getreent();
|
|
||||||
if (vfs == NULL) {
|
|
||||||
__errno_r(r) = ENOENT;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
const char* path_within_vfs = translate_path(vfs, path);
|
|
||||||
CHECK_AND_CALL(ret, r, vfs, utime, path_within_vfs, times);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int esp_vfs_poll(struct pollfd *fds, nfds_t nfds, int timeout)
|
|
||||||
{
|
|
||||||
struct timeval tv = {
|
|
||||||
// timeout is in milliseconds
|
|
||||||
.tv_sec = timeout / 1000,
|
|
||||||
.tv_usec = (timeout % 1000) * 1000,
|
|
||||||
};
|
|
||||||
int max_fd = -1;
|
|
||||||
fd_set readfds;
|
|
||||||
fd_set writefds;
|
|
||||||
fd_set errorfds;
|
|
||||||
struct _reent* r = __getreent();
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (fds == NULL) {
|
|
||||||
__errno_r(r) = ENOENT;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&readfds);
|
|
||||||
FD_ZERO(&writefds);
|
|
||||||
FD_ZERO(&errorfds);
|
|
||||||
|
|
||||||
for (int i = 0; i < nfds; ++i) {
|
|
||||||
fds[i].revents = 0;
|
|
||||||
|
|
||||||
if (fds[i].fd < 0) {
|
|
||||||
// revents should remain 0 and events ignored (according to the documentation of poll()).
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fds[i].fd >= MAX_FDS) {
|
|
||||||
fds[i].revents |= POLLNVAL;
|
|
||||||
++ret;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fds[i].events & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
|
|
||||||
FD_SET(fds[i].fd, &readfds);
|
|
||||||
FD_SET(fds[i].fd, &errorfds);
|
|
||||||
max_fd = MAX(max_fd, fds[i].fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
|
|
||||||
FD_SET(fds[i].fd, &writefds);
|
|
||||||
FD_SET(fds[i].fd, &errorfds);
|
|
||||||
max_fd = MAX(max_fd, fds[i].fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const int select_ret = esp_vfs_select(max_fd + 1, &readfds, &writefds, &errorfds, timeout < 0 ? NULL: &tv);
|
|
||||||
|
|
||||||
if (select_ret > 0) {
|
|
||||||
ret += select_ret;
|
|
||||||
|
|
||||||
for (int i = 0; i < nfds; ++i) {
|
|
||||||
if (FD_ISSET(fds[i].fd, &readfds)) {
|
|
||||||
fds[i].revents |= POLLIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FD_ISSET(fds[i].fd, &writefds)) {
|
|
||||||
fds[i].revents |= POLLOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FD_ISSET(fds[i].fd, &errorfds)) {
|
|
||||||
fds[i].revents |= POLLERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = select_ret;
|
|
||||||
// keeping the errno from select()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vfs_include_syscalls_impl(void)
|
void vfs_include_syscalls_impl(void)
|
||||||
{
|
{
|
||||||
|
@@ -23,6 +23,14 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_vfs.h"
|
#include "esp_vfs.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS
|
||||||
|
#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN
|
||||||
|
#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN 128
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LOG_LOCAL_LEVEL ESP_LOG_NONE
|
#define LOG_LOCAL_LEVEL ESP_LOG_NONE
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
const static char *TAG = "esp_semihost";
|
const static char *TAG = "esp_semihost";
|
||||||
|
@@ -116,6 +116,8 @@ static vfs_uart_context_t* s_ctx[UART_NUM] = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
esp_vfs_select_sem_t select_sem;
|
esp_vfs_select_sem_t select_sem;
|
||||||
fd_set *readfds;
|
fd_set *readfds;
|
||||||
@@ -132,6 +134,8 @@ static portMUX_TYPE s_registered_select_lock = portMUX_INITIALIZER_UNLOCKED;
|
|||||||
|
|
||||||
static esp_err_t uart_end_select(void *end_select_args);
|
static esp_err_t uart_end_select(void *end_select_args);
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
static int uart_open(const char * path, int flags, int mode)
|
static int uart_open(const char * path, int flags, int mode)
|
||||||
{
|
{
|
||||||
// this is fairly primitive, we should check if file is opened read only,
|
// this is fairly primitive, we should check if file is opened read only,
|
||||||
@@ -319,6 +323,8 @@ static int uart_fcntl(int fd, int cmd, int arg)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
static int uart_access(const char *path, int amode)
|
static int uart_access(const char *path, int amode)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -340,6 +346,8 @@ static int uart_access(const char *path, int amode)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
|
||||||
static int uart_fsync(int fd)
|
static int uart_fsync(int fd)
|
||||||
{
|
{
|
||||||
assert(fd >= 0 && fd < 3);
|
assert(fd >= 0 && fd < 3);
|
||||||
@@ -349,6 +357,8 @@ static int uart_fsync(int fd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
static esp_err_t register_select(uart_select_args_t *args)
|
static esp_err_t register_select(uart_select_args_t *args)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_ERR_INVALID_ARG;
|
esp_err_t ret = ESP_ERR_INVALID_ARG;
|
||||||
@@ -509,6 +519,8 @@ static esp_err_t uart_end_select(void *end_select_args)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
|
|
||||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
static int uart_tcsetattr(int fd, int optional_actions, const struct termios *p)
|
static int uart_tcsetattr(int fd, int optional_actions, const struct termios *p)
|
||||||
{
|
{
|
||||||
@@ -972,9 +984,13 @@ void esp_vfs_dev_uart_register(void)
|
|||||||
.read = &uart_read,
|
.read = &uart_read,
|
||||||
.fcntl = &uart_fcntl,
|
.fcntl = &uart_fcntl,
|
||||||
.fsync = &uart_fsync,
|
.fsync = &uart_fsync,
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_DIR
|
||||||
.access = &uart_access,
|
.access = &uart_access,
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_DIR
|
||||||
|
#ifdef CONFIG_VFS_SUPPORT_SELECT
|
||||||
.start_select = &uart_start_select,
|
.start_select = &uart_start_select,
|
||||||
.end_select = &uart_end_select,
|
.end_select = &uart_end_select,
|
||||||
|
#endif // CONFIG_VFS_SUPPORT_SELECT
|
||||||
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
|
||||||
.tcsetattr = &uart_tcsetattr,
|
.tcsetattr = &uart_tcsetattr,
|
||||||
.tcgetattr = &uart_tcgetattr,
|
.tcgetattr = &uart_tcgetattr,
|
||||||
|
Reference in New Issue
Block a user