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