xref: /btstack/platform/posix/btstack_uart_posix.c (revision 2fca4dad957cd7b88f4657ed51e89c12615dda72)
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
23*2fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*2fca4dadSMilanka 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 
64f2cb8f20SMatthias Ringwald // data source for integration with BTstack Runloop
65f2cb8f20SMatthias Ringwald static btstack_data_source_t transport_data_source;
66f2cb8f20SMatthias Ringwald 
67f2cb8f20SMatthias Ringwald // block write
68f2cb8f20SMatthias Ringwald static int             btstack_uart_block_write_bytes_len;
69f2cb8f20SMatthias Ringwald static const uint8_t * btstack_uart_block_write_bytes_data;
70f2cb8f20SMatthias Ringwald 
71f2cb8f20SMatthias Ringwald // block read
72f2cb8f20SMatthias Ringwald static uint16_t  btstack_uart_block_read_bytes_len;
73f2cb8f20SMatthias Ringwald static uint8_t * btstack_uart_block_read_bytes_data;
74f2cb8f20SMatthias Ringwald 
75f2cb8f20SMatthias Ringwald // callbacks
76f2cb8f20SMatthias Ringwald static void (*block_sent)(void);
77f2cb8f20SMatthias Ringwald static void (*block_received)(void);
78f2cb8f20SMatthias Ringwald 
79f2cb8f20SMatthias Ringwald 
80f2cb8f20SMatthias Ringwald static int btstack_uart_posix_init(const btstack_uart_config_t * config){
81f2cb8f20SMatthias Ringwald     uart_config = config;
82f2cb8f20SMatthias Ringwald     return 0;
83f2cb8f20SMatthias Ringwald }
84f2cb8f20SMatthias Ringwald 
85f2cb8f20SMatthias Ringwald static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type);
86f2cb8f20SMatthias Ringwald 
87f2cb8f20SMatthias Ringwald static void btstack_uart_block_posix_process_write(btstack_data_source_t *ds) {
88f2cb8f20SMatthias Ringwald 
89f2cb8f20SMatthias Ringwald     if (btstack_uart_block_write_bytes_len == 0) return;
90f2cb8f20SMatthias Ringwald 
91f2cb8f20SMatthias Ringwald     uint32_t start = btstack_run_loop_get_time_ms();
92f2cb8f20SMatthias Ringwald 
93f2cb8f20SMatthias Ringwald     // write up to write_bytes_len to fd
94f2cb8f20SMatthias Ringwald     int bytes_written = (int) write(ds->source.fd, btstack_uart_block_write_bytes_data, btstack_uart_block_write_bytes_len);
95f2cb8f20SMatthias Ringwald     uint32_t end = btstack_run_loop_get_time_ms();
96f2cb8f20SMatthias Ringwald     if (end - start > 10){
97f2cb8f20SMatthias Ringwald         log_info("write took %u ms", end - start);
98f2cb8f20SMatthias Ringwald     }
99f2cb8f20SMatthias Ringwald     if (bytes_written == 0){
100f2cb8f20SMatthias Ringwald         log_error("wrote zero bytes\n");
101f2cb8f20SMatthias Ringwald         return;
102f2cb8f20SMatthias Ringwald     }
103f2cb8f20SMatthias Ringwald     if (bytes_written < 0) {
104f2cb8f20SMatthias Ringwald         log_error("write returned error\n");
105f2cb8f20SMatthias Ringwald         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
106f2cb8f20SMatthias Ringwald         return;
107f2cb8f20SMatthias Ringwald     }
108f2cb8f20SMatthias Ringwald 
109f2cb8f20SMatthias Ringwald     btstack_uart_block_write_bytes_data += bytes_written;
110f2cb8f20SMatthias Ringwald     btstack_uart_block_write_bytes_len  -= bytes_written;
111f2cb8f20SMatthias Ringwald 
112f2cb8f20SMatthias Ringwald     if (btstack_uart_block_write_bytes_len){
113f2cb8f20SMatthias Ringwald         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
114f2cb8f20SMatthias Ringwald         return;
115f2cb8f20SMatthias Ringwald     }
116f2cb8f20SMatthias Ringwald 
117f2cb8f20SMatthias Ringwald     btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
118f2cb8f20SMatthias Ringwald 
119f2cb8f20SMatthias Ringwald     // notify done
120f2cb8f20SMatthias Ringwald     if (block_sent){
121f2cb8f20SMatthias Ringwald         block_sent();
122f2cb8f20SMatthias Ringwald     }
123f2cb8f20SMatthias Ringwald }
124f2cb8f20SMatthias Ringwald 
125f2cb8f20SMatthias Ringwald static void btstack_uart_block_posix_process_read(btstack_data_source_t *ds) {
126f2cb8f20SMatthias Ringwald 
127f2cb8f20SMatthias Ringwald     if (btstack_uart_block_read_bytes_len == 0) {
128f2cb8f20SMatthias Ringwald         log_info("called but no read pending");
129f2cb8f20SMatthias Ringwald         btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
130f2cb8f20SMatthias Ringwald     }
131f2cb8f20SMatthias Ringwald 
132f2cb8f20SMatthias Ringwald     uint32_t start = btstack_run_loop_get_time_ms();
133f2cb8f20SMatthias Ringwald 
134f2cb8f20SMatthias Ringwald     // read up to bytes_to_read data in
135f2cb8f20SMatthias Ringwald     ssize_t bytes_read = read(ds->source.fd, btstack_uart_block_read_bytes_data, btstack_uart_block_read_bytes_len);
136f2cb8f20SMatthias Ringwald     // log_info("read need %u bytes, got %d", btstack_uart_block_read_bytes_len, (int) bytes_read);
137f2cb8f20SMatthias Ringwald     uint32_t end = btstack_run_loop_get_time_ms();
138f2cb8f20SMatthias Ringwald     if (end - start > 10){
139f2cb8f20SMatthias Ringwald         log_info("read took %u ms", end - start);
140f2cb8f20SMatthias Ringwald     }
141f2cb8f20SMatthias Ringwald     if (bytes_read == 0){
142f2cb8f20SMatthias Ringwald         log_error("read zero bytes\n");
143f2cb8f20SMatthias Ringwald         return;
144f2cb8f20SMatthias Ringwald     }
145f2cb8f20SMatthias Ringwald     if (bytes_read < 0) {
146f2cb8f20SMatthias Ringwald         log_error("read returned error\n");
147f2cb8f20SMatthias Ringwald         return;
148f2cb8f20SMatthias Ringwald     }
149f2cb8f20SMatthias Ringwald 
150f2cb8f20SMatthias Ringwald     btstack_uart_block_read_bytes_len   -= bytes_read;
151f2cb8f20SMatthias Ringwald     btstack_uart_block_read_bytes_data  += bytes_read;
152f2cb8f20SMatthias Ringwald     if (btstack_uart_block_read_bytes_len > 0) return;
153f2cb8f20SMatthias Ringwald 
154f2cb8f20SMatthias Ringwald     btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_READ);
155f2cb8f20SMatthias Ringwald 
156f2cb8f20SMatthias Ringwald     if (block_received){
157f2cb8f20SMatthias Ringwald         block_received();
158f2cb8f20SMatthias Ringwald     }
159f2cb8f20SMatthias Ringwald }
160f2cb8f20SMatthias Ringwald 
161f2cb8f20SMatthias Ringwald static int btstack_uart_posix_set_baudrate(uint32_t baudrate){
162f2cb8f20SMatthias Ringwald 
163f2cb8f20SMatthias Ringwald     int fd = transport_data_source.source.fd;
164f2cb8f20SMatthias Ringwald 
165f2cb8f20SMatthias Ringwald     log_info("h4_set_baudrate %u", baudrate);
166f2cb8f20SMatthias Ringwald 
167f2cb8f20SMatthias Ringwald     struct termios toptions;
168f2cb8f20SMatthias Ringwald 
169f2cb8f20SMatthias Ringwald     if (tcgetattr(fd, &toptions) < 0) {
170f2cb8f20SMatthias Ringwald         log_error("btstack_uart_posix_set_baudrate: Couldn't get term attributes");
171f2cb8f20SMatthias Ringwald         return -1;
172f2cb8f20SMatthias Ringwald     }
173f2cb8f20SMatthias Ringwald 
174f2cb8f20SMatthias Ringwald #ifndef __APPLE__
175f2cb8f20SMatthias Ringwald 
176f2cb8f20SMatthias Ringwald     speed_t brate = baudrate; // let you override switch below if needed
177f2cb8f20SMatthias Ringwald     switch(baudrate) {
178f2cb8f20SMatthias Ringwald         case    9600: brate=B9600;    break;
179f2cb8f20SMatthias Ringwald         case   19200: brate=B19200;   break;
180f2cb8f20SMatthias Ringwald         case   38400: brate=B38400;   break;
181f2cb8f20SMatthias Ringwald         case 57600:  brate=B57600;  break;
182f2cb8f20SMatthias Ringwald         case 115200: brate=B115200; break;
183f2cb8f20SMatthias Ringwald #ifdef B230400
184f2cb8f20SMatthias Ringwald         case 230400: brate=B230400; break;
185f2cb8f20SMatthias Ringwald #endif
186f2cb8f20SMatthias Ringwald #ifdef B460800
187f2cb8f20SMatthias Ringwald         case 460800: brate=B460800; break;
188f2cb8f20SMatthias Ringwald #endif
189f2cb8f20SMatthias Ringwald #ifdef B500000
190f2cb8f20SMatthias Ringwald         case  500000: brate=B500000;  break;
191f2cb8f20SMatthias Ringwald #endif
192f2cb8f20SMatthias Ringwald #ifdef B576000
193f2cb8f20SMatthias Ringwald         case  576000: brate=B576000;  break;
194f2cb8f20SMatthias Ringwald #endif
195f2cb8f20SMatthias Ringwald #ifdef B921600
196f2cb8f20SMatthias Ringwald         case 921600: brate=B921600; break;
197f2cb8f20SMatthias Ringwald #endif
198f2cb8f20SMatthias Ringwald #ifdef B1000000
199f2cb8f20SMatthias Ringwald         case 1000000: brate=B1000000; break;
200f2cb8f20SMatthias Ringwald #endif
201f2cb8f20SMatthias Ringwald #ifdef B1152000
202f2cb8f20SMatthias Ringwald         case 1152000: brate=B1152000; break;
203f2cb8f20SMatthias Ringwald #endif
204f2cb8f20SMatthias Ringwald #ifdef B1500000
205f2cb8f20SMatthias Ringwald         case 1500000: brate=B1500000; break;
206f2cb8f20SMatthias Ringwald #endif
207f2cb8f20SMatthias Ringwald #ifdef B2000000
208f2cb8f20SMatthias Ringwald         case 2000000: brate=B2000000; break;
209f2cb8f20SMatthias Ringwald #endif
210f2cb8f20SMatthias Ringwald #ifdef B2500000
211f2cb8f20SMatthias Ringwald         case 2500000: brate=B2500000; break;
212f2cb8f20SMatthias Ringwald #endif
213f2cb8f20SMatthias Ringwald #ifdef B3000000
214f2cb8f20SMatthias Ringwald         case 3000000: brate=B3000000; break;
215f2cb8f20SMatthias Ringwald #endif
216f2cb8f20SMatthias Ringwald #ifdef B3500000
217f2cb8f20SMatthias Ringwald         case 3500000: brate=B3500000; break;
218f2cb8f20SMatthias Ringwald #endif
219f2cb8f20SMatthias Ringwald #ifdef B400000
220f2cb8f20SMatthias Ringwald         case 4000000: brate=B4000000; break;
221f2cb8f20SMatthias Ringwald #endif
222f2cb8f20SMatthias Ringwald         default:
223f2cb8f20SMatthias Ringwald             log_error("can't set baudrate %dn", baudrate );
224f2cb8f20SMatthias Ringwald             return -1;
225f2cb8f20SMatthias Ringwald     }
226f2cb8f20SMatthias Ringwald     cfsetospeed(&toptions, brate);
227f2cb8f20SMatthias Ringwald     cfsetispeed(&toptions, brate);
228f2cb8f20SMatthias Ringwald #endif
229f2cb8f20SMatthias Ringwald 
230f2cb8f20SMatthias Ringwald     // also set options for __APPLE__ to enforce write drain
231f2cb8f20SMatthias Ringwald     // Mac OS Mojave: tcsdrain did not work as expected
232f2cb8f20SMatthias Ringwald 
233f2cb8f20SMatthias Ringwald     if( tcsetattr(fd, TCSADRAIN, &toptions) < 0) {
234f2cb8f20SMatthias Ringwald         log_error("Couldn't set term attributes");
235f2cb8f20SMatthias Ringwald         return -1;
236f2cb8f20SMatthias Ringwald     }
237f2cb8f20SMatthias Ringwald 
238f2cb8f20SMatthias Ringwald #ifdef __APPLE__
239f2cb8f20SMatthias Ringwald     // From https://developer.apple.com/library/content/samplecode/SerialPortSample/Listings/SerialPortSample_SerialPortSample_c.html
240f2cb8f20SMatthias Ringwald 
241f2cb8f20SMatthias Ringwald     // The IOSSIOSPEED ioctl can be used to set arbitrary baud rates
242f2cb8f20SMatthias Ringwald     // other than those specified by POSIX. The driver for the underlying serial hardware
243f2cb8f20SMatthias Ringwald     // ultimately determines which baud rates can be used. This ioctl sets both the input
244f2cb8f20SMatthias Ringwald     // and output speed.
245f2cb8f20SMatthias Ringwald 
246f2cb8f20SMatthias Ringwald     speed_t speed = baudrate;
247f2cb8f20SMatthias Ringwald     if (ioctl(fd, IOSSIOSPEED, &speed) == -1) {
248f2cb8f20SMatthias Ringwald         log_error("btstack_uart_posix_set_baudrate: error calling ioctl(..., IOSSIOSPEED, %u) - %s(%d).\n", baudrate, strerror(errno), errno);
249f2cb8f20SMatthias Ringwald         return -1;
250f2cb8f20SMatthias Ringwald     }
251f2cb8f20SMatthias Ringwald #endif
252f2cb8f20SMatthias Ringwald 
253f2cb8f20SMatthias Ringwald     return 0;
254f2cb8f20SMatthias Ringwald }
255f2cb8f20SMatthias Ringwald 
256f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_parity_option(struct termios * toptions, int parity){
257f2cb8f20SMatthias Ringwald     switch (parity){
258f2cb8f20SMatthias Ringwald         case BTSTACK_UART_PARITY_OFF:
259f2cb8f20SMatthias Ringwald             toptions->c_cflag &= ~PARENB;
260f2cb8f20SMatthias Ringwald             toptions->c_cflag &= ~PARODD;
261f2cb8f20SMatthias Ringwald             break;
262f2cb8f20SMatthias Ringwald         case BTSTACK_UART_PARITY_EVEN:
263f2cb8f20SMatthias Ringwald             toptions->c_cflag |=  PARENB;
264f2cb8f20SMatthias Ringwald             toptions->c_cflag &= ~PARODD;
265f2cb8f20SMatthias Ringwald             break;
266f2cb8f20SMatthias Ringwald         case BTSTACK_UART_PARITY_ODD:
267f2cb8f20SMatthias Ringwald             toptions->c_cflag |= PARENB;
268f2cb8f20SMatthias Ringwald             toptions->c_cflag |= PARODD;
269f2cb8f20SMatthias Ringwald         default:
270f2cb8f20SMatthias Ringwald             break;
271f2cb8f20SMatthias Ringwald     }
272f2cb8f20SMatthias Ringwald }
273f2cb8f20SMatthias Ringwald 
274f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_flowcontrol_option(struct termios * toptions, int flowcontrol){
275f2cb8f20SMatthias Ringwald     if (flowcontrol) {
276f2cb8f20SMatthias Ringwald         // with flow control
277f2cb8f20SMatthias Ringwald         toptions->c_cflag |= CRTSCTS;
278f2cb8f20SMatthias Ringwald     } else {
279f2cb8f20SMatthias Ringwald         // no flow control
280f2cb8f20SMatthias Ringwald         toptions->c_cflag &= ~CRTSCTS;
281f2cb8f20SMatthias Ringwald     }
282f2cb8f20SMatthias Ringwald }
283f2cb8f20SMatthias Ringwald 
284f2cb8f20SMatthias Ringwald static int btstack_uart_posix_set_parity(int parity){
285f2cb8f20SMatthias Ringwald     int fd = transport_data_source.source.fd;
286f2cb8f20SMatthias Ringwald     struct termios toptions;
287f2cb8f20SMatthias Ringwald     if (tcgetattr(fd, &toptions) < 0) {
288f2cb8f20SMatthias Ringwald         log_error("Couldn't get term attributes");
289f2cb8f20SMatthias Ringwald         return -1;
290f2cb8f20SMatthias Ringwald     }
291f2cb8f20SMatthias Ringwald     btstack_uart_posix_set_parity_option(&toptions, parity);
292f2cb8f20SMatthias Ringwald     if(tcsetattr(fd, TCSANOW, &toptions) < 0) {
293f2cb8f20SMatthias Ringwald         log_error("Couldn't set term attributes");
294f2cb8f20SMatthias Ringwald         return -1;
295f2cb8f20SMatthias Ringwald     }
296f2cb8f20SMatthias Ringwald     return 0;
297f2cb8f20SMatthias Ringwald }
298f2cb8f20SMatthias Ringwald 
299f2cb8f20SMatthias Ringwald 
300f2cb8f20SMatthias Ringwald static int btstack_uart_posix_set_flowcontrol(int flowcontrol){
301f2cb8f20SMatthias Ringwald     int fd = transport_data_source.source.fd;
302f2cb8f20SMatthias Ringwald     struct termios toptions;
303f2cb8f20SMatthias Ringwald     if (tcgetattr(fd, &toptions) < 0) {
304f2cb8f20SMatthias Ringwald         log_error("Couldn't get term attributes");
305f2cb8f20SMatthias Ringwald         return -1;
306f2cb8f20SMatthias Ringwald     }
307f2cb8f20SMatthias Ringwald     btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol);
308f2cb8f20SMatthias Ringwald     if(tcsetattr(fd, TCSANOW, &toptions) < 0) {
309f2cb8f20SMatthias Ringwald         log_error("Couldn't set term attributes");
310f2cb8f20SMatthias Ringwald         return -1;
311f2cb8f20SMatthias Ringwald     }
312f2cb8f20SMatthias Ringwald     return 0;
313f2cb8f20SMatthias Ringwald }
314f2cb8f20SMatthias Ringwald 
315f2cb8f20SMatthias Ringwald static int btstack_uart_posix_open(void){
316f2cb8f20SMatthias Ringwald 
317f2cb8f20SMatthias Ringwald     const char * device_name = uart_config->device_name;
318f2cb8f20SMatthias Ringwald     const uint32_t baudrate  = uart_config->baudrate;
3191738838cSMatthias Ringwald     const int flowcontrol    = uart_config->flowcontrol;
3201738838cSMatthias Ringwald     const int parity         = uart_config->parity;
321f2cb8f20SMatthias Ringwald 
322f2cb8f20SMatthias Ringwald     struct termios toptions;
323f2cb8f20SMatthias Ringwald     int flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
324f2cb8f20SMatthias Ringwald     int fd = open(device_name, flags);
325f2cb8f20SMatthias Ringwald     if (fd == -1)  {
326f2cb8f20SMatthias Ringwald         log_error("Unable to open port %s", device_name);
327f2cb8f20SMatthias Ringwald         return -1;
328f2cb8f20SMatthias Ringwald     }
329f2cb8f20SMatthias Ringwald 
330f2cb8f20SMatthias Ringwald     if (tcgetattr(fd, &toptions) < 0) {
331f2cb8f20SMatthias Ringwald         log_error("Couldn't get term attributes");
332f2cb8f20SMatthias Ringwald         return -1;
333f2cb8f20SMatthias Ringwald     }
334f2cb8f20SMatthias Ringwald 
335f2cb8f20SMatthias Ringwald     cfmakeraw(&toptions);   // make raw
336f2cb8f20SMatthias Ringwald 
337f2cb8f20SMatthias Ringwald     // 8N1
338f2cb8f20SMatthias Ringwald     toptions.c_cflag &= ~CSTOPB;
339f2cb8f20SMatthias Ringwald     toptions.c_cflag |= CS8;
340f2cb8f20SMatthias Ringwald 
341f2cb8f20SMatthias Ringwald     toptions.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
342f2cb8f20SMatthias Ringwald     toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
343f2cb8f20SMatthias Ringwald 
344f2cb8f20SMatthias Ringwald     // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
345f2cb8f20SMatthias Ringwald     toptions.c_cc[VMIN]  = 1;
346f2cb8f20SMatthias Ringwald     toptions.c_cc[VTIME] = 0;
347f2cb8f20SMatthias Ringwald 
348f2cb8f20SMatthias Ringwald     // no parity
3491738838cSMatthias Ringwald     btstack_uart_posix_set_parity_option(&toptions, parity);
350f2cb8f20SMatthias Ringwald 
351f2cb8f20SMatthias Ringwald     // flowcontrol
352f2cb8f20SMatthias Ringwald     btstack_uart_posix_set_flowcontrol_option(&toptions, flowcontrol);
353f2cb8f20SMatthias Ringwald 
354f2cb8f20SMatthias Ringwald     if(tcsetattr(fd, TCSANOW, &toptions) < 0) {
355f2cb8f20SMatthias Ringwald         log_error("Couldn't set term attributes");
356f2cb8f20SMatthias Ringwald         return -1;
357f2cb8f20SMatthias Ringwald     }
358f2cb8f20SMatthias Ringwald 
359f2cb8f20SMatthias Ringwald     // store fd in data source
360f2cb8f20SMatthias Ringwald     transport_data_source.source.fd = fd;
361f2cb8f20SMatthias Ringwald 
362f2cb8f20SMatthias Ringwald     // also set baudrate
363f2cb8f20SMatthias Ringwald     if (btstack_uart_posix_set_baudrate(baudrate) < 0){
364f2cb8f20SMatthias Ringwald         return -1;
365f2cb8f20SMatthias Ringwald     }
366f2cb8f20SMatthias Ringwald 
367f2cb8f20SMatthias Ringwald     // set up data_source
368f2cb8f20SMatthias Ringwald     btstack_run_loop_set_data_source_fd(&transport_data_source, fd);
369f2cb8f20SMatthias Ringwald     btstack_run_loop_set_data_source_handler(&transport_data_source, &hci_uart_posix_process);
370f2cb8f20SMatthias Ringwald     btstack_run_loop_add_data_source(&transport_data_source);
371f2cb8f20SMatthias Ringwald 
372f2cb8f20SMatthias Ringwald     // wait a bit - at least cheap FTDI232 clones might send the first byte out incorrectly
373f2cb8f20SMatthias Ringwald     usleep(100000);
374f2cb8f20SMatthias Ringwald 
375f2cb8f20SMatthias Ringwald     return 0;
376f2cb8f20SMatthias Ringwald }
377f2cb8f20SMatthias Ringwald 
378f2cb8f20SMatthias Ringwald static int btstack_uart_posix_close_new(void){
379f2cb8f20SMatthias Ringwald 
380f2cb8f20SMatthias Ringwald     // first remove run loop handler
381f2cb8f20SMatthias Ringwald     btstack_run_loop_remove_data_source(&transport_data_source);
382f2cb8f20SMatthias Ringwald 
383f2cb8f20SMatthias Ringwald     // then close device
384f2cb8f20SMatthias Ringwald     close(transport_data_source.source.fd);
385f2cb8f20SMatthias Ringwald     transport_data_source.source.fd = -1;
386f2cb8f20SMatthias Ringwald     return 0;
387f2cb8f20SMatthias Ringwald }
388f2cb8f20SMatthias Ringwald 
389f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_block_received( void (*block_handler)(void)){
390f2cb8f20SMatthias Ringwald     block_received = block_handler;
391f2cb8f20SMatthias Ringwald }
392f2cb8f20SMatthias Ringwald 
393f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_block_sent( void (*block_handler)(void)){
394f2cb8f20SMatthias Ringwald     block_sent = block_handler;
395f2cb8f20SMatthias Ringwald }
396f2cb8f20SMatthias Ringwald 
397f2cb8f20SMatthias Ringwald static void btstack_uart_posix_send_block(const uint8_t *data, uint16_t size){
398f2cb8f20SMatthias Ringwald     // setup async write
399f2cb8f20SMatthias Ringwald     btstack_uart_block_write_bytes_data = data;
400f2cb8f20SMatthias Ringwald     btstack_uart_block_write_bytes_len  = size;
401f2cb8f20SMatthias Ringwald     btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE);
402f2cb8f20SMatthias Ringwald }
403f2cb8f20SMatthias Ringwald 
404f2cb8f20SMatthias Ringwald static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len){
405f2cb8f20SMatthias Ringwald     btstack_uart_block_read_bytes_data = buffer;
406f2cb8f20SMatthias Ringwald     btstack_uart_block_read_bytes_len = len;
407f2cb8f20SMatthias Ringwald     btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
408f2cb8f20SMatthias Ringwald }
409f2cb8f20SMatthias Ringwald 
410f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5
411f2cb8f20SMatthias Ringwald 
412f2cb8f20SMatthias Ringwald // SLIP Implementation Start
413f2cb8f20SMatthias Ringwald #include "btstack_slip.h"
414f2cb8f20SMatthias Ringwald 
415f2cb8f20SMatthias Ringwald // max size of outgoing SLIP chunks
416f2cb8f20SMatthias Ringwald #define SLIP_TX_CHUNK_LEN   128
417f2cb8f20SMatthias Ringwald 
418f2cb8f20SMatthias Ringwald #define SLIP_RECEIVE_BUFFER_SIZE 128
419f2cb8f20SMatthias Ringwald 
420f2cb8f20SMatthias Ringwald // encoded SLIP chunk
421f2cb8f20SMatthias Ringwald static uint8_t   btstack_uart_slip_outgoing_buffer[SLIP_TX_CHUNK_LEN+1];
422f2cb8f20SMatthias Ringwald 
423f2cb8f20SMatthias Ringwald // block write
424f2cb8f20SMatthias Ringwald static int             btstack_uart_slip_write_bytes_len;
425f2cb8f20SMatthias Ringwald static const uint8_t * btstack_uart_slip_write_bytes_data;
426f2cb8f20SMatthias Ringwald static int             btstack_uart_slip_write_active;
427f2cb8f20SMatthias Ringwald 
428f2cb8f20SMatthias Ringwald // block read
429f2cb8f20SMatthias Ringwald static uint8_t         btstack_uart_slip_receive_buffer[SLIP_RECEIVE_BUFFER_SIZE];
430f2cb8f20SMatthias Ringwald static uint16_t        btstack_uart_slip_receive_pos;
431f2cb8f20SMatthias Ringwald static uint16_t        btstack_uart_slip_receive_len;
432f2cb8f20SMatthias Ringwald static uint8_t         btstack_uart_slip_receive_track_start;
433f2cb8f20SMatthias Ringwald static uint32_t        btstack_uart_slip_receive_start_time;
434f2cb8f20SMatthias Ringwald static int             btstack_uart_slip_receive_active;
435f2cb8f20SMatthias Ringwald 
436f2cb8f20SMatthias Ringwald // callbacks
437f2cb8f20SMatthias Ringwald static void (*frame_sent)(void);
438f2cb8f20SMatthias Ringwald static void (*frame_received)(uint16_t frame_size);
439f2cb8f20SMatthias Ringwald 
440f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_block_sent(void);
441f2cb8f20SMatthias Ringwald 
442f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_process_write(btstack_data_source_t *ds) {
443f2cb8f20SMatthias Ringwald 
444f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_write_bytes_len == 0) return;
445f2cb8f20SMatthias Ringwald 
446f2cb8f20SMatthias Ringwald     uint32_t start = btstack_run_loop_get_time_ms();
447f2cb8f20SMatthias Ringwald 
448f2cb8f20SMatthias Ringwald     // write up to btstack_uart_slip_write_bytes_len to fd
449f2cb8f20SMatthias Ringwald     int bytes_written = (int) write(ds->source.fd, btstack_uart_slip_write_bytes_data, btstack_uart_slip_write_bytes_len);
450f2cb8f20SMatthias Ringwald     if (bytes_written < 0) {
451f2cb8f20SMatthias Ringwald         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
452f2cb8f20SMatthias Ringwald         return;
453f2cb8f20SMatthias Ringwald     }
454f2cb8f20SMatthias Ringwald 
455f2cb8f20SMatthias Ringwald     uint32_t end = btstack_run_loop_get_time_ms();
456f2cb8f20SMatthias Ringwald     if (end - start > 10){
457f2cb8f20SMatthias Ringwald         log_info("write took %u ms", end - start);
458f2cb8f20SMatthias Ringwald     }
459f2cb8f20SMatthias Ringwald 
460f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_bytes_data += bytes_written;
461f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_bytes_len  -= bytes_written;
462f2cb8f20SMatthias Ringwald 
463f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_write_bytes_len){
464f2cb8f20SMatthias Ringwald         btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
465f2cb8f20SMatthias Ringwald         return;
466f2cb8f20SMatthias Ringwald     }
467f2cb8f20SMatthias Ringwald 
468f2cb8f20SMatthias Ringwald     btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE);
469f2cb8f20SMatthias Ringwald 
470f2cb8f20SMatthias Ringwald     // done with TX chunk
471f2cb8f20SMatthias Ringwald     btstack_uart_slip_posix_block_sent();
472f2cb8f20SMatthias Ringwald }
473f2cb8f20SMatthias Ringwald 
474f2cb8f20SMatthias Ringwald // @returns frame size if complete frame decoded and delivered
475f2cb8f20SMatthias Ringwald static uint16_t btstack_uart_slip_posix_process_buffer(void){
476f2cb8f20SMatthias Ringwald     log_debug("process buffer: pos %u, len %u", btstack_uart_slip_receive_pos, btstack_uart_slip_receive_len);
477f2cb8f20SMatthias Ringwald 
478f2cb8f20SMatthias Ringwald     uint16_t frame_size = 0;
479f2cb8f20SMatthias Ringwald     while (btstack_uart_slip_receive_pos < btstack_uart_slip_receive_len && frame_size == 0){
480f2cb8f20SMatthias Ringwald         btstack_slip_decoder_process(btstack_uart_slip_receive_buffer[btstack_uart_slip_receive_pos++]);
481f2cb8f20SMatthias Ringwald         frame_size = btstack_slip_decoder_frame_size();
482f2cb8f20SMatthias Ringwald     }
483f2cb8f20SMatthias Ringwald 
484f2cb8f20SMatthias Ringwald     // reset buffer if fully processed
485f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_receive_pos == btstack_uart_slip_receive_len ){
486f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_len = 0;
487f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_pos = 0;
488f2cb8f20SMatthias Ringwald     }
489f2cb8f20SMatthias Ringwald 
490f2cb8f20SMatthias Ringwald     // deliver frame if frame complete
491f2cb8f20SMatthias Ringwald     if (frame_size) {
492f2cb8f20SMatthias Ringwald 
493f2cb8f20SMatthias Ringwald         // receive done
494f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_active = 0;
495f2cb8f20SMatthias Ringwald 
496f2cb8f20SMatthias Ringwald         // only print if read was involved
497f2cb8f20SMatthias Ringwald         if (btstack_uart_slip_receive_track_start == 0){
498f2cb8f20SMatthias Ringwald             log_info("frame receive time %u ms", btstack_run_loop_get_time_ms() - btstack_uart_slip_receive_start_time);
499f2cb8f20SMatthias Ringwald             btstack_uart_slip_receive_start_time = 0;
500f2cb8f20SMatthias Ringwald         }
501f2cb8f20SMatthias Ringwald 
502f2cb8f20SMatthias Ringwald         (*frame_received)(frame_size);
503f2cb8f20SMatthias Ringwald     }
504f2cb8f20SMatthias Ringwald 
505f2cb8f20SMatthias Ringwald     return frame_size;
506f2cb8f20SMatthias Ringwald }
507f2cb8f20SMatthias Ringwald 
508f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_process_read(btstack_data_source_t *ds) {
509f2cb8f20SMatthias Ringwald 
510f2cb8f20SMatthias Ringwald     uint32_t start = btstack_run_loop_get_time_ms();
511f2cb8f20SMatthias Ringwald 
512f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_receive_track_start){
513f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_track_start = 0;
514f2cb8f20SMatthias Ringwald         btstack_uart_slip_receive_start_time = start;
515f2cb8f20SMatthias Ringwald     }
516f2cb8f20SMatthias Ringwald 
517f2cb8f20SMatthias Ringwald     // read up to bytes_to_read data in
518f2cb8f20SMatthias Ringwald     ssize_t bytes_read = read(ds->source.fd, btstack_uart_slip_receive_buffer, SLIP_RECEIVE_BUFFER_SIZE);
519f2cb8f20SMatthias Ringwald 
520f2cb8f20SMatthias Ringwald     log_debug("requested %u bytes, got %d", SLIP_RECEIVE_BUFFER_SIZE, (int) bytes_read);
521f2cb8f20SMatthias Ringwald     uint32_t end = btstack_run_loop_get_time_ms();
522f2cb8f20SMatthias Ringwald     if (end - start > 10){
523f2cb8f20SMatthias Ringwald         log_info("read took %u ms", end - start);
524f2cb8f20SMatthias Ringwald     }
525f2cb8f20SMatthias Ringwald     if (bytes_read < 0) return;
526f2cb8f20SMatthias Ringwald 
527f2cb8f20SMatthias Ringwald     btstack_uart_slip_receive_pos = 0;
528f2cb8f20SMatthias Ringwald     btstack_uart_slip_receive_len = (uint16_t ) bytes_read;
529f2cb8f20SMatthias Ringwald 
530f2cb8f20SMatthias Ringwald     btstack_uart_slip_posix_process_buffer();
531f2cb8f20SMatthias Ringwald }
532f2cb8f20SMatthias Ringwald 
533f2cb8f20SMatthias Ringwald // -----------------------------
534f2cb8f20SMatthias Ringwald // SLIP ENCODING
535f2cb8f20SMatthias Ringwald 
536f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_encode_chunk_and_send(void){
537f2cb8f20SMatthias Ringwald     uint16_t pos = 0;
538f2cb8f20SMatthias Ringwald     while (btstack_slip_encoder_has_data() & (pos < SLIP_TX_CHUNK_LEN)) {
539f2cb8f20SMatthias Ringwald         btstack_uart_slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte();
540f2cb8f20SMatthias Ringwald     }
541f2cb8f20SMatthias Ringwald 
542f2cb8f20SMatthias Ringwald     // setup async write and start sending
543f2cb8f20SMatthias Ringwald     log_debug("slip: send %d bytes", pos);
544f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_bytes_data = btstack_uart_slip_outgoing_buffer;
545f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_bytes_len  = pos;
546f2cb8f20SMatthias Ringwald     btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE);
547f2cb8f20SMatthias Ringwald }
548f2cb8f20SMatthias Ringwald 
549f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_block_sent(void){
550f2cb8f20SMatthias Ringwald     // check if more data to send
551f2cb8f20SMatthias Ringwald     if (btstack_slip_encoder_has_data()){
552f2cb8f20SMatthias Ringwald         btstack_uart_slip_posix_encode_chunk_and_send();
553f2cb8f20SMatthias Ringwald         return;
554f2cb8f20SMatthias Ringwald     }
555f2cb8f20SMatthias Ringwald 
556f2cb8f20SMatthias Ringwald     // write done
557f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_active = 0;
558f2cb8f20SMatthias Ringwald 
559f2cb8f20SMatthias Ringwald     // notify done
560f2cb8f20SMatthias Ringwald     if (frame_sent){
561f2cb8f20SMatthias Ringwald         frame_sent();
562f2cb8f20SMatthias Ringwald     }
563f2cb8f20SMatthias Ringwald }
564f2cb8f20SMatthias Ringwald 
565f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_send_frame(const uint8_t * frame, uint16_t frame_size){
566f2cb8f20SMatthias Ringwald 
567f2cb8f20SMatthias Ringwald     // write started
568f2cb8f20SMatthias Ringwald     btstack_uart_slip_write_active = 1;
569f2cb8f20SMatthias Ringwald 
570f2cb8f20SMatthias Ringwald     // Prepare encoding of Header + Packet (+ DIC)
571f2cb8f20SMatthias Ringwald     btstack_slip_encoder_start(frame, frame_size);
572f2cb8f20SMatthias Ringwald 
573f2cb8f20SMatthias Ringwald     // Fill rest of chunk from packet and send
574f2cb8f20SMatthias Ringwald     btstack_uart_slip_posix_encode_chunk_and_send();
575f2cb8f20SMatthias Ringwald }
576f2cb8f20SMatthias Ringwald 
577f2cb8f20SMatthias Ringwald // SLIP ENCODING
578f2cb8f20SMatthias Ringwald // -----------------------------
579f2cb8f20SMatthias Ringwald 
580f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_receive_frame(uint8_t *buffer, uint16_t len){
581f2cb8f20SMatthias Ringwald 
582f2cb8f20SMatthias Ringwald     // receive started
583f2cb8f20SMatthias Ringwald     btstack_uart_slip_receive_active = 1;
584f2cb8f20SMatthias Ringwald 
585f2cb8f20SMatthias Ringwald     log_debug("receive block, size %u", len);
586f2cb8f20SMatthias Ringwald     btstack_uart_slip_receive_track_start = 1;
587f2cb8f20SMatthias Ringwald 
588f2cb8f20SMatthias Ringwald     // setup SLIP decoder
589f2cb8f20SMatthias Ringwald     btstack_slip_decoder_init(buffer, len);
590f2cb8f20SMatthias Ringwald 
591f2cb8f20SMatthias Ringwald     // process bytes received in earlier read. might deliver packet, which in turn will call us again.
592f2cb8f20SMatthias Ringwald     // just make sure to exit right away
593f2cb8f20SMatthias Ringwald     if (btstack_uart_slip_receive_len){
594f2cb8f20SMatthias Ringwald         int frame_found = btstack_uart_slip_posix_process_buffer();
595f2cb8f20SMatthias Ringwald         if (frame_found) return;
596f2cb8f20SMatthias Ringwald     }
597f2cb8f20SMatthias Ringwald 
598f2cb8f20SMatthias Ringwald     // no frame delivered, enable posix read
599f2cb8f20SMatthias Ringwald     btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ);
600f2cb8f20SMatthias Ringwald }
601f2cb8f20SMatthias Ringwald 
602f2cb8f20SMatthias Ringwald 
603f2cb8f20SMatthias Ringwald 
604f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_set_frame_received( void (*block_handler)(uint16_t frame_size)){
605f2cb8f20SMatthias Ringwald     frame_received = block_handler;
606f2cb8f20SMatthias Ringwald }
607f2cb8f20SMatthias Ringwald 
608f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_set_frame_sent( void (*block_handler)(void)){
609f2cb8f20SMatthias Ringwald     frame_sent = block_handler;
610f2cb8f20SMatthias Ringwald }
611f2cb8f20SMatthias Ringwald 
612f2cb8f20SMatthias Ringwald // SLIP Implementation End
613f2cb8f20SMatthias Ringwald #endif
614f2cb8f20SMatthias Ringwald 
615f2cb8f20SMatthias Ringwald // dispatch into block or SLIP code
616f2cb8f20SMatthias Ringwald static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
617f2cb8f20SMatthias Ringwald     if (ds->source.fd < 0) return;
618f2cb8f20SMatthias Ringwald     switch (callback_type){
619f2cb8f20SMatthias Ringwald         case DATA_SOURCE_CALLBACK_READ:
620f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5
621f2cb8f20SMatthias Ringwald             if (btstack_uart_slip_receive_active){
622f2cb8f20SMatthias Ringwald                 btstack_uart_slip_posix_process_read(ds);
623f2cb8f20SMatthias Ringwald             } else
624f2cb8f20SMatthias Ringwald #endif
625f2cb8f20SMatthias Ringwald             {
626f2cb8f20SMatthias Ringwald                 btstack_uart_block_posix_process_read(ds);
627f2cb8f20SMatthias Ringwald             }
628f2cb8f20SMatthias Ringwald             break;
629f2cb8f20SMatthias Ringwald         case DATA_SOURCE_CALLBACK_WRITE:
630f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5
631f2cb8f20SMatthias Ringwald             if (btstack_uart_slip_write_active){
632f2cb8f20SMatthias Ringwald                 btstack_uart_slip_posix_process_write(ds);
633f2cb8f20SMatthias Ringwald             } else
634f2cb8f20SMatthias Ringwald #endif
635f2cb8f20SMatthias Ringwald             {
636f2cb8f20SMatthias Ringwald                 btstack_uart_block_posix_process_write(ds);
637f2cb8f20SMatthias Ringwald             }
638f2cb8f20SMatthias Ringwald             break;
639f2cb8f20SMatthias Ringwald         default:
640f2cb8f20SMatthias Ringwald             break;
641f2cb8f20SMatthias Ringwald     }
642f2cb8f20SMatthias Ringwald }
643f2cb8f20SMatthias Ringwald 
644f2cb8f20SMatthias Ringwald static const btstack_uart_t btstack_uart_posix = {
645f2cb8f20SMatthias Ringwald     /* int  (*init)(hci_transport_config_uart_t * config); */              &btstack_uart_posix_init,
646f2cb8f20SMatthias Ringwald     /* int  (*open)(void); */                                              &btstack_uart_posix_open,
647f2cb8f20SMatthias Ringwald     /* int  (*close)(void); */                                             &btstack_uart_posix_close_new,
648f2cb8f20SMatthias Ringwald     /* void (*set_block_received)(void (*handler)(void)); */               &btstack_uart_posix_set_block_received,
649f2cb8f20SMatthias Ringwald     /* void (*set_block_sent)(void (*handler)(void)); */                   &btstack_uart_posix_set_block_sent,
650f2cb8f20SMatthias Ringwald     /* int  (*set_baudrate)(uint32_t baudrate); */                         &btstack_uart_posix_set_baudrate,
651f2cb8f20SMatthias Ringwald     /* int  (*set_parity)(int parity); */                                  &btstack_uart_posix_set_parity,
652f2cb8f20SMatthias Ringwald     /* int  (*set_flowcontrol)(int flowcontrol); */                        &btstack_uart_posix_set_flowcontrol,
653f2cb8f20SMatthias Ringwald     /* void (*receive_block)(uint8_t *buffer, uint16_t len); */            &btstack_uart_posix_receive_block,
654f2cb8f20SMatthias Ringwald     /* void (*send_block)(const uint8_t *buffer, uint16_t length); */      &btstack_uart_posix_send_block,
655f2cb8f20SMatthias Ringwald     /* int (*get_supported_sleep_modes); */                                NULL,
656f2cb8f20SMatthias Ringwald     /* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */         NULL,
657f2cb8f20SMatthias Ringwald     /* void (*set_wakeup_handler)(void (*handler)(void)); */               NULL,
658f2cb8f20SMatthias Ringwald 
659f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5
660f2cb8f20SMatthias Ringwald     /* void (*set_frame_received)(void (*handler)(uint16_t frame_size); */ &btstack_uart_slip_posix_set_frame_received,
661f2cb8f20SMatthias Ringwald     /* void (*set_fraae_sent)(void (*handler)(void)); */                   &btstack_uart_slip_posix_set_frame_sent,
662f2cb8f20SMatthias Ringwald     /* void (*receive_frame)(uint8_t *buffer, uint16_t len); */            &btstack_uart_slip_posix_receive_frame,
663f2cb8f20SMatthias Ringwald     /* void (*send_frame)(const uint8_t *buffer, uint16_t length); */      &btstack_uart_slip_posix_send_frame,
664f2cb8f20SMatthias Ringwald #else
665f2cb8f20SMatthias Ringwald     NULL, NULL, NULL, NULL,
666f2cb8f20SMatthias Ringwald #endif
667f2cb8f20SMatthias Ringwald };
668f2cb8f20SMatthias Ringwald 
669f2cb8f20SMatthias Ringwald const btstack_uart_t * btstack_uart_posix_instance(void){
670f2cb8f20SMatthias Ringwald 	return &btstack_uart_posix;
671f2cb8f20SMatthias Ringwald }
672