xref: /aosp_15_r20/external/openthread/examples/platforms/simulation/uart.c (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *  Copyright (c) 2016, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *  All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *  Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *  modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *  1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *  2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *     notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *     documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *  3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *     names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *     derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17*cfb92d14SAndroid Build Coastguard Worker  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*cfb92d14SAndroid Build Coastguard Worker  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*cfb92d14SAndroid Build Coastguard Worker  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20*cfb92d14SAndroid Build Coastguard Worker  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*cfb92d14SAndroid Build Coastguard Worker  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*cfb92d14SAndroid Build Coastguard Worker  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*cfb92d14SAndroid Build Coastguard Worker  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*cfb92d14SAndroid Build Coastguard Worker  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*cfb92d14SAndroid Build Coastguard Worker  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*cfb92d14SAndroid Build Coastguard Worker  *  POSSIBILITY OF SUCH DAMAGE.
27*cfb92d14SAndroid Build Coastguard Worker  */
28*cfb92d14SAndroid Build Coastguard Worker 
29*cfb92d14SAndroid Build Coastguard Worker #include "platform-simulation.h"
30*cfb92d14SAndroid Build Coastguard Worker 
31*cfb92d14SAndroid Build Coastguard Worker #include <assert.h>
32*cfb92d14SAndroid Build Coastguard Worker #include <errno.h>
33*cfb92d14SAndroid Build Coastguard Worker #include <fcntl.h>
34*cfb92d14SAndroid Build Coastguard Worker #include <poll.h>
35*cfb92d14SAndroid Build Coastguard Worker #include <signal.h>
36*cfb92d14SAndroid Build Coastguard Worker #include <stdio.h>
37*cfb92d14SAndroid Build Coastguard Worker #include <stdlib.h>
38*cfb92d14SAndroid Build Coastguard Worker #include <termios.h>
39*cfb92d14SAndroid Build Coastguard Worker #include <unistd.h>
40*cfb92d14SAndroid Build Coastguard Worker 
41*cfb92d14SAndroid Build Coastguard Worker #include <openthread/platform/debug_uart.h>
42*cfb92d14SAndroid Build Coastguard Worker 
43*cfb92d14SAndroid Build Coastguard Worker #include "simul_utils.h"
44*cfb92d14SAndroid Build Coastguard Worker #include "utils/code_utils.h"
45*cfb92d14SAndroid Build Coastguard Worker #include "utils/uart.h"
46*cfb92d14SAndroid Build Coastguard Worker 
47*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
48*cfb92d14SAndroid Build Coastguard Worker 
49*cfb92d14SAndroid Build Coastguard Worker static uint8_t        s_receive_buffer[128];
50*cfb92d14SAndroid Build Coastguard Worker static const uint8_t *s_write_buffer;
51*cfb92d14SAndroid Build Coastguard Worker static uint16_t       s_write_length;
52*cfb92d14SAndroid Build Coastguard Worker static int            s_in_fd;
53*cfb92d14SAndroid Build Coastguard Worker static int            s_out_fd;
54*cfb92d14SAndroid Build Coastguard Worker 
55*cfb92d14SAndroid Build Coastguard Worker static struct termios original_stdin_termios;
56*cfb92d14SAndroid Build Coastguard Worker static struct termios original_stdout_termios;
57*cfb92d14SAndroid Build Coastguard Worker 
restore_stdin_termios(void)58*cfb92d14SAndroid Build Coastguard Worker static void restore_stdin_termios(void) { tcsetattr(s_in_fd, TCSAFLUSH, &original_stdin_termios); }
59*cfb92d14SAndroid Build Coastguard Worker 
restore_stdout_termios(void)60*cfb92d14SAndroid Build Coastguard Worker static void restore_stdout_termios(void) { tcsetattr(s_out_fd, TCSAFLUSH, &original_stdout_termios); }
61*cfb92d14SAndroid Build Coastguard Worker 
platformUartRestore(void)62*cfb92d14SAndroid Build Coastguard Worker void platformUartRestore(void)
63*cfb92d14SAndroid Build Coastguard Worker {
64*cfb92d14SAndroid Build Coastguard Worker     restore_stdin_termios();
65*cfb92d14SAndroid Build Coastguard Worker     restore_stdout_termios();
66*cfb92d14SAndroid Build Coastguard Worker     dup2(s_out_fd, STDOUT_FILENO);
67*cfb92d14SAndroid Build Coastguard Worker }
68*cfb92d14SAndroid Build Coastguard Worker 
otPlatUartEnable(void)69*cfb92d14SAndroid Build Coastguard Worker otError otPlatUartEnable(void)
70*cfb92d14SAndroid Build Coastguard Worker {
71*cfb92d14SAndroid Build Coastguard Worker     otError        error = OT_ERROR_NONE;
72*cfb92d14SAndroid Build Coastguard Worker     struct termios termios;
73*cfb92d14SAndroid Build Coastguard Worker 
74*cfb92d14SAndroid Build Coastguard Worker     s_in_fd  = dup(STDIN_FILENO);
75*cfb92d14SAndroid Build Coastguard Worker     s_out_fd = dup(STDOUT_FILENO);
76*cfb92d14SAndroid Build Coastguard Worker     dup2(STDERR_FILENO, STDOUT_FILENO);
77*cfb92d14SAndroid Build Coastguard Worker 
78*cfb92d14SAndroid Build Coastguard Worker     // We need this signal to make sure that this
79*cfb92d14SAndroid Build Coastguard Worker     // process terminates properly.
80*cfb92d14SAndroid Build Coastguard Worker     signal(SIGPIPE, SIG_DFL);
81*cfb92d14SAndroid Build Coastguard Worker 
82*cfb92d14SAndroid Build Coastguard Worker     if (isatty(s_in_fd))
83*cfb92d14SAndroid Build Coastguard Worker     {
84*cfb92d14SAndroid Build Coastguard Worker         tcgetattr(s_in_fd, &original_stdin_termios);
85*cfb92d14SAndroid Build Coastguard Worker         atexit(&restore_stdin_termios);
86*cfb92d14SAndroid Build Coastguard Worker     }
87*cfb92d14SAndroid Build Coastguard Worker 
88*cfb92d14SAndroid Build Coastguard Worker     if (isatty(s_out_fd))
89*cfb92d14SAndroid Build Coastguard Worker     {
90*cfb92d14SAndroid Build Coastguard Worker         tcgetattr(s_out_fd, &original_stdout_termios);
91*cfb92d14SAndroid Build Coastguard Worker         atexit(&restore_stdout_termios);
92*cfb92d14SAndroid Build Coastguard Worker     }
93*cfb92d14SAndroid Build Coastguard Worker 
94*cfb92d14SAndroid Build Coastguard Worker     if (isatty(s_in_fd))
95*cfb92d14SAndroid Build Coastguard Worker     {
96*cfb92d14SAndroid Build Coastguard Worker         // get current configuration
97*cfb92d14SAndroid Build Coastguard Worker         otEXPECT_ACTION(tcgetattr(s_in_fd, &termios) == 0, perror("tcgetattr"); error = OT_ERROR_GENERIC);
98*cfb92d14SAndroid Build Coastguard Worker 
99*cfb92d14SAndroid Build Coastguard Worker         // Set up the termios settings for raw mode. This turns
100*cfb92d14SAndroid Build Coastguard Worker         // off input/output processing, line processing, and character processing.
101*cfb92d14SAndroid Build Coastguard Worker         cfmakeraw(&termios);
102*cfb92d14SAndroid Build Coastguard Worker 
103*cfb92d14SAndroid Build Coastguard Worker         // Set up our cflags for local use. Turn on hangup-on-close.
104*cfb92d14SAndroid Build Coastguard Worker         termios.c_cflag |= HUPCL | CREAD | CLOCAL;
105*cfb92d14SAndroid Build Coastguard Worker 
106*cfb92d14SAndroid Build Coastguard Worker         // "Minimum number of characters for noncanonical read"
107*cfb92d14SAndroid Build Coastguard Worker         termios.c_cc[VMIN] = 1;
108*cfb92d14SAndroid Build Coastguard Worker 
109*cfb92d14SAndroid Build Coastguard Worker         // "Timeout in deciseconds for noncanonical read"
110*cfb92d14SAndroid Build Coastguard Worker         termios.c_cc[VTIME] = 0;
111*cfb92d14SAndroid Build Coastguard Worker 
112*cfb92d14SAndroid Build Coastguard Worker         // configure baud rate
113*cfb92d14SAndroid Build Coastguard Worker         otEXPECT_ACTION(cfsetispeed(&termios, OPENTHREAD_SIMULATION_UART_BAUDRATE) == 0, perror("cfsetispeed");
114*cfb92d14SAndroid Build Coastguard Worker                         error = OT_ERROR_GENERIC);
115*cfb92d14SAndroid Build Coastguard Worker 
116*cfb92d14SAndroid Build Coastguard Worker         // set configuration
117*cfb92d14SAndroid Build Coastguard Worker         otEXPECT_ACTION(tcsetattr(s_in_fd, TCSANOW, &termios) == 0, perror("tcsetattr"); error = OT_ERROR_GENERIC);
118*cfb92d14SAndroid Build Coastguard Worker     }
119*cfb92d14SAndroid Build Coastguard Worker 
120*cfb92d14SAndroid Build Coastguard Worker     if (isatty(s_out_fd))
121*cfb92d14SAndroid Build Coastguard Worker     {
122*cfb92d14SAndroid Build Coastguard Worker         // get current configuration
123*cfb92d14SAndroid Build Coastguard Worker         otEXPECT_ACTION(tcgetattr(s_out_fd, &termios) == 0, perror("tcgetattr"); error = OT_ERROR_GENERIC);
124*cfb92d14SAndroid Build Coastguard Worker 
125*cfb92d14SAndroid Build Coastguard Worker         // Set up the termios settings for raw mode. This turns
126*cfb92d14SAndroid Build Coastguard Worker         // off input/output processing, line processing, and character processing.
127*cfb92d14SAndroid Build Coastguard Worker         cfmakeraw(&termios);
128*cfb92d14SAndroid Build Coastguard Worker 
129*cfb92d14SAndroid Build Coastguard Worker         // Absolutely obliterate all output processing.
130*cfb92d14SAndroid Build Coastguard Worker         termios.c_oflag = 0;
131*cfb92d14SAndroid Build Coastguard Worker 
132*cfb92d14SAndroid Build Coastguard Worker         // Set up our cflags for local use. Turn on hangup-on-close.
133*cfb92d14SAndroid Build Coastguard Worker         termios.c_cflag |= HUPCL | CREAD | CLOCAL;
134*cfb92d14SAndroid Build Coastguard Worker 
135*cfb92d14SAndroid Build Coastguard Worker         // configure baud rate
136*cfb92d14SAndroid Build Coastguard Worker         otEXPECT_ACTION(cfsetospeed(&termios, OPENTHREAD_SIMULATION_UART_BAUDRATE) == 0, perror("cfsetospeed");
137*cfb92d14SAndroid Build Coastguard Worker                         error = OT_ERROR_GENERIC);
138*cfb92d14SAndroid Build Coastguard Worker 
139*cfb92d14SAndroid Build Coastguard Worker         // set configuration
140*cfb92d14SAndroid Build Coastguard Worker         otEXPECT_ACTION(tcsetattr(s_out_fd, TCSANOW, &termios) == 0, perror("tcsetattr"); error = OT_ERROR_GENERIC);
141*cfb92d14SAndroid Build Coastguard Worker     }
142*cfb92d14SAndroid Build Coastguard Worker 
143*cfb92d14SAndroid Build Coastguard Worker     return error;
144*cfb92d14SAndroid Build Coastguard Worker 
145*cfb92d14SAndroid Build Coastguard Worker exit:
146*cfb92d14SAndroid Build Coastguard Worker     close(s_in_fd);
147*cfb92d14SAndroid Build Coastguard Worker     close(s_out_fd);
148*cfb92d14SAndroid Build Coastguard Worker     return error;
149*cfb92d14SAndroid Build Coastguard Worker }
150*cfb92d14SAndroid Build Coastguard Worker 
otPlatUartDisable(void)151*cfb92d14SAndroid Build Coastguard Worker otError otPlatUartDisable(void)
152*cfb92d14SAndroid Build Coastguard Worker {
153*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
154*cfb92d14SAndroid Build Coastguard Worker 
155*cfb92d14SAndroid Build Coastguard Worker     close(s_in_fd);
156*cfb92d14SAndroid Build Coastguard Worker     close(s_out_fd);
157*cfb92d14SAndroid Build Coastguard Worker 
158*cfb92d14SAndroid Build Coastguard Worker     return error;
159*cfb92d14SAndroid Build Coastguard Worker }
160*cfb92d14SAndroid Build Coastguard Worker 
otPlatUartSend(const uint8_t * aBuf,uint16_t aBufLength)161*cfb92d14SAndroid Build Coastguard Worker otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
162*cfb92d14SAndroid Build Coastguard Worker {
163*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
164*cfb92d14SAndroid Build Coastguard Worker 
165*cfb92d14SAndroid Build Coastguard Worker     otEXPECT_ACTION(s_write_length == 0, error = OT_ERROR_BUSY);
166*cfb92d14SAndroid Build Coastguard Worker 
167*cfb92d14SAndroid Build Coastguard Worker     s_write_buffer = aBuf;
168*cfb92d14SAndroid Build Coastguard Worker     s_write_length = aBufLength;
169*cfb92d14SAndroid Build Coastguard Worker 
170*cfb92d14SAndroid Build Coastguard Worker exit:
171*cfb92d14SAndroid Build Coastguard Worker     return error;
172*cfb92d14SAndroid Build Coastguard Worker }
173*cfb92d14SAndroid Build Coastguard Worker 
platformUartUpdateFdSet(fd_set * aReadFdSet,fd_set * aWriteFdSet,fd_set * aErrorFdSet,int * aMaxFd)174*cfb92d14SAndroid Build Coastguard Worker void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd)
175*cfb92d14SAndroid Build Coastguard Worker {
176*cfb92d14SAndroid Build Coastguard Worker     utilsAddFdToFdSet(s_in_fd, aReadFdSet, aMaxFd);
177*cfb92d14SAndroid Build Coastguard Worker     utilsAddFdToFdSet(s_in_fd, aErrorFdSet, aMaxFd);
178*cfb92d14SAndroid Build Coastguard Worker 
179*cfb92d14SAndroid Build Coastguard Worker     if ((s_write_length > 0))
180*cfb92d14SAndroid Build Coastguard Worker     {
181*cfb92d14SAndroid Build Coastguard Worker         utilsAddFdToFdSet(s_out_fd, aWriteFdSet, aMaxFd);
182*cfb92d14SAndroid Build Coastguard Worker         utilsAddFdToFdSet(s_out_fd, aErrorFdSet, aMaxFd);
183*cfb92d14SAndroid Build Coastguard Worker     }
184*cfb92d14SAndroid Build Coastguard Worker }
185*cfb92d14SAndroid Build Coastguard Worker 
otPlatUartFlush(void)186*cfb92d14SAndroid Build Coastguard Worker otError otPlatUartFlush(void)
187*cfb92d14SAndroid Build Coastguard Worker {
188*cfb92d14SAndroid Build Coastguard Worker     otError error = OT_ERROR_NONE;
189*cfb92d14SAndroid Build Coastguard Worker     ssize_t count;
190*cfb92d14SAndroid Build Coastguard Worker 
191*cfb92d14SAndroid Build Coastguard Worker     otEXPECT_ACTION(s_write_buffer != NULL && s_write_length > 0, error = OT_ERROR_INVALID_STATE);
192*cfb92d14SAndroid Build Coastguard Worker 
193*cfb92d14SAndroid Build Coastguard Worker     while ((count = write(s_out_fd, s_write_buffer, s_write_length)) > 0 && (s_write_length -= count) > 0)
194*cfb92d14SAndroid Build Coastguard Worker     {
195*cfb92d14SAndroid Build Coastguard Worker         s_write_buffer += count;
196*cfb92d14SAndroid Build Coastguard Worker     }
197*cfb92d14SAndroid Build Coastguard Worker 
198*cfb92d14SAndroid Build Coastguard Worker     if (count != -1)
199*cfb92d14SAndroid Build Coastguard Worker     {
200*cfb92d14SAndroid Build Coastguard Worker         assert(s_write_length == 0);
201*cfb92d14SAndroid Build Coastguard Worker         s_write_buffer = NULL;
202*cfb92d14SAndroid Build Coastguard Worker     }
203*cfb92d14SAndroid Build Coastguard Worker     else
204*cfb92d14SAndroid Build Coastguard Worker     {
205*cfb92d14SAndroid Build Coastguard Worker         perror("write(UART)");
206*cfb92d14SAndroid Build Coastguard Worker         exit(EXIT_FAILURE);
207*cfb92d14SAndroid Build Coastguard Worker     }
208*cfb92d14SAndroid Build Coastguard Worker 
209*cfb92d14SAndroid Build Coastguard Worker exit:
210*cfb92d14SAndroid Build Coastguard Worker     return error;
211*cfb92d14SAndroid Build Coastguard Worker }
212*cfb92d14SAndroid Build Coastguard Worker 
platformUartProcess(void)213*cfb92d14SAndroid Build Coastguard Worker void platformUartProcess(void)
214*cfb92d14SAndroid Build Coastguard Worker {
215*cfb92d14SAndroid Build Coastguard Worker     ssize_t       rval;
216*cfb92d14SAndroid Build Coastguard Worker     const int     error_flags = POLLERR | POLLNVAL | POLLHUP;
217*cfb92d14SAndroid Build Coastguard Worker     struct pollfd pollfd[]    = {
218*cfb92d14SAndroid Build Coastguard Worker            {s_in_fd, POLLIN | error_flags, 0},
219*cfb92d14SAndroid Build Coastguard Worker            {s_out_fd, POLLOUT | error_flags, 0},
220*cfb92d14SAndroid Build Coastguard Worker     };
221*cfb92d14SAndroid Build Coastguard Worker 
222*cfb92d14SAndroid Build Coastguard Worker     errno = 0;
223*cfb92d14SAndroid Build Coastguard Worker 
224*cfb92d14SAndroid Build Coastguard Worker     rval = poll(pollfd, sizeof(pollfd) / sizeof(*pollfd), 0);
225*cfb92d14SAndroid Build Coastguard Worker 
226*cfb92d14SAndroid Build Coastguard Worker     if (rval < 0)
227*cfb92d14SAndroid Build Coastguard Worker     {
228*cfb92d14SAndroid Build Coastguard Worker         perror("poll");
229*cfb92d14SAndroid Build Coastguard Worker         exit(EXIT_FAILURE);
230*cfb92d14SAndroid Build Coastguard Worker     }
231*cfb92d14SAndroid Build Coastguard Worker 
232*cfb92d14SAndroid Build Coastguard Worker     if (rval > 0)
233*cfb92d14SAndroid Build Coastguard Worker     {
234*cfb92d14SAndroid Build Coastguard Worker         if ((pollfd[0].revents & error_flags) != 0)
235*cfb92d14SAndroid Build Coastguard Worker         {
236*cfb92d14SAndroid Build Coastguard Worker             perror("s_in_fd");
237*cfb92d14SAndroid Build Coastguard Worker             exit(EXIT_FAILURE);
238*cfb92d14SAndroid Build Coastguard Worker         }
239*cfb92d14SAndroid Build Coastguard Worker 
240*cfb92d14SAndroid Build Coastguard Worker         if ((pollfd[1].revents & error_flags) != 0)
241*cfb92d14SAndroid Build Coastguard Worker         {
242*cfb92d14SAndroid Build Coastguard Worker             perror("s_out_fd");
243*cfb92d14SAndroid Build Coastguard Worker             exit(EXIT_FAILURE);
244*cfb92d14SAndroid Build Coastguard Worker         }
245*cfb92d14SAndroid Build Coastguard Worker 
246*cfb92d14SAndroid Build Coastguard Worker         if (pollfd[0].revents & POLLIN)
247*cfb92d14SAndroid Build Coastguard Worker         {
248*cfb92d14SAndroid Build Coastguard Worker             rval = read(s_in_fd, s_receive_buffer, sizeof(s_receive_buffer));
249*cfb92d14SAndroid Build Coastguard Worker 
250*cfb92d14SAndroid Build Coastguard Worker             if (rval <= 0)
251*cfb92d14SAndroid Build Coastguard Worker             {
252*cfb92d14SAndroid Build Coastguard Worker                 perror("read");
253*cfb92d14SAndroid Build Coastguard Worker                 exit(EXIT_FAILURE);
254*cfb92d14SAndroid Build Coastguard Worker             }
255*cfb92d14SAndroid Build Coastguard Worker 
256*cfb92d14SAndroid Build Coastguard Worker             otPlatUartReceived(s_receive_buffer, (uint16_t)rval);
257*cfb92d14SAndroid Build Coastguard Worker         }
258*cfb92d14SAndroid Build Coastguard Worker 
259*cfb92d14SAndroid Build Coastguard Worker         if ((s_write_length > 0) && (pollfd[1].revents & POLLOUT))
260*cfb92d14SAndroid Build Coastguard Worker         {
261*cfb92d14SAndroid Build Coastguard Worker             rval = write(s_out_fd, s_write_buffer, s_write_length);
262*cfb92d14SAndroid Build Coastguard Worker 
263*cfb92d14SAndroid Build Coastguard Worker             if (rval >= 0)
264*cfb92d14SAndroid Build Coastguard Worker             {
265*cfb92d14SAndroid Build Coastguard Worker                 s_write_buffer += (uint16_t)rval;
266*cfb92d14SAndroid Build Coastguard Worker                 s_write_length -= (uint16_t)rval;
267*cfb92d14SAndroid Build Coastguard Worker 
268*cfb92d14SAndroid Build Coastguard Worker                 if (s_write_length == 0)
269*cfb92d14SAndroid Build Coastguard Worker                 {
270*cfb92d14SAndroid Build Coastguard Worker                     otPlatUartSendDone();
271*cfb92d14SAndroid Build Coastguard Worker                 }
272*cfb92d14SAndroid Build Coastguard Worker             }
273*cfb92d14SAndroid Build Coastguard Worker             else if (errno != EINTR)
274*cfb92d14SAndroid Build Coastguard Worker             {
275*cfb92d14SAndroid Build Coastguard Worker                 perror("write");
276*cfb92d14SAndroid Build Coastguard Worker                 exit(EXIT_FAILURE);
277*cfb92d14SAndroid Build Coastguard Worker             }
278*cfb92d14SAndroid Build Coastguard Worker         }
279*cfb92d14SAndroid Build Coastguard Worker     }
280*cfb92d14SAndroid Build Coastguard Worker }
281*cfb92d14SAndroid Build Coastguard Worker #endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
282*cfb92d14SAndroid Build Coastguard Worker 
283*cfb92d14SAndroid Build Coastguard Worker #if OPENTHREAD_CONFIG_ENABLE_DEBUG_UART && (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART)
284*cfb92d14SAndroid Build Coastguard Worker 
285*cfb92d14SAndroid Build Coastguard Worker static FILE *posix_logfile;
286*cfb92d14SAndroid Build Coastguard Worker 
otPlatDebugUart_logfile(const char * filename)287*cfb92d14SAndroid Build Coastguard Worker otError otPlatDebugUart_logfile(const char *filename)
288*cfb92d14SAndroid Build Coastguard Worker {
289*cfb92d14SAndroid Build Coastguard Worker     posix_logfile = fopen(filename, "wt");
290*cfb92d14SAndroid Build Coastguard Worker 
291*cfb92d14SAndroid Build Coastguard Worker     return posix_logfile ? OT_ERROR_NONE : OT_ERROR_FAILED;
292*cfb92d14SAndroid Build Coastguard Worker }
293*cfb92d14SAndroid Build Coastguard Worker 
otPlatDebugUart_putchar_raw(int c)294*cfb92d14SAndroid Build Coastguard Worker void otPlatDebugUart_putchar_raw(int c)
295*cfb92d14SAndroid Build Coastguard Worker {
296*cfb92d14SAndroid Build Coastguard Worker     FILE *fp;
297*cfb92d14SAndroid Build Coastguard Worker 
298*cfb92d14SAndroid Build Coastguard Worker     /* note: log file will have a mix of cr/lf and
299*cfb92d14SAndroid Build Coastguard Worker      * in some/many cases duplicate cr because in
300*cfb92d14SAndroid Build Coastguard Worker      * some cases the log function {ie: Mbed} already
301*cfb92d14SAndroid Build Coastguard Worker      * includes the CR or LF... but other log functions
302*cfb92d14SAndroid Build Coastguard Worker      * do not include cr/lf and expect it appended
303*cfb92d14SAndroid Build Coastguard Worker      */
304*cfb92d14SAndroid Build Coastguard Worker     fp = posix_logfile;
305*cfb92d14SAndroid Build Coastguard Worker 
306*cfb92d14SAndroid Build Coastguard Worker     if (fp != NULL)
307*cfb92d14SAndroid Build Coastguard Worker     {
308*cfb92d14SAndroid Build Coastguard Worker         /* log is lost ... until a file is setup */
309*cfb92d14SAndroid Build Coastguard Worker         fputc(c, fp);
310*cfb92d14SAndroid Build Coastguard Worker         /* we could "fflush" but will not */
311*cfb92d14SAndroid Build Coastguard Worker     }
312*cfb92d14SAndroid Build Coastguard Worker }
313*cfb92d14SAndroid Build Coastguard Worker 
otPlatDebugUart_kbhit(void)314*cfb92d14SAndroid Build Coastguard Worker int otPlatDebugUart_kbhit(void)
315*cfb92d14SAndroid Build Coastguard Worker {
316*cfb92d14SAndroid Build Coastguard Worker     /* not supported */
317*cfb92d14SAndroid Build Coastguard Worker     return 0;
318*cfb92d14SAndroid Build Coastguard Worker }
319*cfb92d14SAndroid Build Coastguard Worker 
otPlatDebugUart_getc(void)320*cfb92d14SAndroid Build Coastguard Worker int otPlatDebugUart_getc(void)
321*cfb92d14SAndroid Build Coastguard Worker {
322*cfb92d14SAndroid Build Coastguard Worker     /* not supported */
323*cfb92d14SAndroid Build Coastguard Worker     return -1;
324*cfb92d14SAndroid Build Coastguard Worker }
325*cfb92d14SAndroid Build Coastguard Worker 
326*cfb92d14SAndroid Build Coastguard Worker #endif
327