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