1 /*
2 * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <string.h>
8 #include <stdbool.h>
9 #include <stdarg.h>
10 #include <sys/errno.h>
11 #include <sys/lock.h>
12 #include <sys/fcntl.h>
13 #include <sys/param.h>
14 #include "esp_vfs.h"
15 #include "esp_vfs_dev.h"
16 #include "esp_attr.h"
17 #include "soc/uart_periph.h"
18 #include "driver/uart.h"
19 #include "sdkconfig.h"
20 #include "driver/uart_select.h"
21 #include "esp_rom_uart.h"
22 #include "soc/soc_caps.h"
23 #include "hal/uart_ll.h"
24
25 // TODO: make the number of UARTs chip dependent
26 #define UART_NUM SOC_UART_NUM
27
28 // Token signifying that no character is available
29 #define NONE -1
30
31 #if CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF
32 # define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CRLF
33 #elif CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR
34 # define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CR
35 #else
36 # define DEFAULT_TX_MODE ESP_LINE_ENDINGS_LF
37 #endif
38
39 #if CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF
40 # define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CRLF
41 #elif CONFIG_NEWLIB_STDIN_LINE_ENDING_CR
42 # define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CR
43 #else
44 # define DEFAULT_RX_MODE ESP_LINE_ENDINGS_LF
45 #endif
46
47 // UART write bytes function type
48 typedef void (*tx_func_t)(int, int);
49 // UART read bytes function type
50 typedef int (*rx_func_t)(int);
51
52 // Basic functions for sending and receiving bytes over UART
53 static void uart_tx_char(int fd, int c);
54 static int uart_rx_char(int fd);
55
56 // Functions for sending and receiving bytes which use UART driver
57 static void uart_tx_char_via_driver(int fd, int c);
58 static int uart_rx_char_via_driver(int fd);
59
60 typedef struct {
61 // Pointers to UART peripherals
62 uart_dev_t* uart;
63 // One-character buffer used for newline conversion code, per UART
64 int peek_char;
65 // per-UART locks, lazily initialized
66 _lock_t read_lock;
67 _lock_t write_lock;
68 // Per-UART non-blocking flag. Note: default implementation does not honor this
69 // flag, all reads are non-blocking. This option becomes effective if UART
70 // driver is used.
71 bool non_blocking;
72 // Newline conversion mode when transmitting
73 esp_line_endings_t tx_mode;
74 // Newline conversion mode when receiving
75 esp_line_endings_t rx_mode;
76 // Functions used to write bytes to UART. Default to "basic" functions.
77 tx_func_t tx_func;
78 // Functions used to read bytes from UART. Default to "basic" functions.
79 rx_func_t rx_func;
80 } vfs_uart_context_t;
81
82 #define VFS_CTX_DEFAULT_VAL(uart_dev) (vfs_uart_context_t) {\
83 .uart = (uart_dev),\
84 .peek_char = NONE,\
85 .tx_mode = DEFAULT_TX_MODE,\
86 .rx_mode = DEFAULT_RX_MODE,\
87 .tx_func = uart_tx_char,\
88 .rx_func = uart_rx_char,\
89 }
90
91 //If the context should be dynamically initialized, remove this structure
92 //and point s_ctx to allocated data.
93 static vfs_uart_context_t s_context[UART_NUM] = {
94 VFS_CTX_DEFAULT_VAL(&UART0),
95 VFS_CTX_DEFAULT_VAL(&UART1),
96 #if UART_NUM > 2
97 VFS_CTX_DEFAULT_VAL(&UART2),
98 #endif
99 };
100
101 static vfs_uart_context_t* s_ctx[UART_NUM] = {
102 &s_context[0],
103 &s_context[1],
104 #if UART_NUM > 2
105 &s_context[2],
106 #endif
107 };
108
109 #ifdef CONFIG_VFS_SUPPORT_SELECT
110
111 typedef struct {
112 esp_vfs_select_sem_t select_sem;
113 fd_set *readfds;
114 fd_set *writefds;
115 fd_set *errorfds;
116 fd_set readfds_orig;
117 fd_set writefds_orig;
118 fd_set errorfds_orig;
119 } uart_select_args_t;
120
121 static uart_select_args_t **s_registered_selects = NULL;
122 static int s_registered_select_num = 0;
123 static portMUX_TYPE s_registered_select_lock = portMUX_INITIALIZER_UNLOCKED;
124
125 static esp_err_t uart_end_select(void *end_select_args);
126
127 #endif // CONFIG_VFS_SUPPORT_SELECT
128
uart_open(const char * path,int flags,int mode)129 static int uart_open(const char * path, int flags, int mode)
130 {
131 // this is fairly primitive, we should check if file is opened read only,
132 // and error out if write is requested
133 int fd = -1;
134
135 if (strcmp(path, "/0") == 0) {
136 fd = 0;
137 } else if (strcmp(path, "/1") == 0) {
138 fd = 1;
139 } else if (strcmp(path, "/2") == 0) {
140 fd = 2;
141 } else {
142 errno = ENOENT;
143 return fd;
144 }
145
146 s_ctx[fd]->non_blocking = ((flags & O_NONBLOCK) == O_NONBLOCK);
147
148 return fd;
149 }
150
uart_tx_char(int fd,int c)151 static void uart_tx_char(int fd, int c)
152 {
153 uart_dev_t* uart = s_ctx[fd]->uart;
154 const uint8_t ch = (uint8_t) c;
155
156 while (uart_ll_get_txfifo_len(uart) < 2) {
157 ;
158 }
159
160 uart_ll_write_txfifo(uart, &ch, 1);
161 }
162
uart_tx_char_via_driver(int fd,int c)163 static void uart_tx_char_via_driver(int fd, int c)
164 {
165 char ch = (char) c;
166 uart_write_bytes(fd, &ch, 1);
167 }
168
uart_rx_char(int fd)169 static int uart_rx_char(int fd)
170 {
171 uart_dev_t* uart = s_ctx[fd]->uart;
172 uint8_t ch;
173 if (uart_ll_get_rxfifo_len(uart) == 0) {
174 return NONE;
175 }
176 uart_ll_read_rxfifo(uart, &ch, 1);
177
178 return ch;
179 }
180
uart_rx_char_via_driver(int fd)181 static int uart_rx_char_via_driver(int fd)
182 {
183 uint8_t c;
184 int timeout = s_ctx[fd]->non_blocking ? 0 : portMAX_DELAY;
185 int n = uart_read_bytes(fd, &c, 1, timeout);
186 if (n <= 0) {
187 return NONE;
188 }
189 return c;
190 }
191
uart_write(int fd,const void * data,size_t size)192 static ssize_t uart_write(int fd, const void * data, size_t size)
193 {
194 assert(fd >=0 && fd < 3);
195 const char *data_c = (const char *)data;
196 /* Even though newlib does stream locking on each individual stream, we need
197 * a dedicated UART lock if two streams (stdout and stderr) point to the
198 * same UART.
199 */
200 _lock_acquire_recursive(&s_ctx[fd]->write_lock);
201 for (size_t i = 0; i < size; i++) {
202 int c = data_c[i];
203 if (c == '\n' && s_ctx[fd]->tx_mode != ESP_LINE_ENDINGS_LF) {
204 s_ctx[fd]->tx_func(fd, '\r');
205 if (s_ctx[fd]->tx_mode == ESP_LINE_ENDINGS_CR) {
206 continue;
207 }
208 }
209 s_ctx[fd]->tx_func(fd, c);
210 }
211 _lock_release_recursive(&s_ctx[fd]->write_lock);
212 return size;
213 }
214
215 /* Helper function which returns a previous character or reads a new one from
216 * UART. Previous character can be returned ("pushed back") using
217 * uart_return_char function.
218 */
uart_read_char(int fd)219 static int uart_read_char(int fd)
220 {
221 /* return character from peek buffer, if it is there */
222 if (s_ctx[fd]->peek_char != NONE) {
223 int c = s_ctx[fd]->peek_char;
224 s_ctx[fd]->peek_char = NONE;
225 return c;
226 }
227 return s_ctx[fd]->rx_func(fd);
228 }
229
230 /* Push back a character; it will be returned by next call to uart_read_char */
uart_return_char(int fd,int c)231 static void uart_return_char(int fd, int c)
232 {
233 assert(s_ctx[fd]->peek_char == NONE);
234 s_ctx[fd]->peek_char = c;
235 }
236
uart_read(int fd,void * data,size_t size)237 static ssize_t uart_read(int fd, void* data, size_t size)
238 {
239 assert(fd >=0 && fd < 3);
240 char *data_c = (char *) data;
241 size_t received = 0;
242 _lock_acquire_recursive(&s_ctx[fd]->read_lock);
243 while (received < size) {
244 int c = uart_read_char(fd);
245 if (c == '\r') {
246 if (s_ctx[fd]->rx_mode == ESP_LINE_ENDINGS_CR) {
247 c = '\n';
248 } else if (s_ctx[fd]->rx_mode == ESP_LINE_ENDINGS_CRLF) {
249 /* look ahead */
250 int c2 = uart_read_char(fd);
251 if (c2 == NONE) {
252 /* could not look ahead, put the current character back */
253 uart_return_char(fd, c);
254 break;
255 }
256 if (c2 == '\n') {
257 /* this was \r\n sequence. discard \r, return \n */
258 c = '\n';
259 } else {
260 /* \r followed by something else. put the second char back,
261 * it will be processed on next iteration. return \r now.
262 */
263 uart_return_char(fd, c2);
264 }
265 }
266 } else if (c == NONE) {
267 break;
268 }
269 data_c[received] = (char) c;
270 ++received;
271 if (c == '\n') {
272 break;
273 }
274 }
275 _lock_release_recursive(&s_ctx[fd]->read_lock);
276 if (received > 0) {
277 return received;
278 }
279 errno = EWOULDBLOCK;
280 return -1;
281 }
282
uart_fstat(int fd,struct stat * st)283 static int uart_fstat(int fd, struct stat * st)
284 {
285 assert(fd >=0 && fd < 3);
286 memset(st, 0, sizeof(*st));
287 st->st_mode = S_IFCHR;
288 return 0;
289 }
290
uart_close(int fd)291 static int uart_close(int fd)
292 {
293 assert(fd >=0 && fd < 3);
294 return 0;
295 }
296
uart_fcntl(int fd,int cmd,int arg)297 static int uart_fcntl(int fd, int cmd, int arg)
298 {
299 assert(fd >=0 && fd < 3);
300 int result = 0;
301 if (cmd == F_GETFL) {
302 if (s_ctx[fd]->non_blocking) {
303 result |= O_NONBLOCK;
304 }
305 } else if (cmd == F_SETFL) {
306 s_ctx[fd]->non_blocking = (arg & O_NONBLOCK) != 0;
307 } else {
308 // unsupported operation
309 result = -1;
310 errno = ENOSYS;
311 }
312 return result;
313 }
314
315 #ifdef CONFIG_VFS_SUPPORT_DIR
316
uart_access(const char * path,int amode)317 static int uart_access(const char *path, int amode)
318 {
319 int ret = -1;
320
321 if (strcmp(path, "/0") == 0 || strcmp(path, "/1") == 0 || strcmp(path, "/2") == 0) {
322 if (F_OK == amode) {
323 ret = 0; //path exists
324 } else {
325 if ((((amode & R_OK) == R_OK) || ((amode & W_OK) == W_OK)) && ((amode & X_OK) != X_OK)) {
326 ret = 0; //path is readable and/or writable but not executable
327 } else {
328 errno = EACCES;
329 }
330 }
331 } else {
332 errno = ENOENT;
333 }
334
335 return ret;
336 }
337
338 #endif // CONFIG_VFS_SUPPORT_DIR
339
uart_fsync(int fd)340 static int uart_fsync(int fd)
341 {
342 assert(fd >= 0 && fd < 3);
343 _lock_acquire_recursive(&s_ctx[fd]->write_lock);
344 esp_rom_uart_tx_wait_idle((uint8_t) fd);
345 _lock_release_recursive(&s_ctx[fd]->write_lock);
346 return 0;
347 }
348
349 #ifdef CONFIG_VFS_SUPPORT_SELECT
350
register_select(uart_select_args_t * args)351 static esp_err_t register_select(uart_select_args_t *args)
352 {
353 esp_err_t ret = ESP_ERR_INVALID_ARG;
354
355 if (args) {
356 portENTER_CRITICAL(&s_registered_select_lock);
357 const int new_size = s_registered_select_num + 1;
358 uart_select_args_t **new_selects;
359 if ((new_selects = realloc(s_registered_selects, new_size * sizeof(uart_select_args_t *))) == NULL) {
360 ret = ESP_ERR_NO_MEM;
361 } else {
362 s_registered_selects = new_selects;
363 s_registered_selects[s_registered_select_num] = args;
364 s_registered_select_num = new_size;
365 ret = ESP_OK;
366 }
367 portEXIT_CRITICAL(&s_registered_select_lock);
368 }
369
370 return ret;
371 }
372
unregister_select(uart_select_args_t * args)373 static esp_err_t unregister_select(uart_select_args_t *args)
374 {
375 esp_err_t ret = ESP_OK;
376 if (args) {
377 ret = ESP_ERR_INVALID_STATE;
378 portENTER_CRITICAL(&s_registered_select_lock);
379 for (int i = 0; i < s_registered_select_num; ++i) {
380 if (s_registered_selects[i] == args) {
381 const int new_size = s_registered_select_num - 1;
382 // The item is removed by overwriting it with the last item. The subsequent rellocation will drop the
383 // last item.
384 s_registered_selects[i] = s_registered_selects[new_size];
385 s_registered_selects = realloc(s_registered_selects, new_size * sizeof(uart_select_args_t *));
386 // Shrinking a buffer with realloc is guaranteed to succeed.
387 s_registered_select_num = new_size;
388 ret = ESP_OK;
389 break;
390 }
391 }
392 portEXIT_CRITICAL(&s_registered_select_lock);
393 }
394 return ret;
395 }
396
select_notif_callback_isr(uart_port_t uart_num,uart_select_notif_t uart_select_notif,BaseType_t * task_woken)397 static void select_notif_callback_isr(uart_port_t uart_num, uart_select_notif_t uart_select_notif, BaseType_t *task_woken)
398 {
399 portENTER_CRITICAL_ISR(&s_registered_select_lock);
400 for (int i = 0; i < s_registered_select_num; ++i) {
401 uart_select_args_t *args = s_registered_selects[i];
402 if (args) {
403 switch (uart_select_notif) {
404 case UART_SELECT_READ_NOTIF:
405 if (FD_ISSET(uart_num, &args->readfds_orig)) {
406 FD_SET(uart_num, args->readfds);
407 esp_vfs_select_triggered_isr(args->select_sem, task_woken);
408 }
409 break;
410 case UART_SELECT_WRITE_NOTIF:
411 if (FD_ISSET(uart_num, &args->writefds_orig)) {
412 FD_SET(uart_num, args->writefds);
413 esp_vfs_select_triggered_isr(args->select_sem, task_woken);
414 }
415 break;
416 case UART_SELECT_ERROR_NOTIF:
417 if (FD_ISSET(uart_num, &args->errorfds_orig)) {
418 FD_SET(uart_num, args->errorfds);
419 esp_vfs_select_triggered_isr(args->select_sem, task_woken);
420 }
421 break;
422 }
423 }
424 }
425 portEXIT_CRITICAL_ISR(&s_registered_select_lock);
426 }
427
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)428 static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
429 esp_vfs_select_sem_t select_sem, void **end_select_args)
430 {
431 const int max_fds = MIN(nfds, UART_NUM);
432 *end_select_args = NULL;
433
434 for (int i = 0; i < max_fds; ++i) {
435 if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds)) {
436 if (!uart_is_driver_installed(i)) {
437 return ESP_ERR_INVALID_STATE;
438 }
439 }
440 }
441
442 uart_select_args_t *args = malloc(sizeof(uart_select_args_t));
443
444 if (args == NULL) {
445 return ESP_ERR_NO_MEM;
446 }
447
448 args->select_sem = select_sem;
449 args->readfds = readfds;
450 args->writefds = writefds;
451 args->errorfds = exceptfds;
452 args->readfds_orig = *readfds; // store the original values because they will be set to zero
453 args->writefds_orig = *writefds;
454 args->errorfds_orig = *exceptfds;
455 FD_ZERO(readfds);
456 FD_ZERO(writefds);
457 FD_ZERO(exceptfds);
458
459 portENTER_CRITICAL(uart_get_selectlock());
460
461 //uart_set_select_notif_callback sets the callbacks in UART ISR
462 for (int i = 0; i < max_fds; ++i) {
463 if (FD_ISSET(i, &args->readfds_orig) || FD_ISSET(i, &args->writefds_orig) || FD_ISSET(i, &args->errorfds_orig)) {
464 uart_set_select_notif_callback(i, select_notif_callback_isr);
465 }
466 }
467
468 for (int i = 0; i < max_fds; ++i) {
469 if (FD_ISSET(i, &args->readfds_orig)) {
470 size_t buffered_size;
471 if (uart_get_buffered_data_len(i, &buffered_size) == ESP_OK && buffered_size > 0) {
472 // signalize immediately when data is buffered
473 FD_SET(i, readfds);
474 esp_vfs_select_triggered(args->select_sem);
475 }
476 }
477 }
478
479 esp_err_t ret = register_select(args);
480 if (ret != ESP_OK) {
481 portEXIT_CRITICAL(uart_get_selectlock());
482 free(args);
483 return ret;
484 }
485
486 portEXIT_CRITICAL(uart_get_selectlock());
487
488 *end_select_args = args;
489 return ESP_OK;
490 }
491
uart_end_select(void * end_select_args)492 static esp_err_t uart_end_select(void *end_select_args)
493 {
494 uart_select_args_t *args = end_select_args;
495
496 portENTER_CRITICAL(uart_get_selectlock());
497 esp_err_t ret = unregister_select(args);
498 for (int i = 0; i < UART_NUM; ++i) {
499 uart_set_select_notif_callback(i, NULL);
500 }
501 portEXIT_CRITICAL(uart_get_selectlock());
502
503 if (args) {
504 free(args);
505 }
506
507 return ret;
508 }
509
510 #endif // CONFIG_VFS_SUPPORT_SELECT
511
512 #ifdef CONFIG_VFS_SUPPORT_TERMIOS
uart_tcsetattr(int fd,int optional_actions,const struct termios * p)513 static int uart_tcsetattr(int fd, int optional_actions, const struct termios *p)
514 {
515 if (fd < 0 || fd >= UART_NUM) {
516 errno = EBADF;
517 return -1;
518 }
519
520 if (p == NULL) {
521 errno = EINVAL;
522 return -1;
523 }
524
525 switch (optional_actions) {
526 case TCSANOW:
527 // nothing to do
528 break;
529 case TCSADRAIN:
530 if (uart_wait_tx_done(fd, portMAX_DELAY) != ESP_OK) {
531 errno = EINVAL;
532 return -1;
533 }
534
535 /* FALLTHRU */
536
537 case TCSAFLUSH:
538 if (uart_flush_input(fd) != ESP_OK) {
539 errno = EINVAL;
540 return -1;
541 }
542 break;
543 default:
544 errno = EINVAL;
545 return -1;
546 }
547
548 if (p->c_iflag & IGNCR) {
549 s_ctx[fd]->rx_mode = ESP_LINE_ENDINGS_CRLF;
550 } else if (p->c_iflag & ICRNL) {
551 s_ctx[fd]->rx_mode = ESP_LINE_ENDINGS_CR;
552 } else {
553 s_ctx[fd]->rx_mode = ESP_LINE_ENDINGS_LF;
554 }
555
556 // output line endings are not supported because there is no alternative in termios for converting LF to CR
557
558 {
559 uart_word_length_t data_bits;
560 const tcflag_t csize_bits = p->c_cflag & CSIZE;
561
562 switch (csize_bits) {
563 case CS5:
564 data_bits = UART_DATA_5_BITS;
565 break;
566 case CS6:
567 data_bits = UART_DATA_6_BITS;
568 break;
569 case CS7:
570 data_bits = UART_DATA_7_BITS;
571 break;
572 case CS8:
573 data_bits = UART_DATA_8_BITS;
574 break;
575 default:
576 errno = EINVAL;
577 return -1;
578 }
579
580 if (uart_set_word_length(fd, data_bits) != ESP_OK) {
581 errno = EINVAL;
582 return -1;
583 }
584 }
585
586 if (uart_set_stop_bits(fd, (p->c_cflag & CSTOPB) ? UART_STOP_BITS_2 : UART_STOP_BITS_1) != ESP_OK) {
587 errno = EINVAL;
588 return -1;
589 }
590
591 if (uart_set_parity(fd, (p->c_cflag & PARENB) ?
592 ((p->c_cflag & PARODD) ? UART_PARITY_ODD : UART_PARITY_EVEN)
593 :
594 UART_PARITY_DISABLE) != ESP_OK) {
595 errno = EINVAL;
596 return -1;
597 }
598
599 if (p->c_cflag & (CBAUD | CBAUDEX)) {
600 if (p->c_ispeed != p->c_ospeed) {
601 errno = EINVAL;
602 return -1;
603 } else {
604 uint32_t b;
605 if (p->c_cflag & BOTHER) {
606 b = p->c_ispeed;
607 } else {
608 switch (p->c_ispeed) {
609 case B0:
610 b = 0;
611 break;
612 case B50:
613 b = 50;
614 break;
615 case B75:
616 b = 75;
617 break;
618 case B110:
619 b = 110;
620 break;
621 case B134:
622 b = 134;
623 break;
624 case B150:
625 b = 150;
626 break;
627 case B200:
628 b = 200;
629 break;
630 case B300:
631 b = 300;
632 break;
633 case B600:
634 b = 600;
635 break;
636 case B1200:
637 b = 1200;
638 break;
639 case B1800:
640 b = 1800;
641 break;
642 case B2400:
643 b = 2400;
644 break;
645 case B4800:
646 b = 4800;
647 break;
648 case B9600:
649 b = 9600;
650 break;
651 case B19200:
652 b = 19200;
653 break;
654 case B38400:
655 b = 38400;
656 break;
657 case B57600:
658 b = 57600;
659 break;
660 case B115200:
661 b = 115200;
662 break;
663 case B230400:
664 b = 230400;
665 break;
666 case B460800:
667 b = 460800;
668 break;
669 case B500000:
670 b = 500000;
671 break;
672 case B576000:
673 b = 576000;
674 break;
675 case B921600:
676 b = 921600;
677 break;
678 case B1000000:
679 b = 1000000;
680 break;
681 case B1152000:
682 b = 1152000;
683 break;
684 case B1500000:
685 b = 1500000;
686 break;
687 case B2000000:
688 b = 2000000;
689 break;
690 case B2500000:
691 b = 2500000;
692 break;
693 case B3000000:
694 b = 3000000;
695 break;
696 case B3500000:
697 b = 3500000;
698 break;
699 case B4000000:
700 b = 4000000;
701 break;
702 default:
703 errno = EINVAL;
704 return -1;
705 }
706 }
707
708 if (uart_set_baudrate(fd, b) != ESP_OK) {
709 errno = EINVAL;
710 return -1;
711 }
712 }
713 }
714
715 return 0;
716 }
717
uart_tcgetattr(int fd,struct termios * p)718 static int uart_tcgetattr(int fd, struct termios *p)
719 {
720 if (fd < 0 || fd >= UART_NUM) {
721 errno = EBADF;
722 return -1;
723 }
724
725 if (p == NULL) {
726 errno = EINVAL;
727 return -1;
728 }
729
730 memset(p, 0, sizeof(struct termios));
731
732 if (s_ctx[fd]->rx_mode == ESP_LINE_ENDINGS_CRLF) {
733 p->c_iflag |= IGNCR;
734 } else if (s_ctx[fd]->rx_mode == ESP_LINE_ENDINGS_CR) {
735 p->c_iflag |= ICRNL;
736 }
737
738 {
739 uart_word_length_t data_bits;
740
741 if (uart_get_word_length(fd, &data_bits) != ESP_OK) {
742 errno = EINVAL;
743 return -1;
744 }
745
746 p->c_cflag &= (~CSIZE);
747
748 switch (data_bits) {
749 case UART_DATA_5_BITS:
750 p->c_cflag |= CS5;
751 break;
752 case UART_DATA_6_BITS:
753 p->c_cflag |= CS6;
754 break;
755 case UART_DATA_7_BITS:
756 p->c_cflag |= CS7;
757 break;
758 case UART_DATA_8_BITS:
759 p->c_cflag |= CS8;
760 break;
761 default:
762 errno = ENOSYS;
763 return -1;
764 }
765 }
766
767 {
768 uart_stop_bits_t stop_bits;
769 if (uart_get_stop_bits(fd, &stop_bits) != ESP_OK) {
770 errno = EINVAL;
771 return -1;
772 }
773
774 switch (stop_bits) {
775 case UART_STOP_BITS_1:
776 // nothing to do
777 break;
778 case UART_STOP_BITS_2:
779 p->c_cflag |= CSTOPB;
780 break;
781 default:
782 // UART_STOP_BITS_1_5 is unsupported by termios
783 errno = ENOSYS;
784 return -1;
785 }
786 }
787
788 {
789 uart_parity_t parity_mode;
790 if (uart_get_parity(fd, &parity_mode) != ESP_OK) {
791 errno = EINVAL;
792 return -1;
793 }
794
795 switch (parity_mode) {
796 case UART_PARITY_EVEN:
797 p->c_cflag |= PARENB;
798 break;
799 case UART_PARITY_ODD:
800 p->c_cflag |= (PARENB | PARODD);
801 break;
802 case UART_PARITY_DISABLE:
803 // nothing to do
804 break;
805 default:
806 errno = ENOSYS;
807 return -1;
808 }
809 }
810
811 {
812 uint32_t baudrate;
813 if (uart_get_baudrate(fd, &baudrate) != ESP_OK) {
814 errno = EINVAL;
815 return -1;
816 }
817
818 p->c_cflag |= (CBAUD | CBAUDEX);
819
820 speed_t sp;
821 switch (baudrate) {
822 case 0:
823 sp = B0;
824 break;
825 case 50:
826 sp = B50;
827 break;
828 case 75:
829 sp = B75;
830 break;
831 case 110:
832 sp = B110;
833 break;
834 case 134:
835 sp = B134;
836 break;
837 case 150:
838 sp = B150;
839 break;
840 case 200:
841 sp = B200;
842 break;
843 case 300:
844 sp = B300;
845 break;
846 case 600:
847 sp = B600;
848 break;
849 case 1200:
850 sp = B1200;
851 break;
852 case 1800:
853 sp = B1800;
854 break;
855 case 2400:
856 sp = B2400;
857 break;
858 case 4800:
859 sp = B4800;
860 break;
861 case 9600:
862 sp = B9600;
863 break;
864 case 19200:
865 sp = B19200;
866 break;
867 case 38400:
868 sp = B38400;
869 break;
870 case 57600:
871 sp = B57600;
872 break;
873 case 115200:
874 sp = B115200;
875 break;
876 case 230400:
877 sp = B230400;
878 break;
879 case 460800:
880 sp = B460800;
881 break;
882 case 500000:
883 sp = B500000;
884 break;
885 case 576000:
886 sp = B576000;
887 break;
888 case 921600:
889 sp = B921600;
890 break;
891 case 1000000:
892 sp = B1000000;
893 break;
894 case 1152000:
895 sp = B1152000;
896 break;
897 case 1500000:
898 sp = B1500000;
899 break;
900 case 2000000:
901 sp = B2000000;
902 break;
903 case 2500000:
904 sp = B2500000;
905 break;
906 case 3000000:
907 sp = B3000000;
908 break;
909 case 3500000:
910 sp = B3500000;
911 break;
912 case 4000000:
913 sp = B4000000;
914 break;
915 default:
916 p->c_cflag |= BOTHER;
917 sp = baudrate;
918 break;
919 }
920
921 p->c_ispeed = p->c_ospeed = sp;
922 }
923
924 return 0;
925 }
926
uart_tcdrain(int fd)927 static int uart_tcdrain(int fd)
928 {
929 if (fd < 0 || fd >= UART_NUM) {
930 errno = EBADF;
931 return -1;
932 }
933
934 if (uart_wait_tx_done(fd, portMAX_DELAY) != ESP_OK) {
935 errno = EINVAL;
936 return -1;
937 }
938
939 return 0;
940 }
941
uart_tcflush(int fd,int select)942 static int uart_tcflush(int fd, int select)
943 {
944 if (fd < 0 || fd >= UART_NUM) {
945 errno = EBADF;
946 return -1;
947 }
948
949 if (select == TCIFLUSH) {
950 if (uart_flush_input(fd) != ESP_OK) {
951 errno = EINVAL;
952 return -1;
953 }
954 } else {
955 // output flushing is not supported
956 errno = EINVAL;
957 return -1;
958 }
959
960 return 0;
961 }
962 #endif // CONFIG_VFS_SUPPORT_TERMIOS
963
964 static const esp_vfs_t vfs = {
965 .flags = ESP_VFS_FLAG_DEFAULT,
966 .write = &uart_write,
967 .open = &uart_open,
968 .fstat = &uart_fstat,
969 .close = &uart_close,
970 .read = &uart_read,
971 .fcntl = &uart_fcntl,
972 .fsync = &uart_fsync,
973 #ifdef CONFIG_VFS_SUPPORT_DIR
974 .access = &uart_access,
975 #endif // CONFIG_VFS_SUPPORT_DIR
976 #ifdef CONFIG_VFS_SUPPORT_SELECT
977 .start_select = &uart_start_select,
978 .end_select = &uart_end_select,
979 #endif // CONFIG_VFS_SUPPORT_SELECT
980 #ifdef CONFIG_VFS_SUPPORT_TERMIOS
981 .tcsetattr = &uart_tcsetattr,
982 .tcgetattr = &uart_tcgetattr,
983 .tcdrain = &uart_tcdrain,
984 .tcflush = &uart_tcflush,
985 #endif // CONFIG_VFS_SUPPORT_TERMIOS
986 };
987
esp_vfs_uart_get_vfs(void)988 const esp_vfs_t* esp_vfs_uart_get_vfs(void)
989 {
990 return &vfs;
991 }
992
esp_vfs_dev_uart_register(void)993 void esp_vfs_dev_uart_register(void)
994 {
995 ESP_ERROR_CHECK(esp_vfs_register("/dev/uart", &vfs, NULL));
996 }
997
esp_vfs_dev_uart_port_set_rx_line_endings(int uart_num,esp_line_endings_t mode)998 int esp_vfs_dev_uart_port_set_rx_line_endings(int uart_num, esp_line_endings_t mode)
999 {
1000 if (uart_num < 0 || uart_num >= UART_NUM) {
1001 errno = EBADF;
1002 return -1;
1003 }
1004 s_ctx[uart_num]->rx_mode = mode;
1005 return 0;
1006 }
1007
esp_vfs_dev_uart_port_set_tx_line_endings(int uart_num,esp_line_endings_t mode)1008 int esp_vfs_dev_uart_port_set_tx_line_endings(int uart_num, esp_line_endings_t mode)
1009 {
1010 if (uart_num < 0 || uart_num >= UART_NUM) {
1011 errno = EBADF;
1012 return -1;
1013 }
1014 s_ctx[uart_num]->tx_mode = mode;
1015 return 0;
1016 }
1017
esp_vfs_dev_uart_set_rx_line_endings(esp_line_endings_t mode)1018 void esp_vfs_dev_uart_set_rx_line_endings(esp_line_endings_t mode)
1019 {
1020 for (int i = 0; i < UART_NUM; ++i) {
1021 s_ctx[i]->rx_mode = mode;
1022 }
1023 }
1024
esp_vfs_dev_uart_set_tx_line_endings(esp_line_endings_t mode)1025 void esp_vfs_dev_uart_set_tx_line_endings(esp_line_endings_t mode)
1026 {
1027 for (int i = 0; i < UART_NUM; ++i) {
1028 s_ctx[i]->tx_mode = mode;
1029 }
1030 }
1031
esp_vfs_dev_uart_use_nonblocking(int uart_num)1032 void esp_vfs_dev_uart_use_nonblocking(int uart_num)
1033 {
1034 _lock_acquire_recursive(&s_ctx[uart_num]->read_lock);
1035 _lock_acquire_recursive(&s_ctx[uart_num]->write_lock);
1036 s_ctx[uart_num]->tx_func = uart_tx_char;
1037 s_ctx[uart_num]->rx_func = uart_rx_char;
1038 _lock_release_recursive(&s_ctx[uart_num]->write_lock);
1039 _lock_release_recursive(&s_ctx[uart_num]->read_lock);
1040 }
1041
esp_vfs_dev_uart_use_driver(int uart_num)1042 void esp_vfs_dev_uart_use_driver(int uart_num)
1043 {
1044 _lock_acquire_recursive(&s_ctx[uart_num]->read_lock);
1045 _lock_acquire_recursive(&s_ctx[uart_num]->write_lock);
1046 s_ctx[uart_num]->tx_func = uart_tx_char_via_driver;
1047 s_ctx[uart_num]->rx_func = uart_rx_char_via_driver;
1048 _lock_release_recursive(&s_ctx[uart_num]->write_lock);
1049 _lock_release_recursive(&s_ctx[uart_num]->read_lock);
1050 }
1051