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