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