xref: /btstack/platform/posix/btstack_uart_posix.c (revision efc1df55758f287e8647ae160314c93def22eb07)
1f2cb8f20SMatthias Ringwald /*
2f2cb8f20SMatthias Ringwald  * Copyright (C) 2016 BlueKitchen GmbH
3f2cb8f20SMatthias Ringwald  *
4f2cb8f20SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5f2cb8f20SMatthias Ringwald  * modification, are permitted provided that the following conditions
6f2cb8f20SMatthias Ringwald  * are met:
7f2cb8f20SMatthias Ringwald  *
8f2cb8f20SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9f2cb8f20SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10f2cb8f20SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11f2cb8f20SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12f2cb8f20SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13f2cb8f20SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14f2cb8f20SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15f2cb8f20SMatthias Ringwald  *    from this software without specific prior written permission.
16f2cb8f20SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17f2cb8f20SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18f2cb8f20SMatthias Ringwald  *    monetary gain.
19f2cb8f20SMatthias Ringwald  *
20f2cb8f20SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21f2cb8f20SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22f2cb8f20SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25f2cb8f20SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26f2cb8f20SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27f2cb8f20SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28f2cb8f20SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29f2cb8f20SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30f2cb8f20SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31f2cb8f20SMatthias Ringwald  * SUCH DAMAGE.
32f2cb8f20SMatthias Ringwald  *
33f2cb8f20SMatthias Ringwald  * Please inquire about commercial licensing options at
34f2cb8f20SMatthias Ringwald  * [email protected]
35f2cb8f20SMatthias Ringwald  *
36f2cb8f20SMatthias Ringwald  */
37f2cb8f20SMatthias Ringwald 
38f2cb8f20SMatthias Ringwald #define BTSTACK_FILE__ "btstack_uart_posix.c"
39f2cb8f20SMatthias Ringwald 
40f2cb8f20SMatthias Ringwald /*
41f2cb8f20SMatthias Ringwald  *  btstack_uart_posix.c
42f2cb8f20SMatthias Ringwald  *
43f2cb8f20SMatthias Ringwald  *  Common code to access serial port via asynchronous block read/write commands
44f2cb8f20SMatthias Ringwald  *
45f2cb8f20SMatthias Ringwald  */
46f2cb8f20SMatthias Ringwald 
47f2cb8f20SMatthias Ringwald #include "btstack_uart.h"
48f2cb8f20SMatthias Ringwald #include "btstack_run_loop.h"
49f2cb8f20SMatthias Ringwald #include "btstack_debug.h"
50f2cb8f20SMatthias Ringwald 
51f2cb8f20SMatthias Ringwald #include <termios.h>  /* POSIX terminal control definitions */
52f2cb8f20SMatthias Ringwald #include <fcntl.h>    /* File control definitions */
53f2cb8f20SMatthias Ringwald #include <unistd.h>   /* UNIX standard function definitions */
54f2cb8f20SMatthias Ringwald #include <string.h>
55f2cb8f20SMatthias Ringwald #include <errno.h>
56f2cb8f20SMatthias Ringwald #ifdef __APPLE__
57f2cb8f20SMatthias Ringwald #include <sys/ioctl.h>
58f2cb8f20SMatthias Ringwald #include <IOKit/serial/ioss.h>
59f2cb8f20SMatthias Ringwald #endif
60f2cb8f20SMatthias Ringwald 
61f2cb8f20SMatthias Ringwald // uart config
62f2cb8f20SMatthias Ringwald static const btstack_uart_config_t * uart_config;
63f2cb8f20SMatthias Ringwald 
644437baf6SMatthias Ringwald // on macOS 12.1, CTS/RTS control flags are always read back as zero.
654437baf6SMatthias Ringwald // To work around this, we cache our terios settings
664437baf6SMatthias Ringwald struct termios btstack_uart_block_termios;
674437baf6SMatthias Ringwald 
68f2cb8f20SMatthias Ringwald // data source for integration with BTstack Runloop
69f2cb8f20SMatthias Ringwald static btstack_data_source_t transport_data_source;
70f2cb8f20SMatthias Ringwald 
71f2cb8f20SMatthias Ringwald // block write
72f2cb8f20SMatthias Ringwald static int             btstack_uart_block_write_bytes_len;
73f2cb8f20SMatthias Ringwald static const uint8_t * btstack_uart_block_write_bytes_data;
74f2cb8f20SMatthias Ringwald 
75f2cb8f20SMatthias Ringwald // block read
76f2cb8f20SMatthias Ringwald static uint16_t  btstack_uart_block_read_bytes_len;
77f2cb8f20SMatthias Ringwald static uint8_t * btstack_uart_block_read_bytes_data;
78f2cb8f20SMatthias Ringwald 
79f2cb8f20SMatthias Ringwald // callbacks
80f2cb8f20SMatthias Ringwald static void (*block_sent)(void);
81f2cb8f20SMatthias Ringwald static void (*block_received)(void);
82f2cb8f20SMatthias Ringwald 
83f2cb8f20SMatthias Ringwald 
84f2cb8f20SMatthias Ringwald static int btstack_uart_posix_init(const btstack_uart_config_t * config){
85f2cb8f20SMatthias Ringwald     uart_config = config;
86f2cb8f20SMatthias Ringwald     return 0;
87f2cb8f20SMatthias Ringwald }
88f2cb8f20SMatthias Ringwald 
89f2cb8f20SMatthias Ringwald static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type);
90f2cb8f20SMatthias Ringwald 
91f2cb8f20SMatthias Ringwald static void btstack_uart_block_posix_process_write(btstack_data_source_t *ds) {
92f2cb8f20SMatthias Ringwald 
93f2cb8f20SMatthias Ringwald     if (btstack_uart_block_write_bytes_len == 0) return;
94f2cb8f20SMatthias Ringwald 
95f2cb8f20SMatthias Ringwald     uint32_t start = btstack_run_loop_get_time_ms();
96f2cb8f20SMatthias Ringwald 
97f2cb8f20SMatthias Ringwald     // write up to write_bytes_len to fd
98f2cb8f20SMatthias Ringwald     int bytes_written = (int) write(ds->source.fd, btstack_uart_block_write_bytes_data, btstack_uart_block_write_bytes_len);
99f2cb8f20SMatthias Ringwald     uint32_t end = btstack_run_loop_get_time_ms();
100f2cb8f20SMatthias Ringwald     if (end - start > 10){
101f2cb8f20SMatthias Ringwald         log_info("write took %u ms", end - start);
102f2cb8f20SMatthias Ringwald     }
103f2cb8f20SMatthias Ringwald     if (bytes_written == 0){
104f2cb8f20SMatthias Ringwald         log_error("wrote zero bytes\n");
105f2cb8f20SMatthias Ringwald         return;
106f2cb8f20SMatthias Ringwald     }
107f2cb8f20SMatthias Ringwald     if (bytes_written < 0) {
108f2cb8f20SMatthias Ringwald         log_error("write returned error\n");
109f2cb8f20SMatthias Ringwald         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
110f2cb8f20SMatthias Ringwald         return;
111f2cb8f20SMatthias Ringwald     }
112f2cb8f20SMatthias Ringwald 
113f2cb8f20SMatthias Ringwald     btstack_uart_block_write_bytes_data += bytes_written;
114f2cb8f20SMatthias Ringwald     btstack_uart_block_write_bytes_len  -= bytes_written;
115f2cb8f20SMatthias Ringwald 
116f2cb8f20SMatthias Ringwald     if (btstack_uart_block_write_bytes_len){
117f2cb8f20SMatthias Ringwald         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
118f2cb8f20SMatthias Ringwald         return;
119f2cb8f20SMatthias Ringwald     }
120f2cb8f20SMatthias Ringwald 
121f2cb8f20SMatthias Ringwald     btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
122f2cb8f20SMatthias Ringwald 
123f2cb8f20SMatthias Ringwald     // notify done
124f2cb8f20SMatthias Ringwald     if (block_sent){
125f2cb8f20SMatthias Ringwald         block_sent();
126f2cb8f20SMatthias Ringwald     }
127f2cb8f20SMatthias Ringwald }
128f2cb8f20SMatthias Ringwald 
129f2cb8f20SMatthias Ringwald static void btstack_uart_block_posix_process_read(btstack_data_source_t *ds) {
130f2cb8f20SMatthias Ringwald 
131f2cb8f20SMatthias Ringwald     if (btstack_uart_block_read_bytes_len == 0) {
132f2cb8f20SMatthias Ringwald         log_info("called but no read pending");
133f2cb8f20SMatthias Ringwald         btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
134f2cb8f20SMatthias Ringwald     }
135f2cb8f20SMatthias Ringwald 
136f2cb8f20SMatthias Ringwald     uint32_t start = btstack_run_loop_get_time_ms();
137f2cb8f20SMatthias Ringwald 
138f2cb8f20SMatthias Ringwald     // read up to bytes_to_read data in
139f2cb8f20SMatthias Ringwald     ssize_t bytes_read = read(ds->source.fd, btstack_uart_block_read_bytes_data, btstack_uart_block_read_bytes_len);
140f2cb8f20SMatthias Ringwald     // log_info("read need %u bytes, got %d", btstack_uart_block_read_bytes_len, (int) bytes_read);
141f2cb8f20SMatthias Ringwald     uint32_t end = btstack_run_loop_get_time_ms();
142f2cb8f20SMatthias Ringwald     if (end - start > 10){
143f2cb8f20SMatthias Ringwald         log_info("read took %u ms", end - start);
144f2cb8f20SMatthias Ringwald     }
145f2cb8f20SMatthias Ringwald     if (bytes_read == 0){
146f2cb8f20SMatthias Ringwald         log_error("read zero bytes\n");
147f2cb8f20SMatthias Ringwald         return;
148f2cb8f20SMatthias Ringwald     }
149f2cb8f20SMatthias Ringwald     if (bytes_read < 0) {
150f2cb8f20SMatthias Ringwald         log_error("read returned error\n");
151f2cb8f20SMatthias Ringwald         return;
152f2cb8f20SMatthias Ringwald     }
153f2cb8f20SMatthias Ringwald 
154f2cb8f20SMatthias Ringwald     btstack_uart_block_read_bytes_len   -= bytes_read;
155f2cb8f20SMatthias Ringwald     btstack_uart_block_read_bytes_data  += bytes_read;
156f2cb8f20SMatthias Ringwald     if (btstack_uart_block_read_bytes_len > 0) return;
157f2cb8f20SMatthias Ringwald 
158f2cb8f20SMatthias Ringwald     btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
159f2cb8f20SMatthias Ringwald 
160f2cb8f20SMatthias Ringwald     if (block_received){
161f2cb8f20SMatthias Ringwald         block_received();
162f2cb8f20SMatthias Ringwald     }
163f2cb8f20SMatthias Ringwald }
164f2cb8f20SMatthias Ringwald 
165f2cb8f20SMatthias Ringwald static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
166f2cb8f20SMatthias Ringwald 
167f2cb8f20SMatthias Ringwald     int fd = transport_data_source.source.fd;
168f2cb8f20SMatthias Ringwald 
169f2cb8f20SMatthias Ringwald     log_info("h4_set_baudrate %u", baudrate);
170f2cb8f20SMatthias Ringwald 
171f2cb8f20SMatthias Ringwald #ifndef __APPLE__
172f2cb8f20SMatthias Ringwald 
173f2cb8f20SMatthias Ringwald     speed_t brate = baudrate; // let you override switch below if needed
174f2cb8f20SMatthias Ringwald     switch(baudrate) {
175f2cb8f20SMatthias Ringwald         case    9600: brate=B9600;    break;
176f2cb8f20SMatthias Ringwald         case   19200: brate=B19200;   break;
177f2cb8f20SMatthias Ringwald         case   38400: brate=B38400;   break;
178f2cb8f20SMatthias Ringwald         case 57600:  brate=B57600;  break;
179f2cb8f20SMatthias Ringwald         case 115200: brate=B115200; break;
180f2cb8f20SMatthias Ringwald #ifdef B230400
181f2cb8f20SMatthias Ringwald         case 230400: brate=B230400; break;
182f2cb8f20SMatthias Ringwald #endif
183f2cb8f20SMatthias Ringwald #ifdef B460800
184f2cb8f20SMatthias Ringwald         case 460800: brate=B460800; break;
185f2cb8f20SMatthias Ringwald #endif
186f2cb8f20SMatthias Ringwald #ifdef B500000
187f2cb8f20SMatthias Ringwald         case  500000: brate=B500000;  break;
188f2cb8f20SMatthias Ringwald #endif
189f2cb8f20SMatthias Ringwald #ifdef B576000
190f2cb8f20SMatthias Ringwald         case  576000: brate=B576000;  break;
191f2cb8f20SMatthias Ringwald #endif
192f2cb8f20SMatthias Ringwald #ifdef B921600
193f2cb8f20SMatthias Ringwald         case 921600: brate=B921600; break;
194f2cb8f20SMatthias Ringwald #endif
195f2cb8f20SMatthias Ringwald #ifdef B1000000
196f2cb8f20SMatthias Ringwald         case 1000000: brate=B1000000; break;
197f2cb8f20SMatthias Ringwald #endif
198f2cb8f20SMatthias Ringwald #ifdef B1152000
199f2cb8f20SMatthias Ringwald         case 1152000: brate=B1152000; break;
200f2cb8f20SMatthias Ringwald #endif
201f2cb8f20SMatthias Ringwald #ifdef B1500000
202f2cb8f20SMatthias Ringwald         case 1500000: brate=B1500000; break;
203f2cb8f20SMatthias Ringwald #endif
204f2cb8f20SMatthias Ringwald #ifdef B2000000
205f2cb8f20SMatthias Ringwald         case 2000000: brate=B2000000; break;
206f2cb8f20SMatthias Ringwald #endif
207f2cb8f20SMatthias Ringwald #ifdef B2500000
208f2cb8f20SMatthias Ringwald         case 2500000: brate=B2500000; break;
209f2cb8f20SMatthias Ringwald #endif
210f2cb8f20SMatthias Ringwald #ifdef B3000000
211f2cb8f20SMatthias Ringwald         case 3000000: brate=B3000000; break;
212f2cb8f20SMatthias Ringwald #endif
213f2cb8f20SMatthias Ringwald #ifdef B3500000
214f2cb8f20SMatthias Ringwald         case 3500000: brate=B3500000; break;
215f2cb8f20SMatthias Ringwald #endif
216f2cb8f20SMatthias Ringwald #ifdef B400000
217f2cb8f20SMatthias Ringwald         case 4000000: brate=B4000000; break;
218f2cb8f20SMatthias Ringwald #endif
219f2cb8f20SMatthias Ringwald         default:
220f2cb8f20SMatthias Ringwald             log_error("can't set baudrate %dn", baudrate );
221f2cb8f20SMatthias Ringwald             return -1;
222f2cb8f20SMatthias Ringwald     }
2234437baf6SMatthias Ringwald     cfsetospeed(&btstack_uart_block_termios, brate);
2244437baf6SMatthias Ringwald     cfsetispeed(&btstack_uart_block_termios, brate);
225f2cb8f20SMatthias Ringwald #endif
226f2cb8f20SMatthias Ringwald 
227f2cb8f20SMatthias Ringwald     // also set options for __APPLE__ to enforce write drain
228f2cb8f20SMatthias Ringwald     // Mac OS Mojave: tcsdrain did not work as expected
229f2cb8f20SMatthias Ringwald 
2304437baf6SMatthias Ringwald     if( tcsetattr(fd, TCSADRAIN, &btstack_uart_block_termios) < 0) {
231f2cb8f20SMatthias Ringwald         log_error("Couldn't set term attributes");
232f2cb8f20SMatthias Ringwald         return -1;
233f2cb8f20SMatthias Ringwald     }
234f2cb8f20SMatthias Ringwald 
235f2cb8f20SMatthias Ringwald #ifdef __APPLE__
236f2cb8f20SMatthias Ringwald     // From https://developer.apple.com/library/content/samplecode/SerialPortSample/Listings/SerialPortSample_SerialPortSample_c.html
237f2cb8f20SMatthias Ringwald 
238f2cb8f20SMatthias Ringwald     // The IOSSIOSPEED ioctl can be used to set arbitrary baud rates
239f2cb8f20SMatthias Ringwald     // other than those specified by POSIX. The driver for the underlying serial hardware
240f2cb8f20SMatthias Ringwald     // ultimately determines which baud rates can be used. This ioctl sets both the input
241f2cb8f20SMatthias Ringwald     // and output speed.
242f2cb8f20SMatthias Ringwald 
243f2cb8f20SMatthias Ringwald     speed_t speed = baudrate;
244f2cb8f20SMatthias Ringwald     if (ioctl(fd, IOSSIOSPEED, &speed) == -1) {
245f2cb8f20SMatthias Ringwald         log_error("btstack_uart_posix_set_baudrate: error calling ioctl(..., IOSSIOSPEED, %u) - %s(%d).\n", baudrate, strerror(errno), errno);
246f2cb8f20SMatthias Ringwald         return -1;
247f2cb8f20SMatthias Ringwald     }
248f2cb8f20SMatthias Ringwald #endif
249f2cb8f20SMatthias Ringwald 
250f2cb8f20SMatthias Ringwald     return 0;
251f2cb8f20SMatthias Ringwald }
252f2cb8f20SMatthias Ringwald 
253f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_parity_option(struct termios * toptions, int parity){
254f2cb8f20SMatthias Ringwald     switch (parity){
255f2cb8f20SMatthias Ringwald         case BTSTACK_UART_PARITY_OFF:
256f2cb8f20SMatthias Ringwald             toptions->c_cflag &= ~PARENB;
257f2cb8f20SMatthias Ringwald             toptions->c_cflag &= ~PARODD;
258f2cb8f20SMatthias Ringwald             break;
259f2cb8f20SMatthias Ringwald         case BTSTACK_UART_PARITY_EVEN:
260f2cb8f20SMatthias Ringwald             toptions->c_cflag |=  PARENB;
261f2cb8f20SMatthias Ringwald             toptions->c_cflag &= ~PARODD;
262f2cb8f20SMatthias Ringwald             break;
263f2cb8f20SMatthias Ringwald         case BTSTACK_UART_PARITY_ODD:
264f2cb8f20SMatthias Ringwald             toptions->c_cflag |= PARENB;
265f2cb8f20SMatthias Ringwald             toptions->c_cflag |= PARODD;
266f2cb8f20SMatthias Ringwald         default:
267f2cb8f20SMatthias Ringwald             break;
268f2cb8f20SMatthias Ringwald     }
269f2cb8f20SMatthias Ringwald }
270f2cb8f20SMatthias Ringwald 
271f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_flowcontrol_option(struct termios * toptions, int flowcontrol){
272f2cb8f20SMatthias Ringwald     if (flowcontrol) {
273f2cb8f20SMatthias Ringwald         // with flow control
274f2cb8f20SMatthias Ringwald         toptions->c_cflag |= CRTSCTS;
275f2cb8f20SMatthias Ringwald     } else {
276f2cb8f20SMatthias Ringwald         // no flow control
277f2cb8f20SMatthias Ringwald         toptions->c_cflag &= ~CRTSCTS;
278f2cb8f20SMatthias Ringwald     }
279f2cb8f20SMatthias Ringwald }
280f2cb8f20SMatthias Ringwald 
281f2cb8f20SMatthias Ringwald static int btstack_uart_posix_set_parity(int parity){
282f2cb8f20SMatthias Ringwald     int fd = transport_data_source.source.fd;
2834437baf6SMatthias Ringwald     btstack_uart_posix_set_parity_option(&btstack_uart_block_termios, parity);
2844437baf6SMatthias Ringwald     if(tcsetattr(fd, TCSANOW, &btstack_uart_block_termios) < 0) {
285f2cb8f20SMatthias Ringwald         log_error("Couldn't set term attributes");
286f2cb8f20SMatthias Ringwald         return -1;
287f2cb8f20SMatthias Ringwald     }
288f2cb8f20SMatthias Ringwald     return 0;
289f2cb8f20SMatthias Ringwald }
290f2cb8f20SMatthias Ringwald 
291f2cb8f20SMatthias Ringwald 
292f2cb8f20SMatthias Ringwald static int btstack_uart_posix_set_flowcontrol(int flowcontrol){
293f2cb8f20SMatthias Ringwald     int fd = transport_data_source.source.fd;
2944437baf6SMatthias Ringwald     btstack_uart_posix_set_flowcontrol_option(&btstack_uart_block_termios, flowcontrol);
2954437baf6SMatthias Ringwald     if(tcsetattr(fd, TCSANOW, &btstack_uart_block_termios) < 0) {
296f2cb8f20SMatthias Ringwald         log_error("Couldn't set term attributes");
297f2cb8f20SMatthias Ringwald         return -1;
298f2cb8f20SMatthias Ringwald     }
299f2cb8f20SMatthias Ringwald     return 0;
300f2cb8f20SMatthias Ringwald }
301f2cb8f20SMatthias Ringwald 
302f2cb8f20SMatthias Ringwald static int btstack_uart_posix_open(void){
303f2cb8f20SMatthias Ringwald 
304f2cb8f20SMatthias Ringwald     const char * device_name = uart_config->device_name;
305f2cb8f20SMatthias Ringwald     const uint32_t baudrate  = uart_config->baudrate;
3061738838cSMatthias Ringwald     const int flowcontrol    = uart_config->flowcontrol;
3071738838cSMatthias Ringwald     const int parity         = uart_config->parity;
308f2cb8f20SMatthias Ringwald 
309f2cb8f20SMatthias Ringwald     int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
310f2cb8f20SMatthias Ringwald     int fd = open(device_name, flags);
311f2cb8f20SMatthias Ringwald     if (fd == -1)  {
312f2cb8f20SMatthias Ringwald         log_error("Unable to open port %s", device_name);
313f2cb8f20SMatthias Ringwald         return -1;
314f2cb8f20SMatthias Ringwald     }
315f2cb8f20SMatthias Ringwald 
3164437baf6SMatthias Ringwald     if (tcgetattr(fd, &btstack_uart_block_termios) < 0) {
317f2cb8f20SMatthias Ringwald         log_error("Couldn't get term attributes");
318f2cb8f20SMatthias Ringwald         return -1;
319f2cb8f20SMatthias Ringwald     }
3204437baf6SMatthias Ringwald     cfmakeraw(&btstack_uart_block_termios);   // make raw
321f2cb8f20SMatthias Ringwald 
322f2cb8f20SMatthias Ringwald     // 8N1
3234437baf6SMatthias Ringwald     btstack_uart_block_termios.c_cflag &= ~CSTOPB;
3244437baf6SMatthias Ringwald     btstack_uart_block_termios.c_cflag |= CS8;
325f2cb8f20SMatthias Ringwald 
3264437baf6SMatthias Ringwald     btstack_uart_block_termios.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
3274437baf6SMatthias Ringwald     btstack_uart_block_termios.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
328f2cb8f20SMatthias Ringwald 
329f2cb8f20SMatthias Ringwald     // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
3304437baf6SMatthias Ringwald     btstack_uart_block_termios.c_cc[VMIN]  = 1;
3314437baf6SMatthias Ringwald     btstack_uart_block_termios.c_cc[VTIME] = 0;
332f2cb8f20SMatthias Ringwald 
333f2cb8f20SMatthias Ringwald     // no parity
3344437baf6SMatthias Ringwald     btstack_uart_posix_set_parity_option(&btstack_uart_block_termios, parity);
335f2cb8f20SMatthias Ringwald 
336f2cb8f20SMatthias Ringwald     // flowcontrol
3374437baf6SMatthias Ringwald     btstack_uart_posix_set_flowcontrol_option(&btstack_uart_block_termios, flowcontrol);
338f2cb8f20SMatthias Ringwald 
3394437baf6SMatthias Ringwald     if(tcsetattr(fd, TCSANOW, &btstack_uart_block_termios) < 0) {
340f2cb8f20SMatthias Ringwald         log_error("Couldn't set term attributes");
341f2cb8f20SMatthias Ringwald         return -1;
342f2cb8f20SMatthias Ringwald     }
343f2cb8f20SMatthias Ringwald 
344f2cb8f20SMatthias Ringwald     // store fd in data source
345f2cb8f20SMatthias Ringwald     transport_data_source.source.fd = fd;
346f2cb8f20SMatthias Ringwald 
347f2cb8f20SMatthias Ringwald     // also set baudrate
348f2cb8f20SMatthias Ringwald     if (btstack_uart_posix_set_baudrate(baudrate) < 0){
349f2cb8f20SMatthias Ringwald         return -1;
350f2cb8f20SMatthias Ringwald     }
351f2cb8f20SMatthias Ringwald 
352f2cb8f20SMatthias Ringwald     // set up data_source
353f2cb8f20SMatthias Ringwald     btstack_run_loop_set_data_source_fd(&transport_data_source, fd);
354f2cb8f20SMatthias Ringwald     btstack_run_loop_set_data_source_handler(&transport_data_source, &hci_uart_posix_process);
355f2cb8f20SMatthias Ringwald     btstack_run_loop_add_data_source(&transport_data_source);
356f2cb8f20SMatthias Ringwald 
357f2cb8f20SMatthias Ringwald     // wait a bit - at least cheap FTDI232 clones might send the first byte out incorrectly
358f2cb8f20SMatthias Ringwald     usleep(100000);
359f2cb8f20SMatthias Ringwald 
360f2cb8f20SMatthias Ringwald     return 0;
361f2cb8f20SMatthias Ringwald }
362f2cb8f20SMatthias Ringwald 
363f2cb8f20SMatthias Ringwald static int btstack_uart_posix_close_new(void){
364f2cb8f20SMatthias Ringwald 
365f2cb8f20SMatthias Ringwald     // first remove run loop handler
366f2cb8f20SMatthias Ringwald     btstack_run_loop_remove_data_source(&transport_data_source);
367f2cb8f20SMatthias Ringwald 
368f2cb8f20SMatthias Ringwald     // then close device
369f2cb8f20SMatthias Ringwald     close(transport_data_source.source.fd);
370f2cb8f20SMatthias Ringwald     transport_data_source.source.fd = -1;
371f2cb8f20SMatthias Ringwald     return 0;
372f2cb8f20SMatthias Ringwald }
373f2cb8f20SMatthias Ringwald 
374f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_block_received( void (*block_handler)(void)){
375*efc1df55SMatthias Ringwald     btstack_uart_block_read_bytes_len = 0;
376f2cb8f20SMatthias Ringwald     block_received = block_handler;
377f2cb8f20SMatthias Ringwald }
378f2cb8f20SMatthias Ringwald 
379f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_block_sent( void (*block_handler)(void)){
380*efc1df55SMatthias Ringwald     btstack_uart_block_write_bytes_len = 0;
381f2cb8f20SMatthias Ringwald     block_sent = block_handler;
382f2cb8f20SMatthias Ringwald }
383f2cb8f20SMatthias Ringwald 
384f2cb8f20SMatthias Ringwald static void btstack_uart_posix_send_block(const uint8_t *data, uint16_t size){
385efef2dd3SMatthias Ringwald     btstack_assert(btstack_uart_block_write_bytes_len == 0);
386efef2dd3SMatthias Ringwald 
387f2cb8f20SMatthias Ringwald     // setup async write
388f2cb8f20SMatthias Ringwald     btstack_uart_block_write_bytes_data = data;
389f2cb8f20SMatthias Ringwald     btstack_uart_block_write_bytes_len  = size;
390f2cb8f20SMatthias Ringwald     btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE);
391f2cb8f20SMatthias Ringwald }
392f2cb8f20SMatthias Ringwald 
393f2cb8f20SMatthias Ringwald static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len){
394efef2dd3SMatthias Ringwald     btstack_assert(btstack_uart_block_read_bytes_len == 0);
395efef2dd3SMatthias Ringwald 
396efef2dd3SMatthias Ringwald     // setup async read
397f2cb8f20SMatthias Ringwald     btstack_uart_block_read_bytes_data = buffer;
398f2cb8f20SMatthias Ringwald     btstack_uart_block_read_bytes_len = len;
399f2cb8f20SMatthias Ringwald     btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
400f2cb8f20SMatthias Ringwald }
401f2cb8f20SMatthias Ringwald 
402f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5
403f2cb8f20SMatthias Ringwald 
404f2cb8f20SMatthias Ringwald // SLIP Implementation Start
405f2cb8f20SMatthias Ringwald #include "btstack_slip.h"
406f2cb8f20SMatthias Ringwald 
407f2cb8f20SMatthias Ringwald // max size of outgoing SLIP chunks
408f2cb8f20SMatthias Ringwald #define SLIP_TX_CHUNK_LEN   128
409f2cb8f20SMatthias Ringwald 
410f2cb8f20SMatthias Ringwald #define SLIP_RECEIVE_BUFFER_SIZE 128
411f2cb8f20SMatthias Ringwald 
412f2cb8f20SMatthias Ringwald // encoded SLIP chunk
413f2cb8f20SMatthias Ringwald static uint8_t   btstack_uart_slip_outgoing_buffer[SLIP_TX_CHUNK_LEN+1];
414f2cb8f20SMatthias Ringwald 
415f2cb8f20SMatthias Ringwald // block write
416f2cb8f20SMatthias Ringwald static int             btstack_uart_slip_write_bytes_len;
417f2cb8f20SMatthias Ringwald static const uint8_t * btstack_uart_slip_write_bytes_data;
418f2cb8f20SMatthias Ringwald static int             btstack_uart_slip_write_active;
419f2cb8f20SMatthias Ringwald 
420f2cb8f20SMatthias Ringwald // block read
421f2cb8f20SMatthias Ringwald static uint8_t         btstack_uart_slip_receive_buffer[SLIP_RECEIVE_BUFFER_SIZE];
422f2cb8f20SMatthias Ringwald static uint16_t        btstack_uart_slip_receive_pos;
423f2cb8f20SMatthias Ringwald static uint16_t        btstack_uart_slip_receive_len;
424f2cb8f20SMatthias Ringwald static uint8_t         btstack_uart_slip_receive_track_start;
425f2cb8f20SMatthias Ringwald static uint32_t        btstack_uart_slip_receive_start_time;
426f2cb8f20SMatthias Ringwald static int             btstack_uart_slip_receive_active;
427f2cb8f20SMatthias Ringwald 
428f2cb8f20SMatthias Ringwald // callbacks
429f2cb8f20SMatthias Ringwald static void (*frame_sent)(void);
430f2cb8f20SMatthias Ringwald static void (*frame_received)(uint16_t frame_size);
431f2cb8f20SMatthias Ringwald 
432f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_block_sent(void);
433f2cb8f20SMatthias Ringwald 
434f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_process_write(btstack_data_source_t *ds) {
435f2cb8f20SMatthias Ringwald 
436f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_write_bytes_len == 0) return;
437f2cb8f20SMatthias Ringwald 
438f2cb8f20SMatthias Ringwald     uint32_t start = btstack_run_loop_get_time_ms();
439f2cb8f20SMatthias Ringwald 
440f2cb8f20SMatthias Ringwald     // write up to btstack_uart_slip_write_bytes_len to fd
441f2cb8f20SMatthias Ringwald     int bytes_written = (int) write(ds->source.fd, btstack_uart_slip_write_bytes_data, btstack_uart_slip_write_bytes_len);
442f2cb8f20SMatthias Ringwald     if (bytes_written < 0) {
443f2cb8f20SMatthias Ringwald         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
444f2cb8f20SMatthias Ringwald         return;
445f2cb8f20SMatthias Ringwald     }
446f2cb8f20SMatthias Ringwald 
447f2cb8f20SMatthias Ringwald     uint32_t end = btstack_run_loop_get_time_ms();
448f2cb8f20SMatthias Ringwald     if (end - start > 10){
449f2cb8f20SMatthias Ringwald         log_info("write took %u ms", end - start);
450f2cb8f20SMatthias Ringwald     }
451f2cb8f20SMatthias Ringwald 
452f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_bytes_data += bytes_written;
453f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_bytes_len  -= bytes_written;
454f2cb8f20SMatthias Ringwald 
455f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_write_bytes_len){
456f2cb8f20SMatthias Ringwald         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
457f2cb8f20SMatthias Ringwald         return;
458f2cb8f20SMatthias Ringwald     }
459f2cb8f20SMatthias Ringwald 
460f2cb8f20SMatthias Ringwald     btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
461f2cb8f20SMatthias Ringwald 
462f2cb8f20SMatthias Ringwald     // done with TX chunk
463f2cb8f20SMatthias Ringwald     btstack_uart_slip_posix_block_sent();
464f2cb8f20SMatthias Ringwald }
465f2cb8f20SMatthias Ringwald 
466f2cb8f20SMatthias Ringwald // @returns frame size if complete frame decoded and delivered
467f2cb8f20SMatthias Ringwald static uint16_t btstack_uart_slip_posix_process_buffer(void){
468f2cb8f20SMatthias Ringwald     log_debug("process buffer: pos %u, len %u", btstack_uart_slip_receive_pos, btstack_uart_slip_receive_len);
469f2cb8f20SMatthias Ringwald 
470f2cb8f20SMatthias Ringwald     uint16_t frame_size = 0;
471f2cb8f20SMatthias Ringwald     while (btstack_uart_slip_receive_pos < btstack_uart_slip_receive_len && frame_size == 0){
472f2cb8f20SMatthias Ringwald         btstack_slip_decoder_process(btstack_uart_slip_receive_buffer[btstack_uart_slip_receive_pos++]);
473f2cb8f20SMatthias Ringwald         frame_size = btstack_slip_decoder_frame_size();
474f2cb8f20SMatthias Ringwald     }
475f2cb8f20SMatthias Ringwald 
476f2cb8f20SMatthias Ringwald     // reset buffer if fully processed
477f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_receive_pos == btstack_uart_slip_receive_len ){
478f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_len = 0;
479f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_pos = 0;
480f2cb8f20SMatthias Ringwald     }
481f2cb8f20SMatthias Ringwald 
482f2cb8f20SMatthias Ringwald     // deliver frame if frame complete
483f2cb8f20SMatthias Ringwald     if (frame_size) {
484f2cb8f20SMatthias Ringwald 
485f2cb8f20SMatthias Ringwald         // receive done
486f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_active = 0;
487f2cb8f20SMatthias Ringwald 
488f2cb8f20SMatthias Ringwald         // only print if read was involved
489f2cb8f20SMatthias Ringwald         if (btstack_uart_slip_receive_track_start == 0){
490f2cb8f20SMatthias Ringwald             log_info("frame receive time %u ms", btstack_run_loop_get_time_ms() - btstack_uart_slip_receive_start_time);
491f2cb8f20SMatthias Ringwald             btstack_uart_slip_receive_start_time = 0;
492f2cb8f20SMatthias Ringwald         }
493f2cb8f20SMatthias Ringwald 
494f2cb8f20SMatthias Ringwald         (*frame_received)(frame_size);
495f2cb8f20SMatthias Ringwald     }
496f2cb8f20SMatthias Ringwald 
497f2cb8f20SMatthias Ringwald     return frame_size;
498f2cb8f20SMatthias Ringwald }
499f2cb8f20SMatthias Ringwald 
500f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_process_read(btstack_data_source_t *ds) {
501f2cb8f20SMatthias Ringwald 
502f2cb8f20SMatthias Ringwald     uint32_t start = btstack_run_loop_get_time_ms();
503f2cb8f20SMatthias Ringwald 
504f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_receive_track_start){
505f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_track_start = 0;
506f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_start_time = start;
507f2cb8f20SMatthias Ringwald     }
508f2cb8f20SMatthias Ringwald 
509f2cb8f20SMatthias Ringwald     // read up to bytes_to_read data in
510f2cb8f20SMatthias Ringwald     ssize_t bytes_read = read(ds->source.fd, btstack_uart_slip_receive_buffer, SLIP_RECEIVE_BUFFER_SIZE);
511f2cb8f20SMatthias Ringwald 
512f2cb8f20SMatthias Ringwald     log_debug("requested %u bytes, got %d", SLIP_RECEIVE_BUFFER_SIZE, (int) bytes_read);
513f2cb8f20SMatthias Ringwald     uint32_t end = btstack_run_loop_get_time_ms();
514f2cb8f20SMatthias Ringwald     if (end - start > 10){
515f2cb8f20SMatthias Ringwald         log_info("read took %u ms", end - start);
516f2cb8f20SMatthias Ringwald     }
517f2cb8f20SMatthias Ringwald     if (bytes_read < 0) return;
518f2cb8f20SMatthias Ringwald 
519f2cb8f20SMatthias Ringwald     btstack_uart_slip_receive_pos = 0;
520f2cb8f20SMatthias Ringwald     btstack_uart_slip_receive_len = (uint16_t ) bytes_read;
521f2cb8f20SMatthias Ringwald 
522f2cb8f20SMatthias Ringwald     btstack_uart_slip_posix_process_buffer();
523f2cb8f20SMatthias Ringwald }
524f2cb8f20SMatthias Ringwald 
525f2cb8f20SMatthias Ringwald // -----------------------------
526f2cb8f20SMatthias Ringwald // SLIP ENCODING
527f2cb8f20SMatthias Ringwald 
528f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_encode_chunk_and_send(void){
529f2cb8f20SMatthias Ringwald     uint16_t pos = 0;
530f2cb8f20SMatthias Ringwald     while (btstack_slip_encoder_has_data() & (pos < SLIP_TX_CHUNK_LEN)) {
531f2cb8f20SMatthias Ringwald         btstack_uart_slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
532f2cb8f20SMatthias Ringwald     }
533f2cb8f20SMatthias Ringwald 
534f2cb8f20SMatthias Ringwald     // setup async write and start sending
535f2cb8f20SMatthias Ringwald     log_debug("slip: send %d bytes", pos);
536f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_bytes_data = btstack_uart_slip_outgoing_buffer;
537f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_bytes_len  = pos;
538f2cb8f20SMatthias Ringwald     btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE);
539f2cb8f20SMatthias Ringwald }
540f2cb8f20SMatthias Ringwald 
541f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_block_sent(void){
542f2cb8f20SMatthias Ringwald     // check if more data to send
543f2cb8f20SMatthias Ringwald     if (btstack_slip_encoder_has_data()){
544f2cb8f20SMatthias Ringwald         btstack_uart_slip_posix_encode_chunk_and_send();
545f2cb8f20SMatthias Ringwald         return;
546f2cb8f20SMatthias Ringwald     }
547f2cb8f20SMatthias Ringwald 
548f2cb8f20SMatthias Ringwald     // write done
549f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_active = 0;
550f2cb8f20SMatthias Ringwald 
551f2cb8f20SMatthias Ringwald     // notify done
552f2cb8f20SMatthias Ringwald     if (frame_sent){
553f2cb8f20SMatthias Ringwald         frame_sent();
554f2cb8f20SMatthias Ringwald     }
555f2cb8f20SMatthias Ringwald }
556f2cb8f20SMatthias Ringwald 
557f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_send_frame(const uint8_t * frame, uint16_t frame_size){
558f2cb8f20SMatthias Ringwald 
559f2cb8f20SMatthias Ringwald     // write started
560f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_active = 1;
561f2cb8f20SMatthias Ringwald 
562f2cb8f20SMatthias Ringwald     // Prepare encoding of Header + Packet (+ DIC)
563f2cb8f20SMatthias Ringwald     btstack_slip_encoder_start(frame, frame_size);
564f2cb8f20SMatthias Ringwald 
565f2cb8f20SMatthias Ringwald     // Fill rest of chunk from packet and send
566f2cb8f20SMatthias Ringwald     btstack_uart_slip_posix_encode_chunk_and_send();
567f2cb8f20SMatthias Ringwald }
568f2cb8f20SMatthias Ringwald 
569f2cb8f20SMatthias Ringwald // SLIP ENCODING
570f2cb8f20SMatthias Ringwald // -----------------------------
571f2cb8f20SMatthias Ringwald 
572f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_receive_frame(uint8_t *buffer, uint16_t len){
573f2cb8f20SMatthias Ringwald 
574f2cb8f20SMatthias Ringwald     // receive started
575f2cb8f20SMatthias Ringwald     btstack_uart_slip_receive_active = 1;
576f2cb8f20SMatthias Ringwald 
577f2cb8f20SMatthias Ringwald     log_debug("receive block, size %u", len);
578f2cb8f20SMatthias Ringwald     btstack_uart_slip_receive_track_start = 1;
579f2cb8f20SMatthias Ringwald 
580f2cb8f20SMatthias Ringwald     // setup SLIP decoder
581f2cb8f20SMatthias Ringwald     btstack_slip_decoder_init(buffer, len);
582f2cb8f20SMatthias Ringwald 
583f2cb8f20SMatthias Ringwald     // process bytes received in earlier read. might deliver packet, which in turn will call us again.
584f2cb8f20SMatthias Ringwald     // just make sure to exit right away
585f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_receive_len){
586f2cb8f20SMatthias Ringwald         int frame_found = btstack_uart_slip_posix_process_buffer();
587f2cb8f20SMatthias Ringwald         if (frame_found) return;
588f2cb8f20SMatthias Ringwald     }
589f2cb8f20SMatthias Ringwald 
590f2cb8f20SMatthias Ringwald     // no frame delivered, enable posix read
591f2cb8f20SMatthias Ringwald     btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
592f2cb8f20SMatthias Ringwald }
593f2cb8f20SMatthias Ringwald 
594f2cb8f20SMatthias Ringwald 
595f2cb8f20SMatthias Ringwald 
596f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_set_frame_received( void (*block_handler)(uint16_t frame_size)){
597f2cb8f20SMatthias Ringwald     frame_received = block_handler;
598f2cb8f20SMatthias Ringwald }
599f2cb8f20SMatthias Ringwald 
600f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_set_frame_sent( void (*block_handler)(void)){
601f2cb8f20SMatthias Ringwald     frame_sent = block_handler;
602f2cb8f20SMatthias Ringwald }
603f2cb8f20SMatthias Ringwald 
604f2cb8f20SMatthias Ringwald // SLIP Implementation End
605f2cb8f20SMatthias Ringwald #endif
606f2cb8f20SMatthias Ringwald 
607f2cb8f20SMatthias Ringwald // dispatch into block or SLIP code
608f2cb8f20SMatthias Ringwald static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
609f2cb8f20SMatthias Ringwald     if (ds->source.fd < 0) return;
610f2cb8f20SMatthias Ringwald     switch (callback_type){
611f2cb8f20SMatthias Ringwald         case DATA_SOURCE_CALLBACK_READ:
612f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5
613f2cb8f20SMatthias Ringwald             if (btstack_uart_slip_receive_active){
614f2cb8f20SMatthias Ringwald                 btstack_uart_slip_posix_process_read(ds);
615f2cb8f20SMatthias Ringwald             } else
616f2cb8f20SMatthias Ringwald #endif
617f2cb8f20SMatthias Ringwald             {
618f2cb8f20SMatthias Ringwald                 btstack_uart_block_posix_process_read(ds);
619f2cb8f20SMatthias Ringwald             }
620f2cb8f20SMatthias Ringwald             break;
621f2cb8f20SMatthias Ringwald         case DATA_SOURCE_CALLBACK_WRITE:
622f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5
623f2cb8f20SMatthias Ringwald             if (btstack_uart_slip_write_active){
624f2cb8f20SMatthias Ringwald                 btstack_uart_slip_posix_process_write(ds);
625f2cb8f20SMatthias Ringwald             } else
626f2cb8f20SMatthias Ringwald #endif
627f2cb8f20SMatthias Ringwald             {
628f2cb8f20SMatthias Ringwald                 btstack_uart_block_posix_process_write(ds);
629f2cb8f20SMatthias Ringwald             }
630f2cb8f20SMatthias Ringwald             break;
631f2cb8f20SMatthias Ringwald         default:
632f2cb8f20SMatthias Ringwald             break;
633f2cb8f20SMatthias Ringwald     }
634f2cb8f20SMatthias Ringwald }
635f2cb8f20SMatthias Ringwald 
636f2cb8f20SMatthias Ringwald static const btstack_uart_t btstack_uart_posix = {
637f2cb8f20SMatthias Ringwald     /* int  (*init)(hci_transport_config_uart_t * config); */              &btstack_uart_posix_init,
638f2cb8f20SMatthias Ringwald     /* int  (*open)(void); */                                              &btstack_uart_posix_open,
639f2cb8f20SMatthias Ringwald     /* int  (*close)(void); */                                             &btstack_uart_posix_close_new,
640f2cb8f20SMatthias Ringwald     /* void (*set_block_received)(void (*handler)(void)); */               &btstack_uart_posix_set_block_received,
641f2cb8f20SMatthias Ringwald     /* void (*set_block_sent)(void (*handler)(void)); */                   &btstack_uart_posix_set_block_sent,
642f2cb8f20SMatthias Ringwald     /* int  (*set_baudrate)(uint32_t baudrate); */                         &btstack_uart_posix_set_baudrate,
643f2cb8f20SMatthias Ringwald     /* int  (*set_parity)(int parity); */                                  &btstack_uart_posix_set_parity,
644f2cb8f20SMatthias Ringwald     /* int  (*set_flowcontrol)(int flowcontrol); */                        &btstack_uart_posix_set_flowcontrol,
645f2cb8f20SMatthias Ringwald     /* void (*receive_block)(uint8_t *buffer, uint16_t len); */            &btstack_uart_posix_receive_block,
646f2cb8f20SMatthias Ringwald     /* void (*send_block)(const uint8_t *buffer, uint16_t length); */      &btstack_uart_posix_send_block,
647f2cb8f20SMatthias Ringwald     /* int (*get_supported_sleep_modes); */                                NULL,
648f2cb8f20SMatthias Ringwald     /* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */         NULL,
649f2cb8f20SMatthias Ringwald     /* void (*set_wakeup_handler)(void (*handler)(void)); */               NULL,
650f2cb8f20SMatthias Ringwald 
651f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5
652f2cb8f20SMatthias Ringwald     /* void (*set_frame_received)(void (*handler)(uint16_t frame_size); */ &btstack_uart_slip_posix_set_frame_received,
653f2cb8f20SMatthias Ringwald     /* void (*set_fraae_sent)(void (*handler)(void)); */                   &btstack_uart_slip_posix_set_frame_sent,
654f2cb8f20SMatthias Ringwald     /* void (*receive_frame)(uint8_t *buffer, uint16_t len); */            &btstack_uart_slip_posix_receive_frame,
655f2cb8f20SMatthias Ringwald     /* void (*send_frame)(const uint8_t *buffer, uint16_t length); */      &btstack_uart_slip_posix_send_frame,
656f2cb8f20SMatthias Ringwald #else
657f2cb8f20SMatthias Ringwald     NULL, NULL, NULL, NULL,
658f2cb8f20SMatthias Ringwald #endif
659f2cb8f20SMatthias Ringwald };
660f2cb8f20SMatthias Ringwald 
661f2cb8f20SMatthias Ringwald const btstack_uart_t * btstack_uart_posix_instance(void){
662f2cb8f20SMatthias Ringwald 	return &btstack_uart_posix;
663f2cb8f20SMatthias Ringwald }
664