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