1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdio.h>
8 #include "hardware/uart.h"
9 
10 #if defined(__unix) || defined(__APPLE__)
11 #define _XOPEN_SOURCE 600 /* for ONLCR */
12 #define __BSD_VISIBLE 1 /* for ONLCR in *BSD */
13 
14 #include <unistd.h>
15 #include <termios.h>
16 #include <fcntl.h>
17 #include <stdlib.h>
18 
19 #ifndef FNONBLOCK
20 #define FNONBLOCK O_NONBLOCK
21 #endif
22 
23 struct termios _tty;
24 static tcflag_t _res_oflg = 0;
25 static tcflag_t _res_lflg = 0;
26 
_resettty(void)27 void _resettty(void) {
28     if (!isatty(STDIN_FILENO))
29         return;
30 
31     /* reset tty: */
32     _tty.c_oflag = _res_oflg;
33     _tty.c_lflag = _res_lflg;
34     tcsetattr(STDIN_FILENO, TCSADRAIN, &_tty);
35 }
36 
_inittty(void)37 void _inittty(void) {
38     if (!isatty(STDIN_FILENO))
39         return;
40 
41     /* save tty: */
42     tcgetattr(STDIN_FILENO, &_tty);
43     _res_oflg = _tty.c_oflag;
44     _res_lflg = _tty.c_lflag;
45 
46     /* set raw: */
47     _tty.c_lflag &= ~(ICANON | ICRNL);// | ISIG);
48     //_tty.c_oflag &= ~ONLCR;
49     tcsetattr(STDIN_FILENO, TCSANOW, &_tty);
50 
51     fcntl(STDIN_FILENO, F_SETFL, FNONBLOCK);
52     atexit(_resettty);
53 }
54 
55 #else
_inittty()56 void _inittty() {}
57 #endif
58 
59 typedef struct {
60     bool dummy;
61 } uart_hw_t;
62 
63 uart_inst_t *const uart0;
64 uart_inst_t *const uart1;
65 
66 static int _nextchar = EOF;
67 
_peekchar()68 static bool _peekchar() {
69     if (_nextchar == EOF) {
70         _nextchar = getchar();
71     }
72     return _nextchar != EOF;
73 }
74 
uart_init(uart_inst_t * uart,uint baud_rate)75 uint uart_init(uart_inst_t *uart, uint baud_rate) {
76     _inittty();
77     return baud_rate;
78 }
79 
uart_is_writable(uart_inst_t * uart)80 bool uart_is_writable(uart_inst_t *uart) {
81     return 1;
82 }
83 
84 // If returns 0, no data is available to be read from UART.
85 // If returns nonzero, at least that many bytes can be written without blocking.
uart_is_readable(uart_inst_t * uart)86 bool uart_is_readable(uart_inst_t *uart) {
87     return _peekchar() ? 1 : 0;
88 }
89 
90 // Write len bytes directly from src to the UART
uart_write_blocking(uart_inst_t * uart,const uint8_t * src,size_t len)91 void uart_write_blocking(uart_inst_t *uart, const uint8_t *src, size_t len) {
92     for (size_t i = 0; i < len; i++) {
93         uart_putc(uart, src[i]);
94     }
95 }
96 
97 // Read len bytes directly from the UART to dst
uart_read_blocking(uart_inst_t * uart,uint8_t * dst,size_t len)98 void uart_read_blocking(uart_inst_t *uart, uint8_t *dst, size_t len) {
99     for (size_t i = 0; i < len; i++) {
100         dst[i] = uart_getc(uart);
101     }
102 }
103 
104 // ----------------------------------------------------------------------------
105 // UART-specific operations and aliases
106 
uart_putc(uart_inst_t * uart,char c)107 void uart_putc(uart_inst_t *uart, char c) {
108     putchar(c);
109 }
110 
uart_putc_raw(uart_inst_t * uart,char c)111 void uart_putc_raw(uart_inst_t *uart, char c) {
112     putchar(c);
113 }
114 
uart_puts(uart_inst_t * uart,const char * s)115 void uart_puts(uart_inst_t *uart, const char *s) {
116     puts(s);
117 }
118 
uart_getc(uart_inst_t * uart)119 char uart_getc(uart_inst_t *uart) {
120     while (!_peekchar()) {
121         tight_loop_contents();
122     }
123     char rc = (char) _nextchar;
124     _nextchar = EOF;
125     return rc;
126 }
127 
uart_default_tx_wait_blocking()128 void uart_default_tx_wait_blocking() {
129 
130 }
131