vfs: implement fcntl via VFS interface

This commit is contained in:
Ivan Grokhotkov 2017-08-16 14:58:06 +08:00
parent 141b1174c6
commit 1e4587a09f
3 changed files with 55 additions and 9 deletions

View file

@ -17,6 +17,7 @@
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
#include "esp_err.h"
#include <sys/types.h>
#include <sys/reent.h>
@ -140,6 +141,10 @@ typedef struct
int (*rmdir_p)(void* ctx, const char* name);
int (*rmdir)(const char* name);
};
union {
int (*fcntl_p)(void* ctx, int fd, int cmd, va_list args);
int (*fcntl)(int fd, int cmd, va_list args);
};
} esp_vfs_t;

View file

@ -472,3 +472,20 @@ int rmdir(const char* name)
CHECK_AND_CALL(ret, r, vfs, rmdir, path_within_vfs);
return ret;
}
int fcntl(int fd, int cmd, ...)
{
const vfs_entry_t* vfs = get_vfs_for_fd(fd);
struct _reent* r = __getreent();
if (vfs == NULL) {
__errno_r(r) = EBADF;
return -1;
}
int local_fd = translate_fd(vfs, fd);
int ret;
va_list args;
va_start(args, cmd);
CHECK_AND_CALL(ret, r, vfs, fcntl, local_fd, cmd, args);
va_end(args);
return ret;
}

View file

@ -14,11 +14,13 @@
#include <string.h>
#include <stdbool.h>
#include <stdarg.h>
#include <sys/errno.h>
#include <sys/lock.h>
#include <sys/fcntl.h>
#include "esp_vfs.h"
#include "esp_vfs_dev.h"
#include "esp_attr.h"
#include "sys/errno.h"
#include "sys/lock.h"
#include "soc/uart_struct.h"
#include "driver/uart.h"
#include "sdkconfig.h"
@ -48,6 +50,10 @@ static uart_dev_t* s_uarts[UART_NUM] = {&UART0, &UART1, &UART2};
static _lock_t s_uart_locks[UART_NUM];
// One-character buffer used for newline conversion code, per UART
static int s_peek_char[UART_NUM] = { NONE, NONE, NONE };
// Per-UART non-blocking flag. Note: default implementation does not honor this
// flag, all reads are non-blocking. This option becomes effective if UART
// driver is used.
static bool s_non_blocking[UART_NUM];
// Newline conversion mode when transmitting
static esp_line_endings_t s_tx_mode =
@ -122,8 +128,9 @@ static int uart_rx_char(int fd)
static int uart_rx_char_via_driver(int fd)
{
uint8_t c;
int n = uart_read_bytes(fd, &c, 1, portMAX_DELAY);
if (n == 0) {
int timeout = s_non_blocking[fd] ? 0 : portMAX_DELAY;
int n = uart_read_bytes(fd, &c, 1, timeout);
if (n <= 0) {
return NONE;
}
return c;
@ -203,6 +210,8 @@ static ssize_t uart_read(int fd, void* data, size_t size)
uart_return_char(fd, c2);
}
}
} else if (c == NONE) {
break;
}
data_c[received] = (char) c;
++received;
@ -231,6 +240,25 @@ static int uart_close(int fd)
return 0;
}
static int uart_fcntl(int fd, int cmd, va_list args)
{
assert(fd >=0 && fd < 3);
int result = 0;
if (cmd == F_GETFL) {
if (s_non_blocking[fd]) {
result |= O_NONBLOCK;
}
} else if (cmd == F_SETFL) {
int arg = va_arg(args, int);
s_non_blocking[fd] = (arg & O_NONBLOCK) != 0;
} else {
// unsupported operation
result = -1;
errno = ENOSYS;
}
return result;
}
void esp_vfs_dev_uart_register()
{
esp_vfs_t vfs = {
@ -241,11 +269,7 @@ void esp_vfs_dev_uart_register()
.fstat = &uart_fstat,
.close = &uart_close,
.read = &uart_read,
.lseek = NULL,
.stat = NULL,
.link = NULL,
.unlink = NULL,
.rename = NULL
.fcntl = &uart_fcntl
};
ESP_ERROR_CHECK(esp_vfs_register("/dev/uart", &vfs, NULL));
}