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