#include <stdint.h>
#include <stddef.h>
+#include <stdarg.h>
#include "esp_err.h"
#include <sys/types.h>
#include <sys/reent.h>
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;
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;
+}
#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"
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 =
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;
uart_return_char(fd, c2);
}
}
+ } else if (c == NONE) {
+ break;
}
data_c[received] = (char) c;
++received;
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 = {
.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));
}