Merge branch 'feature/vfs_find_free_fd' into 'master'

Add "find file descriptor" API to be used by VFS drivers

See merge request idf/esp-idf!2389
This commit is contained in:
Angus Gratton
2018-05-18 15:22:20 +08:00
5 changed files with 147 additions and 71 deletions

View File

@@ -57,6 +57,11 @@ extern "C" {
*/
#define ESP_VFS_FLAG_CONTEXT_PTR 1
/*
* @brief VFS identificator used for esp_vfs_register_with_id()
*/
typedef int esp_vfs_id_t;
/**
* @brief VFS definition structure
*
@@ -221,6 +226,24 @@ esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ct
*/
esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, int max_fd);
/**
* Special case function for registering a VFS that uses a method other than
* open() to open new file descriptors. In comparison with
* esp_vfs_register_fd_range, this function doesn't pre-registers an interval
* of file descriptors. File descriptors can be registered later, by using
* esp_vfs_register_fd.
*
* @param vfs Pointer to esp_vfs_t. Meaning is the same as for esp_vfs_register().
* @param ctx Pointer to context structure. Meaning is the same as for esp_vfs_register().
* @param vfs_id Here will be written the VFS ID which can be passed to
* esp_vfs_register_fd for registering file descriptors.
*
* @return ESP_OK if successful, ESP_ERR_NO_MEM if too many VFSes are
* registered, ESP_ERR_INVALID_ARG if the file descriptor boundaries
* are incorrect.
*/
esp_err_t esp_vfs_register_with_id(const esp_vfs_t *vfs, void *ctx, esp_vfs_id_t *vfs_id);
/**
* Unregister a virtual filesystem for given path prefix
*
@@ -230,6 +253,31 @@ esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd,
*/
esp_err_t esp_vfs_unregister(const char* base_path);
/**
* Special function for registering another file descriptor for a VFS registered
* by esp_vfs_register_with_id.
*
* @param vfs_id VFS identificator returned by esp_vfs_register_with_id.
* @param fd The registered file descriptor will be written to this address.
*
* @return ESP_OK if the registration is successful,
* ESP_ERR_NO_MEM if too many file descriptors are registered,
* ESP_ERR_INVALID_ARG if the arguments are incorrect.
*/
esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd);
/**
* Special function for unregistering a file descriptor belonging to a VFS
* registered by esp_vfs_register_with_id.
*
* @param vfs_id VFS identificator returned by esp_vfs_register_with_id.
* @param fd File descriptor which should be unregistered.
*
* @return ESP_OK if the registration is successful,
* ESP_ERR_INVALID_ARG if the arguments are incorrect.
*/
esp_err_t esp_vfs_unregister_fd(esp_vfs_id_t vfs_id, int fd);
/**
* These functions are to be used in newlib syscall table. They will be called by
* newlib when it needs to use any of the syscalls.

View File

@@ -157,6 +157,16 @@ esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd,
return ret;
}
esp_err_t esp_vfs_register_with_id(const esp_vfs_t *vfs, void *ctx, esp_vfs_id_t *vfs_id)
{
if (vfs_id == NULL) {
return ESP_ERR_INVALID_ARG;
}
*vfs_id = -1;
return esp_vfs_register_common("", LEN_PATH_PREFIX_IGNORED, vfs, ctx, vfs_id);
}
esp_err_t esp_vfs_unregister(const char* base_path)
{
for (size_t i = 0; i < s_vfs_count; ++i) {
@@ -183,6 +193,48 @@ esp_err_t esp_vfs_unregister(const char* base_path)
return ESP_ERR_INVALID_STATE;
}
esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd)
{
if (vfs_id < 0 || vfs_id >= s_vfs_count || fd == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t ret = ESP_ERR_NO_MEM;
_lock_acquire(&s_fd_table_lock);
for (int i = 0; i < MAX_FDS; ++i) {
if (s_fd_table[i].vfs_index == -1) {
s_fd_table[i].permanent = true;
s_fd_table[i].vfs_index = vfs_id;
s_fd_table[i].local_fd = i;
*fd = i;
ret = ESP_OK;
break;
}
}
_lock_release(&s_fd_table_lock);
return ret;
}
esp_err_t esp_vfs_unregister_fd(esp_vfs_id_t vfs_id, int fd)
{
esp_err_t ret = ESP_ERR_INVALID_ARG;
if (vfs_id < 0 || vfs_id >= s_vfs_count || fd < 0 || fd >= MAX_FDS) {
return ret;
}
_lock_acquire(&s_fd_table_lock);
fd_table_t *item = s_fd_table + fd;
if (item->permanent == true && item->vfs_index == vfs_id && item->local_fd == fd) {
*item = FD_TABLE_ENTRY_UNUSED;
ret = ESP_OK;
}
_lock_release(&s_fd_table_lock);
return ret;
}
static inline const vfs_entry_t *get_vfs_for_index(int index)
{
if (index < 0 || index >= s_vfs_count) {