1
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
112
113
120
121
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
162
166
167
168
169
170
171
172
177
178
184
185
186
187
188
189
190
193
194
195
196
197
202
203
204
205
206
207
210
211
212
213
214
215
216
217
218
219
220
223
224
225
226
227
228
229
230
234
235
245
246
247
248
249
253
263
264
265
270
271
272
273
274
275
276
277
278
279
280
283
284
285
286
289
292
293
294
295
296
299
300
301
326
327
328
329
330
331
332
333
336
337
340
341
342
343
344
351
352
357
358
376
377
378
379
380
381
382
383
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
489
490
491
492
493
494
495
496
503
504
505
506
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
532
533
543
544
545
550
551
552
553
554
555
556
557
558
559
560
561
562
563
572
573
574
577
578
579
580
581
582
583
584
585
586
590
591
595
596
618
619
626
627
628
629
630
631
632
633
650
651
655
656
657
661
662
663
664
665
669
670
671
675
676
679
680
683
686
689
692
695
698
701
704
707
710
713
716
719
722
725
728
731
734
737
740
743
746
749
752
755
758
761
764
767
770
773
776
777
778
779
783
784
785
786
787
788
789
790
791
795
796
800
801
802
803
808
809
810
811
812
816
817
818
819
836
837
858
881
882
883
884
888
889
890
891
892
893
896
899
902
905
908
911
914
917
920
923
926
929
932
935
938
941
944
947
950
953
956
959
962
965
968
971
974
977
980
983
986
990
991
992
993
994
995
996
997
998
999
1000
1004
1005
1009
1010
1011
1012
1013
1014
1015
1019
1020
1030
1031
1032
1033
1034
1035
1036
1040
1041
1042
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1080
1081
1085
1086
1095
1096
1105
1106
1107
1113
1114
1115
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1150
1151
1152
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
/* ... */
#include <string.h>
#include <stdbool.h>
#include <stdarg.h>
#include <sys/errno.h>
#include <sys/lock.h>
#include <sys/fcntl.h>
#include <sys/param.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "driver/uart_vfs.h"
#include "driver/uart.h"
#include "driver/uart_select.h"
#include "esp_rom_uart.h"
#include "hal/uart_ll.h"
#include "soc/soc_caps.h"
#include "esp_vfs_dev.h"
#include "esp_private/startup_internal.h"17 includes
#define UART_NUM SOC_UART_HP_NUM
#define NONE -1
#if CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF
# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CRLF
#elif CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR
# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CR
#else
# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_LF
#endif
#if CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF
# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CRLF
#elif CONFIG_NEWLIB_STDIN_LINE_ENDING_CR
# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CR
#else
# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_LF
#endif
#if CONFIG_VFS_SELECT_IN_RAM
#define UART_VFS_MALLOC_FLAGS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define UART_VFS_MALLOC_FLAGS MALLOC_CAP_DEFAULT
#endif
typedef void (*tx_func_t)(int, int);
typedef int (*rx_func_t)(int);
typedef size_t (*get_available_data_len_func_t)(int);
static void uart_tx_char(int fd, int c);
static int uart_rx_char(int fd);
static size_t uart_get_avail_data_len(int fd);
static void uart_tx_char_via_driver(int fd, int c);
static int uart_rx_char_via_driver(int fd);
static size_t uart_get_avail_data_len_via_driver(int fd);
typedef struct {
uart_dev_t* uart;
int peek_char;
_lock_t read_lock;
_lock_t write_lock;
bool non_blocking;
esp_line_endings_t tx_mode;
esp_line_endings_t rx_mode;
tx_func_t tx_func;
rx_func_t rx_func;
get_available_data_len_func_t get_avail_data_len_func;
}{ ... } uart_vfs_context_t;
#define VFS_CTX_DEFAULT_VAL(uart_dev) (uart_vfs_context_t) {\
.uart = (uart_dev),\
.peek_char = NONE,\
.tx_mode = DEFAULT_TX_MODE,\
.rx_mode = DEFAULT_RX_MODE,\
.tx_func = uart_tx_char,\
.rx_func = uart_rx_char,\
.get_avail_data_len_func = uart_get_avail_data_len,\
}{...}
...
static uart_vfs_context_t s_context[UART_NUM] = {
VFS_CTX_DEFAULT_VAL(&UART0),
VFS_CTX_DEFAULT_VAL(&UART1),
#if UART_NUM > 2
VFS_CTX_DEFAULT_VAL(&UART2),
#endif
}{...};
static uart_vfs_context_t* s_ctx[UART_NUM] = {
&s_context[0],
&s_context[1],
#if UART_NUM > 2
&s_context[2],
#endif
}{...};
static const char *s_uart_mount_points[UART_NUM] = {
"/0",
"/1",
#if UART_NUM > 2
"/2",
#endif
}{...};
#ifdef CONFIG_VFS_SUPPORT_SELECT
typedef struct {
esp_vfs_select_sem_t select_sem;
fd_set *readfds;
fd_set *writefds;
fd_set *errorfds;
fd_set readfds_orig;
fd_set writefds_orig;
fd_set errorfds_orig;
}{ ... } uart_select_args_t;
static uart_select_args_t **s_registered_selects = NULL;
static int s_registered_select_num = 0;
static portMUX_TYPE s_registered_select_lock = portMUX_INITIALIZER_UNLOCKED;
static int s_uart_select_count[UART_NUM] = {0};
static esp_err_t uart_end_select(void *end_select_args);
/* ... */
#endif
static int uart_open(const char *path, int flags, int mode)
{
int fd = -1;
for (int i = 0; i < UART_NUM; i++) {
if (strcmp(path, s_uart_mount_points[i]) == 0) {
fd = i;
break;
}{...}
}{...}
if (fd == -1) {
errno = ENOENT;
return -1;
}{...}
s_ctx[fd]->non_blocking = ((flags & O_NONBLOCK) == O_NONBLOCK);
return fd;
}{ ... }
size_t uart_get_avail_data_len(int fd)
{
uart_dev_t* uart = s_ctx[fd]->uart;
return uart_ll_get_rxfifo_len(uart);
}{ ... }
size_t uart_get_avail_data_len_via_driver(int fd)
{
size_t buffered_size = 0;
uart_get_buffered_data_len(fd, &buffered_size);
return buffered_size;
}{ ... }
static void uart_tx_char(int fd, int c)
{
uart_dev_t* uart = s_ctx[fd]->uart;
const uint8_t ch = (uint8_t) c;
while (uart_ll_get_txfifo_len(uart) < 2) {
;
}{...}
uart_ll_write_txfifo(uart, &ch, 1);
}{ ... }
static void uart_tx_char_via_driver(int fd, int c)
{
char ch = (char) c;
uart_write_bytes(fd, &ch, 1);
}{ ... }
static int uart_rx_char(int fd)
{
uart_dev_t* uart = s_ctx[fd]->uart;
uint8_t ch;
if (uart_ll_get_rxfifo_len(uart) == 0) {
return NONE;
}{...}
uart_ll_read_rxfifo(uart, &ch, 1);
return ch;
}{ ... }
static int uart_rx_char_via_driver(int fd)
{
uint8_t c;
int timeout = s_ctx[fd]->non_blocking ? 0 : portMAX_DELAY;
int n = uart_read_bytes(fd, &c, 1, timeout);
if (n <= 0) {
return NONE;
}{...}
return c;
}{ ... }
static ssize_t uart_write(int fd, const void * data, size_t size)
{
assert(fd >= 0 && fd < 3);
const char *data_c = (const char *)data;
/* ... */
_lock_acquire_recursive(&s_ctx[fd]->write_lock);
for (size_t i = 0; i < size; i++) {
int c = data_c[i];
if (c == '\n' && s_ctx[fd]->tx_mode != ESP_LINE_ENDINGS_LF) {
s_ctx[fd]->tx_func(fd, '\r');
if (s_ctx[fd]->tx_mode == ESP_LINE_ENDINGS_CR) {
continue;
}{...}
}{...}
s_ctx[fd]->tx_func(fd, c);
}{...}
_lock_release_recursive(&s_ctx[fd]->write_lock);
return size;
}{ ... }
/* ... */
static int uart_read_char(int fd)
{
if (s_ctx[fd]->peek_char != NONE) {
int c = s_ctx[fd]->peek_char;
s_ctx[fd]->peek_char = NONE;
return c;
}{...}
return s_ctx[fd]->rx_func(fd);
}{ ... }
static void uart_return_char(int fd, int c)
{
assert(s_ctx[fd]->peek_char == NONE);
s_ctx[fd]->peek_char = c;
}{ ... }
static ssize_t uart_read(int fd, void* data, size_t size)
{
assert(fd >= 0 && fd < 3);
char *data_c = (char *) data;
size_t received = 0;
size_t available_size = 0;
int c = NONE;
_lock_acquire_recursive(&s_ctx[fd]->read_lock);
if (!s_ctx[fd]->non_blocking) {
c = uart_read_char(fd);
}{...}
available_size += s_ctx[fd]->get_avail_data_len_func(fd);
if (c != NONE) {
available_size++;
}{...}
if (s_ctx[fd]->peek_char != NONE) {
available_size++;
}{...}
size_t fetch_size = MIN(available_size, size);
if (fetch_size > 0) {
do {
if (c == NONE) {
c = uart_read_char(fd);
}{...}
assert(c != NONE);
if (c == '\r') {
if (s_ctx[fd]->rx_mode == ESP_LINE_ENDINGS_CR) {
c = '\n';
}{...} else if (s_ctx[fd]->rx_mode == ESP_LINE_ENDINGS_CRLF) {
int c2 = uart_read_char(fd);
fetch_size--;
if (c2 == NONE) {
uart_return_char(fd, c);
c = NONE;
break;
}{...}
if (c2 == '\n') {
c = '\n';
}{...} else {
/* ... */
uart_return_char(fd, c2);
fetch_size++;
}{...}
}{...}
}{...}
data_c[received] = (char) c;
++received;
c = NONE;
}{...} while (received < fetch_size);
}{...}
if (c != NONE) {
uart_return_char(fd, c);
}{...}
_lock_release_recursive(&s_ctx[fd]->read_lock);
if (received > 0) {
return received;
}{...}
errno = EWOULDBLOCK;
return -1;
}{ ... }
static int uart_fstat(int fd, struct stat * st)
{
assert(fd >= 0 && fd < 3);
memset(st, 0, sizeof(*st));
st->st_mode = S_IFCHR;
return 0;
}{ ... }
static int uart_close(int fd)
{
assert(fd >= 0 && fd < 3);
return 0;
}{ ... }
static int uart_fcntl(int fd, int cmd, int arg)
{
assert(fd >= 0 && fd < 3);
int result = 0;
if (cmd == F_GETFL) {
result |= O_RDWR;
if (s_ctx[fd]->non_blocking) {
result |= O_NONBLOCK;
}{...}
}{...} else if (cmd == F_SETFL) {
s_ctx[fd]->non_blocking = (arg & O_NONBLOCK) != 0;
}{...} else {
result = -1;
errno = ENOSYS;
}{...}
return result;
}{ ... }
#ifdef CONFIG_VFS_SUPPORT_DIR
static int uart_access(const char *path, int amode)
{
int ret = -1;
if (strcmp(path, "/0") == 0 || strcmp(path, "/1") == 0 || strcmp(path, "/2") == 0) {
if (F_OK == amode) {
ret = 0;
}{...} else {
if ((((amode & R_OK) == R_OK) || ((amode & W_OK) == W_OK)) && ((amode & X_OK) != X_OK)) {
ret = 0;
}{...} else {
errno = EACCES;
}{...}
}{...}
}{...} else {
errno = ENOENT;
}{...}
return ret;
}{ ... }
/* ... */#endif
static int uart_fsync(int fd)
{
assert(fd >= 0 && fd < 3);
_lock_acquire_recursive(&s_ctx[fd]->write_lock);
esp_rom_output_tx_wait_idle((uint8_t) fd);
_lock_release_recursive(&s_ctx[fd]->write_lock);
return 0;
}{ ... }
#ifdef CONFIG_VFS_SUPPORT_SELECT
static esp_err_t register_select(uart_select_args_t *args)
{
esp_err_t ret = ESP_ERR_INVALID_ARG;
if (args) {
portENTER_CRITICAL(&s_registered_select_lock);
const int new_size = s_registered_select_num + 1;
uart_select_args_t **new_selects;
if ((new_selects = heap_caps_realloc(s_registered_selects, new_size * sizeof(uart_select_args_t *), UART_VFS_MALLOC_FLAGS)) == NULL) {
ret = ESP_ERR_NO_MEM;
}{...} else {
s_registered_selects = new_selects;
s_registered_selects[s_registered_select_num] = args;
s_registered_select_num = new_size;
ret = ESP_OK;
}{...}
portEXIT_CRITICAL(&s_registered_select_lock);
}{...}
return ret;
}{ ... }
static esp_err_t unregister_select(uart_select_args_t *args)
{
esp_err_t ret = ESP_OK;
if (args) {
ret = ESP_ERR_INVALID_STATE;
portENTER_CRITICAL(&s_registered_select_lock);
for (int i = 0; i < s_registered_select_num; ++i) {
if (s_registered_selects[i] == args) {
const int new_size = s_registered_select_num - 1;
s_registered_selects[i] = s_registered_selects[new_size];
s_registered_selects = heap_caps_realloc(s_registered_selects, new_size * sizeof(uart_select_args_t *), UART_VFS_MALLOC_FLAGS);
s_registered_select_num = new_size;
ret = ESP_OK;
break;
}{...}
}{...}
portEXIT_CRITICAL(&s_registered_select_lock);
}{...}
return ret;
}{ ... }
static void select_notif_callback_isr(uart_port_t uart_num, uart_select_notif_t uart_select_notif, BaseType_t *task_woken)
{
portENTER_CRITICAL_ISR(&s_registered_select_lock);
for (int i = 0; i < s_registered_select_num; ++i) {
uart_select_args_t *args = s_registered_selects[i];
if (args) {
switch (uart_select_notif) {
case UART_SELECT_READ_NOTIF:
if (FD_ISSET(uart_num, &args->readfds_orig)) {
FD_SET(uart_num, args->readfds);
esp_vfs_select_triggered_isr(args->select_sem, task_woken);
}{...}
break;...
case UART_SELECT_WRITE_NOTIF:
if (FD_ISSET(uart_num, &args->writefds_orig)) {
FD_SET(uart_num, args->writefds);
esp_vfs_select_triggered_isr(args->select_sem, task_woken);
}{...}
break;...
case UART_SELECT_ERROR_NOTIF:
if (FD_ISSET(uart_num, &args->errorfds_orig)) {
FD_SET(uart_num, args->errorfds);
esp_vfs_select_triggered_isr(args->select_sem, task_woken);
}{...}
break;...
}{...}
}{...}
}{...}
portEXIT_CRITICAL_ISR(&s_registered_select_lock);
}{ ... }
static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
esp_vfs_select_sem_t select_sem, void **end_select_args)
{
const int max_fds = MIN(nfds, UART_NUM);
*end_select_args = NULL;
for (int i = 0; i < max_fds; ++i) {
if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds)) {
if (!uart_is_driver_installed(i)) {
return ESP_ERR_INVALID_STATE;
}{...}
}{...}
}{...}
uart_select_args_t *args = heap_caps_malloc(sizeof(uart_select_args_t), UART_VFS_MALLOC_FLAGS);
if (args == NULL) {
return ESP_ERR_NO_MEM;
}{...}
args->select_sem = select_sem;
args->readfds = readfds;
args->writefds = writefds;
args->errorfds = exceptfds;
args->readfds_orig = *readfds;
args->writefds_orig = *writefds;
args->errorfds_orig = *exceptfds;
FD_ZERO(readfds);
FD_ZERO(writefds);
FD_ZERO(exceptfds);
portENTER_CRITICAL(uart_get_selectlock());
for (int i = 0; i < max_fds; ++i) {
if (FD_ISSET(i, &args->readfds_orig) || FD_ISSET(i, &args->writefds_orig) || FD_ISSET(i, &args->errorfds_orig)) {
if (s_uart_select_count[i] == 0) {
uart_set_select_notif_callback(i, select_notif_callback_isr);
}{...}
s_uart_select_count[i]++;
}{...}
}{...}
for (int i = 0; i < max_fds; ++i) {
if (FD_ISSET(i, &args->readfds_orig)) {
size_t buffered_size;
if (uart_get_buffered_data_len(i, &buffered_size) == ESP_OK && buffered_size > 0) {
FD_SET(i, readfds);
esp_vfs_select_triggered(args->select_sem);
}{...}
}{...}
}{...}
esp_err_t ret = register_select(args);
if (ret != ESP_OK) {
portEXIT_CRITICAL(uart_get_selectlock());
free(args);
return ret;
}{...}
portEXIT_CRITICAL(uart_get_selectlock());
*end_select_args = args;
return ESP_OK;
}{ ... }
static esp_err_t uart_end_select(void *end_select_args)
{
uart_select_args_t *args = end_select_args;
portENTER_CRITICAL(uart_get_selectlock());
esp_err_t ret = unregister_select(args);
for (int i = 0; i < UART_NUM; ++i) {
if (FD_ISSET(i, &args->readfds_orig) || FD_ISSET(i, &args->writefds_orig) || FD_ISSET(i, &args->errorfds_orig)) {
s_uart_select_count[i]--;
if (s_uart_select_count[i] == 0) {
uart_set_select_notif_callback(i, NULL);
}{...}
break;
}{...}
}{...}
portEXIT_CRITICAL(uart_get_selectlock());
if (args) {
free(args);
}{...}
return ret;
}{ ... }
/* ... */#endif
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
static int uart_tcsetattr(int fd, int optional_actions, const struct termios *p)
{
if (fd < 0 || fd >= UART_NUM) {
errno = EBADF;
return -1;
}{...}
if (p == NULL) {
errno = EINVAL;
return -1;
}{...}
switch (optional_actions) {
case TCSANOW:
break;...
case TCSADRAIN:
if (uart_wait_tx_done(fd, portMAX_DELAY) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
...
case TCSAFLUSH:
if (uart_flush_input(fd) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
break;...
default:
errno = EINVAL;
return -1;...
}{...}
if (p->c_iflag & IGNCR) {
s_ctx[fd]->rx_mode = ESP_LINE_ENDINGS_CRLF;
}{...} else if (p->c_iflag & ICRNL) {
s_ctx[fd]->rx_mode = ESP_LINE_ENDINGS_CR;
}{...} else {
s_ctx[fd]->rx_mode = ESP_LINE_ENDINGS_LF;
}{...}
{
uart_word_length_t data_bits;
const tcflag_t csize_bits = p->c_cflag & CSIZE;
switch (csize_bits) {
case CS5:
data_bits = UART_DATA_5_BITS;
break;...
case CS6:
data_bits = UART_DATA_6_BITS;
break;...
case CS7:
data_bits = UART_DATA_7_BITS;
break;...
case CS8:
data_bits = UART_DATA_8_BITS;
break;...
default:
errno = EINVAL;
return -1;...
}{...}
if (uart_set_word_length(fd, data_bits) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
}{...}
if (uart_set_stop_bits(fd, (p->c_cflag & CSTOPB) ? UART_STOP_BITS_2 : UART_STOP_BITS_1) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
if (uart_set_parity(fd, (p->c_cflag & PARENB) ?
((p->c_cflag & PARODD) ? UART_PARITY_ODD : UART_PARITY_EVEN)
:
UART_PARITY_DISABLE) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
if (p->c_cflag & (CBAUD | CBAUDEX)) {
if (p->c_ispeed != p->c_ospeed) {
errno = EINVAL;
return -1;
}{...} else {
uint32_t b;
if (p->c_cflag & BOTHER) {
b = p->c_ispeed;
}{...} else {
switch (p->c_ispeed) {
case B0:
b = 0;
break;...
case B50:
b = 50;
break;...
case B75:
b = 75;
break;...
case B110:
b = 110;
break;...
case B134:
b = 134;
break;...
case B150:
b = 150;
break;...
case B200:
b = 200;
break;...
case B300:
b = 300;
break;...
case B600:
b = 600;
break;...
case B1200:
b = 1200;
break;...
case B1800:
b = 1800;
break;...
case B2400:
b = 2400;
break;...
case B4800:
b = 4800;
break;...
case B9600:
b = 9600;
break;...
case B19200:
b = 19200;
break;...
case B38400:
b = 38400;
break;...
case B57600:
b = 57600;
break;...
case B115200:
b = 115200;
break;...
case B230400:
b = 230400;
break;...
case B460800:
b = 460800;
break;...
case B500000:
b = 500000;
break;...
case B576000:
b = 576000;
break;...
case B921600:
b = 921600;
break;...
case B1000000:
b = 1000000;
break;...
case B1152000:
b = 1152000;
break;...
case B1500000:
b = 1500000;
break;...
case B2000000:
b = 2000000;
break;...
case B2500000:
b = 2500000;
break;...
case B3000000:
b = 3000000;
break;...
case B3500000:
b = 3500000;
break;...
case B4000000:
b = 4000000;
break;...
default:
errno = EINVAL;
return -1;...
}{...}
}{...}
if (uart_set_baudrate(fd, b) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
}{...}
}{...}
return 0;
}{ ... }
static int uart_tcgetattr(int fd, struct termios *p)
{
if (fd < 0 || fd >= UART_NUM) {
errno = EBADF;
return -1;
}{...}
if (p == NULL) {
errno = EINVAL;
return -1;
}{...}
memset(p, 0, sizeof(struct termios));
if (s_ctx[fd]->rx_mode == ESP_LINE_ENDINGS_CRLF) {
p->c_iflag |= IGNCR;
}{...} else if (s_ctx[fd]->rx_mode == ESP_LINE_ENDINGS_CR) {
p->c_iflag |= ICRNL;
}{...}
{
uart_word_length_t data_bits;
if (uart_get_word_length(fd, &data_bits) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
p->c_cflag &= (~CSIZE);
switch (data_bits) {
case UART_DATA_5_BITS:
p->c_cflag |= CS5;
break;...
case UART_DATA_6_BITS:
p->c_cflag |= CS6;
break;...
case UART_DATA_7_BITS:
p->c_cflag |= CS7;
break;...
case UART_DATA_8_BITS:
p->c_cflag |= CS8;
break;...
default:
errno = ENOSYS;
return -1;...
}{...}
}{...}
{
uart_stop_bits_t stop_bits;
if (uart_get_stop_bits(fd, &stop_bits) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
switch (stop_bits) {
case UART_STOP_BITS_1:
break;...
case UART_STOP_BITS_2:
p->c_cflag |= CSTOPB;
break;...
default:
errno = ENOSYS;
return -1;...
}{...}
}{...}
{
uart_parity_t parity_mode;
if (uart_get_parity(fd, &parity_mode) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
switch (parity_mode) {
case UART_PARITY_EVEN:
p->c_cflag |= PARENB;
break;...
case UART_PARITY_ODD:
p->c_cflag |= (PARENB | PARODD);
break;...
case UART_PARITY_DISABLE:
break;...
default:
errno = ENOSYS;
return -1;...
}{...}
}{...}
{
uint32_t baudrate;
if (uart_get_baudrate(fd, &baudrate) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
p->c_cflag |= (CBAUD | CBAUDEX);
speed_t sp;
switch (baudrate) {
case 0:
sp = B0;
break;...
case 50:
sp = B50;
break;...
case 75:
sp = B75;
break;...
case 110:
sp = B110;
break;...
case 134:
sp = B134;
break;...
case 150:
sp = B150;
break;...
case 200:
sp = B200;
break;...
case 300:
sp = B300;
break;...
case 600:
sp = B600;
break;...
case 1200:
sp = B1200;
break;...
case 1800:
sp = B1800;
break;...
case 2400:
sp = B2400;
break;...
case 4800:
sp = B4800;
break;...
case 9600:
sp = B9600;
break;...
case 19200:
sp = B19200;
break;...
case 38400:
sp = B38400;
break;...
case 57600:
sp = B57600;
break;...
case 115200:
sp = B115200;
break;...
case 230400:
sp = B230400;
break;...
case 460800:
sp = B460800;
break;...
case 500000:
sp = B500000;
break;...
case 576000:
sp = B576000;
break;...
case 921600:
sp = B921600;
break;...
case 1000000:
sp = B1000000;
break;...
case 1152000:
sp = B1152000;
break;...
case 1500000:
sp = B1500000;
break;...
case 2000000:
sp = B2000000;
break;...
case 2500000:
sp = B2500000;
break;...
case 3000000:
sp = B3000000;
break;...
case 3500000:
sp = B3500000;
break;...
case 4000000:
sp = B4000000;
break;...
default:
p->c_cflag |= BOTHER;
sp = baudrate;
break;...
}{...}
p->c_ispeed = p->c_ospeed = sp;
}{...}
return 0;
}{ ... }
static int uart_tcdrain(int fd)
{
if (fd < 0 || fd >= UART_NUM) {
errno = EBADF;
return -1;
}{...}
if (uart_wait_tx_done(fd, portMAX_DELAY) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
return 0;
}{ ... }
static int uart_tcflush(int fd, int select)
{
if (fd < 0 || fd >= UART_NUM) {
errno = EBADF;
return -1;
}{...}
if (select == TCIFLUSH) {
if (uart_flush_input(fd) != ESP_OK) {
errno = EINVAL;
return -1;
}{...}
}{...} else {
errno = EINVAL;
return -1;
}{...}
return 0;
}{ ... }
#endif/* ... */
#ifdef CONFIG_VFS_SUPPORT_DIR
static const esp_vfs_dir_ops_t s_vfs_uart_dir = {
.access = &uart_access,
}{...};
/* ... */#endif
#ifdef CONFIG_VFS_SUPPORT_SELECT
static const esp_vfs_select_ops_t s_vfs_uart_select = {
.start_select = &uart_start_select,
.end_select = &uart_end_select,
}{...};
/* ... */#endif
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
static const esp_vfs_termios_ops_t s_vfs_uart_termios = {
.tcsetattr = &uart_tcsetattr,
.tcgetattr = &uart_tcgetattr,
.tcdrain = &uart_tcdrain,
.tcflush = &uart_tcflush,
}{...};
/* ... */#endif
static const esp_vfs_fs_ops_t s_vfs_uart = {
.write = &uart_write,
.open = &uart_open,
.fstat = &uart_fstat,
.close = &uart_close,
.read = &uart_read,
.fcntl = &uart_fcntl,
.fsync = &uart_fsync,
#ifdef CONFIG_VFS_SUPPORT_DIR
.dir = &s_vfs_uart_dir,
#endif
#ifdef CONFIG_VFS_SUPPORT_SELECT
.select = &s_vfs_uart_select,
#endif
#ifdef CONFIG_VFS_SUPPORT_TERMIOS
.termios = &s_vfs_uart_termios,
#endif
}{...};
const esp_vfs_fs_ops_t *esp_vfs_uart_get_vfs(void)
{
return &s_vfs_uart;
}{ ... }
void uart_vfs_dev_register(void)
{
ESP_ERROR_CHECK(esp_vfs_register_fs("/dev/uart", &s_vfs_uart, ESP_VFS_FLAG_STATIC, NULL));
}{ ... }
int uart_vfs_dev_port_set_rx_line_endings(int uart_num, esp_line_endings_t mode)
{
if (uart_num < 0 || uart_num >= UART_NUM) {
errno = EBADF;
return -1;
}{...}
s_ctx[uart_num]->rx_mode = mode;
return 0;
}{ ... }
int uart_vfs_dev_port_set_tx_line_endings(int uart_num, esp_line_endings_t mode)
{
if (uart_num < 0 || uart_num >= UART_NUM) {
errno = EBADF;
return -1;
}{...}
s_ctx[uart_num]->tx_mode = mode;
return 0;
}{ ... }
void uart_vfs_dev_set_rx_line_endings(esp_line_endings_t mode)
{
for (int i = 0; i < UART_NUM; ++i) {
s_ctx[i]->rx_mode = mode;
}{...}
}{ ... }
void uart_vfs_dev_set_tx_line_endings(esp_line_endings_t mode)
{
for (int i = 0; i < UART_NUM; ++i) {
s_ctx[i]->tx_mode = mode;
}{...}
}{ ... }
void uart_vfs_dev_use_nonblocking(int uart_num)
{
_lock_acquire_recursive(&s_ctx[uart_num]->read_lock);
_lock_acquire_recursive(&s_ctx[uart_num]->write_lock);
s_ctx[uart_num]->tx_func = uart_tx_char;
s_ctx[uart_num]->rx_func = uart_rx_char;
s_ctx[uart_num]->get_avail_data_len_func = uart_get_avail_data_len;
_lock_release_recursive(&s_ctx[uart_num]->write_lock);
_lock_release_recursive(&s_ctx[uart_num]->read_lock);
}{ ... }
void uart_vfs_dev_use_driver(int uart_num)
{
_lock_acquire_recursive(&s_ctx[uart_num]->read_lock);
_lock_acquire_recursive(&s_ctx[uart_num]->write_lock);
s_ctx[uart_num]->tx_func = uart_tx_char_via_driver;
s_ctx[uart_num]->rx_func = uart_rx_char_via_driver;
s_ctx[uart_num]->get_avail_data_len_func = uart_get_avail_data_len_via_driver;
_lock_release_recursive(&s_ctx[uart_num]->write_lock);
_lock_release_recursive(&s_ctx[uart_num]->read_lock);
}{ ... }
#if CONFIG_ESP_CONSOLE_UART
ESP_SYSTEM_INIT_FN(init_vfs_uart, CORE, BIT(0), 110)
{
uart_vfs_dev_register();
return ESP_OK;
}{ ... }
#endif
void uart_vfs_include_dev_init(void)
{
}{ ... }
void esp_vfs_dev_uart_register(void) __attribute__((alias("uart_vfs_dev_register")));
void esp_vfs_dev_uart_set_rx_line_endings(esp_line_endings_t mode) __attribute__((alias("uart_vfs_dev_set_rx_line_endings")));
void esp_vfs_dev_uart_set_tx_line_endings(esp_line_endings_t mode) __attribute__((alias("uart_vfs_dev_set_tx_line_endings")));
int esp_vfs_dev_uart_port_set_rx_line_endings(int uart_num, esp_line_endings_t mode) __attribute__((alias("uart_vfs_dev_port_set_rx_line_endings")));
int esp_vfs_dev_uart_port_set_tx_line_endings(int uart_num, esp_line_endings_t mode) __attribute__((alias("uart_vfs_dev_port_set_tx_line_endings")));
void esp_vfs_dev_uart_use_nonblocking(int uart_num) __attribute__((alias("uart_vfs_dev_use_nonblocking")));
esp_vfs_dev_uart_xxx ALIAS (deprecated)
void esp_vfs_dev_uart_use_driver(int uart_num) __attribute__((alias("uart_vfs_dev_use_driver")));