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 64*4437baf6SMatthias Ringwald // on macOS 12.1, CTS/RTS control flags are always read back as zero. 65*4437baf6SMatthias Ringwald // To work around this, we cache our terios settings 66*4437baf6SMatthias Ringwald struct termios btstack_uart_block_termios; 67*4437baf6SMatthias 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 } 223*4437baf6SMatthias Ringwald cfsetospeed(&btstack_uart_block_termios, brate); 224*4437baf6SMatthias 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 230*4437baf6SMatthias 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; 283*4437baf6SMatthias Ringwald btstack_uart_posix_set_parity_option(&btstack_uart_block_termios, parity); 284*4437baf6SMatthias Ringwald printf("set parity %lx", btstack_uart_block_termios.c_cflag); 285*4437baf6SMatthias 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 293f2cb8f20SMatthias Ringwald static int btstack_uart_posix_set_flowcontrol(int flowcontrol){ 294f2cb8f20SMatthias Ringwald int fd = transport_data_source.source.fd; 295*4437baf6SMatthias Ringwald btstack_uart_posix_set_flowcontrol_option(&btstack_uart_block_termios, flowcontrol); 296*4437baf6SMatthias Ringwald printf("set flow %lx", btstack_uart_block_termios.c_cflag); 297*4437baf6SMatthias Ringwald if(tcsetattr(fd, TCSANOW, &btstack_uart_block_termios) < 0) { 298f2cb8f20SMatthias Ringwald log_error("Couldn't set term attributes"); 299f2cb8f20SMatthias Ringwald return -1; 300f2cb8f20SMatthias Ringwald } 301f2cb8f20SMatthias Ringwald return 0; 302f2cb8f20SMatthias Ringwald } 303f2cb8f20SMatthias Ringwald 304f2cb8f20SMatthias Ringwald static int btstack_uart_posix_open(void){ 305f2cb8f20SMatthias Ringwald 306f2cb8f20SMatthias Ringwald const char * device_name = uart_config->device_name; 307f2cb8f20SMatthias Ringwald const uint32_t baudrate = uart_config->baudrate; 3081738838cSMatthias Ringwald const int flowcontrol = uart_config->flowcontrol; 3091738838cSMatthias Ringwald const int parity = uart_config->parity; 310f2cb8f20SMatthias Ringwald 311f2cb8f20SMatthias Ringwald int flags = O_RDWR | O_NOCTTY | O_NONBLOCK; 312f2cb8f20SMatthias Ringwald int fd = open(device_name, flags); 313f2cb8f20SMatthias Ringwald if (fd == -1) { 314f2cb8f20SMatthias Ringwald log_error("Unable to open port %s", device_name); 315f2cb8f20SMatthias Ringwald return -1; 316f2cb8f20SMatthias Ringwald } 317f2cb8f20SMatthias Ringwald 318*4437baf6SMatthias Ringwald if (tcgetattr(fd, &btstack_uart_block_termios) < 0) { 319f2cb8f20SMatthias Ringwald log_error("Couldn't get term attributes"); 320f2cb8f20SMatthias Ringwald return -1; 321f2cb8f20SMatthias Ringwald } 322*4437baf6SMatthias Ringwald cfmakeraw(&btstack_uart_block_termios); // make raw 323f2cb8f20SMatthias Ringwald 324f2cb8f20SMatthias Ringwald // 8N1 325*4437baf6SMatthias Ringwald btstack_uart_block_termios.c_cflag &= ~CSTOPB; 326*4437baf6SMatthias Ringwald btstack_uart_block_termios.c_cflag |= CS8; 327f2cb8f20SMatthias Ringwald 328*4437baf6SMatthias Ringwald btstack_uart_block_termios.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines 329*4437baf6SMatthias Ringwald btstack_uart_block_termios.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl 330f2cb8f20SMatthias Ringwald 331f2cb8f20SMatthias Ringwald // see: http://unixwiz.net/techtips/termios-vmin-vtime.html 332*4437baf6SMatthias Ringwald btstack_uart_block_termios.c_cc[VMIN] = 1; 333*4437baf6SMatthias Ringwald btstack_uart_block_termios.c_cc[VTIME] = 0; 334f2cb8f20SMatthias Ringwald 335f2cb8f20SMatthias Ringwald // no parity 336*4437baf6SMatthias Ringwald btstack_uart_posix_set_parity_option(&btstack_uart_block_termios, parity); 337f2cb8f20SMatthias Ringwald 338f2cb8f20SMatthias Ringwald // flowcontrol 339*4437baf6SMatthias Ringwald btstack_uart_posix_set_flowcontrol_option(&btstack_uart_block_termios, flowcontrol); 340f2cb8f20SMatthias Ringwald 341*4437baf6SMatthias Ringwald printf("init %lx", btstack_uart_block_termios.c_cflag); 342*4437baf6SMatthias Ringwald 343*4437baf6SMatthias Ringwald if(tcsetattr(fd, TCSANOW, &btstack_uart_block_termios) < 0) { 344f2cb8f20SMatthias Ringwald log_error("Couldn't set term attributes"); 345f2cb8f20SMatthias Ringwald return -1; 346f2cb8f20SMatthias Ringwald } 347f2cb8f20SMatthias Ringwald 348f2cb8f20SMatthias Ringwald // store fd in data source 349f2cb8f20SMatthias Ringwald transport_data_source.source.fd = fd; 350f2cb8f20SMatthias Ringwald 351f2cb8f20SMatthias Ringwald // also set baudrate 352f2cb8f20SMatthias Ringwald if (btstack_uart_posix_set_baudrate(baudrate) < 0){ 353f2cb8f20SMatthias Ringwald return -1; 354f2cb8f20SMatthias Ringwald } 355f2cb8f20SMatthias Ringwald 356f2cb8f20SMatthias Ringwald // set up data_source 357f2cb8f20SMatthias Ringwald btstack_run_loop_set_data_source_fd(&transport_data_source, fd); 358f2cb8f20SMatthias Ringwald btstack_run_loop_set_data_source_handler(&transport_data_source, &hci_uart_posix_process); 359f2cb8f20SMatthias Ringwald btstack_run_loop_add_data_source(&transport_data_source); 360f2cb8f20SMatthias Ringwald 361f2cb8f20SMatthias Ringwald // wait a bit - at least cheap FTDI232 clones might send the first byte out incorrectly 362f2cb8f20SMatthias Ringwald usleep(100000); 363f2cb8f20SMatthias Ringwald 364f2cb8f20SMatthias Ringwald return 0; 365f2cb8f20SMatthias Ringwald } 366f2cb8f20SMatthias Ringwald 367f2cb8f20SMatthias Ringwald static int btstack_uart_posix_close_new(void){ 368f2cb8f20SMatthias Ringwald 369f2cb8f20SMatthias Ringwald // first remove run loop handler 370f2cb8f20SMatthias Ringwald btstack_run_loop_remove_data_source(&transport_data_source); 371f2cb8f20SMatthias Ringwald 372f2cb8f20SMatthias Ringwald // then close device 373f2cb8f20SMatthias Ringwald close(transport_data_source.source.fd); 374f2cb8f20SMatthias Ringwald transport_data_source.source.fd = -1; 375f2cb8f20SMatthias Ringwald return 0; 376f2cb8f20SMatthias Ringwald } 377f2cb8f20SMatthias Ringwald 378f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_block_received( void (*block_handler)(void)){ 379f2cb8f20SMatthias Ringwald block_received = block_handler; 380f2cb8f20SMatthias Ringwald } 381f2cb8f20SMatthias Ringwald 382f2cb8f20SMatthias Ringwald static void btstack_uart_posix_set_block_sent( void (*block_handler)(void)){ 383f2cb8f20SMatthias Ringwald block_sent = block_handler; 384f2cb8f20SMatthias Ringwald } 385f2cb8f20SMatthias Ringwald 386f2cb8f20SMatthias Ringwald static void btstack_uart_posix_send_block(const uint8_t *data, uint16_t size){ 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){ 394f2cb8f20SMatthias Ringwald btstack_uart_block_read_bytes_data = buffer; 395f2cb8f20SMatthias Ringwald btstack_uart_block_read_bytes_len = len; 396f2cb8f20SMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ); 397f2cb8f20SMatthias Ringwald } 398f2cb8f20SMatthias Ringwald 399f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5 400f2cb8f20SMatthias Ringwald 401f2cb8f20SMatthias Ringwald // SLIP Implementation Start 402f2cb8f20SMatthias Ringwald #include "btstack_slip.h" 403f2cb8f20SMatthias Ringwald 404f2cb8f20SMatthias Ringwald // max size of outgoing SLIP chunks 405f2cb8f20SMatthias Ringwald #define SLIP_TX_CHUNK_LEN 128 406f2cb8f20SMatthias Ringwald 407f2cb8f20SMatthias Ringwald #define SLIP_RECEIVE_BUFFER_SIZE 128 408f2cb8f20SMatthias Ringwald 409f2cb8f20SMatthias Ringwald // encoded SLIP chunk 410f2cb8f20SMatthias Ringwald static uint8_t btstack_uart_slip_outgoing_buffer[SLIP_TX_CHUNK_LEN+1]; 411f2cb8f20SMatthias Ringwald 412f2cb8f20SMatthias Ringwald // block write 413f2cb8f20SMatthias Ringwald static int btstack_uart_slip_write_bytes_len; 414f2cb8f20SMatthias Ringwald static const uint8_t * btstack_uart_slip_write_bytes_data; 415f2cb8f20SMatthias Ringwald static int btstack_uart_slip_write_active; 416f2cb8f20SMatthias Ringwald 417f2cb8f20SMatthias Ringwald // block read 418f2cb8f20SMatthias Ringwald static uint8_t btstack_uart_slip_receive_buffer[SLIP_RECEIVE_BUFFER_SIZE]; 419f2cb8f20SMatthias Ringwald static uint16_t btstack_uart_slip_receive_pos; 420f2cb8f20SMatthias Ringwald static uint16_t btstack_uart_slip_receive_len; 421f2cb8f20SMatthias Ringwald static uint8_t btstack_uart_slip_receive_track_start; 422f2cb8f20SMatthias Ringwald static uint32_t btstack_uart_slip_receive_start_time; 423f2cb8f20SMatthias Ringwald static int btstack_uart_slip_receive_active; 424f2cb8f20SMatthias Ringwald 425f2cb8f20SMatthias Ringwald // callbacks 426f2cb8f20SMatthias Ringwald static void (*frame_sent)(void); 427f2cb8f20SMatthias Ringwald static void (*frame_received)(uint16_t frame_size); 428f2cb8f20SMatthias Ringwald 429f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_block_sent(void); 430f2cb8f20SMatthias Ringwald 431f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_process_write(btstack_data_source_t *ds) { 432f2cb8f20SMatthias Ringwald 433f2cb8f20SMatthias Ringwald if (btstack_uart_slip_write_bytes_len == 0) return; 434f2cb8f20SMatthias Ringwald 435f2cb8f20SMatthias Ringwald uint32_t start = btstack_run_loop_get_time_ms(); 436f2cb8f20SMatthias Ringwald 437f2cb8f20SMatthias Ringwald // write up to btstack_uart_slip_write_bytes_len to fd 438f2cb8f20SMatthias Ringwald int bytes_written = (int) write(ds->source.fd, btstack_uart_slip_write_bytes_data, btstack_uart_slip_write_bytes_len); 439f2cb8f20SMatthias Ringwald if (bytes_written < 0) { 440f2cb8f20SMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 441f2cb8f20SMatthias Ringwald return; 442f2cb8f20SMatthias Ringwald } 443f2cb8f20SMatthias Ringwald 444f2cb8f20SMatthias Ringwald uint32_t end = btstack_run_loop_get_time_ms(); 445f2cb8f20SMatthias Ringwald if (end - start > 10){ 446f2cb8f20SMatthias Ringwald log_info("write took %u ms", end - start); 447f2cb8f20SMatthias Ringwald } 448f2cb8f20SMatthias Ringwald 449f2cb8f20SMatthias Ringwald btstack_uart_slip_write_bytes_data += bytes_written; 450f2cb8f20SMatthias Ringwald btstack_uart_slip_write_bytes_len -= bytes_written; 451f2cb8f20SMatthias Ringwald 452f2cb8f20SMatthias Ringwald if (btstack_uart_slip_write_bytes_len){ 453f2cb8f20SMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 454f2cb8f20SMatthias Ringwald return; 455f2cb8f20SMatthias Ringwald } 456f2cb8f20SMatthias Ringwald 457f2cb8f20SMatthias Ringwald btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 458f2cb8f20SMatthias Ringwald 459f2cb8f20SMatthias Ringwald // done with TX chunk 460f2cb8f20SMatthias Ringwald btstack_uart_slip_posix_block_sent(); 461f2cb8f20SMatthias Ringwald } 462f2cb8f20SMatthias Ringwald 463f2cb8f20SMatthias Ringwald // @returns frame size if complete frame decoded and delivered 464f2cb8f20SMatthias Ringwald static uint16_t btstack_uart_slip_posix_process_buffer(void){ 465f2cb8f20SMatthias Ringwald log_debug("process buffer: pos %u, len %u", btstack_uart_slip_receive_pos, btstack_uart_slip_receive_len); 466f2cb8f20SMatthias Ringwald 467f2cb8f20SMatthias Ringwald uint16_t frame_size = 0; 468f2cb8f20SMatthias Ringwald while (btstack_uart_slip_receive_pos < btstack_uart_slip_receive_len && frame_size == 0){ 469f2cb8f20SMatthias Ringwald btstack_slip_decoder_process(btstack_uart_slip_receive_buffer[btstack_uart_slip_receive_pos++]); 470f2cb8f20SMatthias Ringwald frame_size = btstack_slip_decoder_frame_size(); 471f2cb8f20SMatthias Ringwald } 472f2cb8f20SMatthias Ringwald 473f2cb8f20SMatthias Ringwald // reset buffer if fully processed 474f2cb8f20SMatthias Ringwald if (btstack_uart_slip_receive_pos == btstack_uart_slip_receive_len ){ 475f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_len = 0; 476f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_pos = 0; 477f2cb8f20SMatthias Ringwald } 478f2cb8f20SMatthias Ringwald 479f2cb8f20SMatthias Ringwald // deliver frame if frame complete 480f2cb8f20SMatthias Ringwald if (frame_size) { 481f2cb8f20SMatthias Ringwald 482f2cb8f20SMatthias Ringwald // receive done 483f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_active = 0; 484f2cb8f20SMatthias Ringwald 485f2cb8f20SMatthias Ringwald // only print if read was involved 486f2cb8f20SMatthias Ringwald if (btstack_uart_slip_receive_track_start == 0){ 487f2cb8f20SMatthias Ringwald log_info("frame receive time %u ms", btstack_run_loop_get_time_ms() - btstack_uart_slip_receive_start_time); 488f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_start_time = 0; 489f2cb8f20SMatthias Ringwald } 490f2cb8f20SMatthias Ringwald 491f2cb8f20SMatthias Ringwald (*frame_received)(frame_size); 492f2cb8f20SMatthias Ringwald } 493f2cb8f20SMatthias Ringwald 494f2cb8f20SMatthias Ringwald return frame_size; 495f2cb8f20SMatthias Ringwald } 496f2cb8f20SMatthias Ringwald 497f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_process_read(btstack_data_source_t *ds) { 498f2cb8f20SMatthias Ringwald 499f2cb8f20SMatthias Ringwald uint32_t start = btstack_run_loop_get_time_ms(); 500f2cb8f20SMatthias Ringwald 501f2cb8f20SMatthias Ringwald if (btstack_uart_slip_receive_track_start){ 502f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_track_start = 0; 503f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_start_time = start; 504f2cb8f20SMatthias Ringwald } 505f2cb8f20SMatthias Ringwald 506f2cb8f20SMatthias Ringwald // read up to bytes_to_read data in 507f2cb8f20SMatthias Ringwald ssize_t bytes_read = read(ds->source.fd, btstack_uart_slip_receive_buffer, SLIP_RECEIVE_BUFFER_SIZE); 508f2cb8f20SMatthias Ringwald 509f2cb8f20SMatthias Ringwald log_debug("requested %u bytes, got %d", SLIP_RECEIVE_BUFFER_SIZE, (int) bytes_read); 510f2cb8f20SMatthias Ringwald uint32_t end = btstack_run_loop_get_time_ms(); 511f2cb8f20SMatthias Ringwald if (end - start > 10){ 512f2cb8f20SMatthias Ringwald log_info("read took %u ms", end - start); 513f2cb8f20SMatthias Ringwald } 514f2cb8f20SMatthias Ringwald if (bytes_read < 0) return; 515f2cb8f20SMatthias Ringwald 516f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_pos = 0; 517f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_len = (uint16_t ) bytes_read; 518f2cb8f20SMatthias Ringwald 519f2cb8f20SMatthias Ringwald btstack_uart_slip_posix_process_buffer(); 520f2cb8f20SMatthias Ringwald } 521f2cb8f20SMatthias Ringwald 522f2cb8f20SMatthias Ringwald // ----------------------------- 523f2cb8f20SMatthias Ringwald // SLIP ENCODING 524f2cb8f20SMatthias Ringwald 525f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_encode_chunk_and_send(void){ 526f2cb8f20SMatthias Ringwald uint16_t pos = 0; 527f2cb8f20SMatthias Ringwald while (btstack_slip_encoder_has_data() & (pos < SLIP_TX_CHUNK_LEN)) { 528f2cb8f20SMatthias Ringwald btstack_uart_slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte(); 529f2cb8f20SMatthias Ringwald } 530f2cb8f20SMatthias Ringwald 531f2cb8f20SMatthias Ringwald // setup async write and start sending 532f2cb8f20SMatthias Ringwald log_debug("slip: send %d bytes", pos); 533f2cb8f20SMatthias Ringwald btstack_uart_slip_write_bytes_data = btstack_uart_slip_outgoing_buffer; 534f2cb8f20SMatthias Ringwald btstack_uart_slip_write_bytes_len = pos; 535f2cb8f20SMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE); 536f2cb8f20SMatthias Ringwald } 537f2cb8f20SMatthias Ringwald 538f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_block_sent(void){ 539f2cb8f20SMatthias Ringwald // check if more data to send 540f2cb8f20SMatthias Ringwald if (btstack_slip_encoder_has_data()){ 541f2cb8f20SMatthias Ringwald btstack_uart_slip_posix_encode_chunk_and_send(); 542f2cb8f20SMatthias Ringwald return; 543f2cb8f20SMatthias Ringwald } 544f2cb8f20SMatthias Ringwald 545f2cb8f20SMatthias Ringwald // write done 546f2cb8f20SMatthias Ringwald btstack_uart_slip_write_active = 0; 547f2cb8f20SMatthias Ringwald 548f2cb8f20SMatthias Ringwald // notify done 549f2cb8f20SMatthias Ringwald if (frame_sent){ 550f2cb8f20SMatthias Ringwald frame_sent(); 551f2cb8f20SMatthias Ringwald } 552f2cb8f20SMatthias Ringwald } 553f2cb8f20SMatthias Ringwald 554f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_send_frame(const uint8_t * frame, uint16_t frame_size){ 555f2cb8f20SMatthias Ringwald 556f2cb8f20SMatthias Ringwald // write started 557f2cb8f20SMatthias Ringwald btstack_uart_slip_write_active = 1; 558f2cb8f20SMatthias Ringwald 559f2cb8f20SMatthias Ringwald // Prepare encoding of Header + Packet (+ DIC) 560f2cb8f20SMatthias Ringwald btstack_slip_encoder_start(frame, frame_size); 561f2cb8f20SMatthias Ringwald 562f2cb8f20SMatthias Ringwald // Fill rest of chunk from packet and send 563f2cb8f20SMatthias Ringwald btstack_uart_slip_posix_encode_chunk_and_send(); 564f2cb8f20SMatthias Ringwald } 565f2cb8f20SMatthias Ringwald 566f2cb8f20SMatthias Ringwald // SLIP ENCODING 567f2cb8f20SMatthias Ringwald // ----------------------------- 568f2cb8f20SMatthias Ringwald 569f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_receive_frame(uint8_t *buffer, uint16_t len){ 570f2cb8f20SMatthias Ringwald 571f2cb8f20SMatthias Ringwald // receive started 572f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_active = 1; 573f2cb8f20SMatthias Ringwald 574f2cb8f20SMatthias Ringwald log_debug("receive block, size %u", len); 575f2cb8f20SMatthias Ringwald btstack_uart_slip_receive_track_start = 1; 576f2cb8f20SMatthias Ringwald 577f2cb8f20SMatthias Ringwald // setup SLIP decoder 578f2cb8f20SMatthias Ringwald btstack_slip_decoder_init(buffer, len); 579f2cb8f20SMatthias Ringwald 580f2cb8f20SMatthias Ringwald // process bytes received in earlier read. might deliver packet, which in turn will call us again. 581f2cb8f20SMatthias Ringwald // just make sure to exit right away 582f2cb8f20SMatthias Ringwald if (btstack_uart_slip_receive_len){ 583f2cb8f20SMatthias Ringwald int frame_found = btstack_uart_slip_posix_process_buffer(); 584f2cb8f20SMatthias Ringwald if (frame_found) return; 585f2cb8f20SMatthias Ringwald } 586f2cb8f20SMatthias Ringwald 587f2cb8f20SMatthias Ringwald // no frame delivered, enable posix read 588f2cb8f20SMatthias Ringwald btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ); 589f2cb8f20SMatthias Ringwald } 590f2cb8f20SMatthias Ringwald 591f2cb8f20SMatthias Ringwald 592f2cb8f20SMatthias Ringwald 593f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_set_frame_received( void (*block_handler)(uint16_t frame_size)){ 594f2cb8f20SMatthias Ringwald frame_received = block_handler; 595f2cb8f20SMatthias Ringwald } 596f2cb8f20SMatthias Ringwald 597f2cb8f20SMatthias Ringwald static void btstack_uart_slip_posix_set_frame_sent( void (*block_handler)(void)){ 598f2cb8f20SMatthias Ringwald frame_sent = block_handler; 599f2cb8f20SMatthias Ringwald } 600f2cb8f20SMatthias Ringwald 601f2cb8f20SMatthias Ringwald // SLIP Implementation End 602f2cb8f20SMatthias Ringwald #endif 603f2cb8f20SMatthias Ringwald 604f2cb8f20SMatthias Ringwald // dispatch into block or SLIP code 605f2cb8f20SMatthias Ringwald static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { 606f2cb8f20SMatthias Ringwald if (ds->source.fd < 0) return; 607f2cb8f20SMatthias Ringwald switch (callback_type){ 608f2cb8f20SMatthias Ringwald case DATA_SOURCE_CALLBACK_READ: 609f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5 610f2cb8f20SMatthias Ringwald if (btstack_uart_slip_receive_active){ 611f2cb8f20SMatthias Ringwald btstack_uart_slip_posix_process_read(ds); 612f2cb8f20SMatthias Ringwald } else 613f2cb8f20SMatthias Ringwald #endif 614f2cb8f20SMatthias Ringwald { 615f2cb8f20SMatthias Ringwald btstack_uart_block_posix_process_read(ds); 616f2cb8f20SMatthias Ringwald } 617f2cb8f20SMatthias Ringwald break; 618f2cb8f20SMatthias Ringwald case DATA_SOURCE_CALLBACK_WRITE: 619f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5 620f2cb8f20SMatthias Ringwald if (btstack_uart_slip_write_active){ 621f2cb8f20SMatthias Ringwald btstack_uart_slip_posix_process_write(ds); 622f2cb8f20SMatthias Ringwald } else 623f2cb8f20SMatthias Ringwald #endif 624f2cb8f20SMatthias Ringwald { 625f2cb8f20SMatthias Ringwald btstack_uart_block_posix_process_write(ds); 626f2cb8f20SMatthias Ringwald } 627f2cb8f20SMatthias Ringwald break; 628f2cb8f20SMatthias Ringwald default: 629f2cb8f20SMatthias Ringwald break; 630f2cb8f20SMatthias Ringwald } 631f2cb8f20SMatthias Ringwald } 632f2cb8f20SMatthias Ringwald 633f2cb8f20SMatthias Ringwald static const btstack_uart_t btstack_uart_posix = { 634f2cb8f20SMatthias Ringwald /* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init, 635f2cb8f20SMatthias Ringwald /* int (*open)(void); */ &btstack_uart_posix_open, 636f2cb8f20SMatthias Ringwald /* int (*close)(void); */ &btstack_uart_posix_close_new, 637f2cb8f20SMatthias Ringwald /* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_posix_set_block_received, 638f2cb8f20SMatthias Ringwald /* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_posix_set_block_sent, 639f2cb8f20SMatthias Ringwald /* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate, 640f2cb8f20SMatthias Ringwald /* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity, 641f2cb8f20SMatthias Ringwald /* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_posix_set_flowcontrol, 642f2cb8f20SMatthias Ringwald /* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_posix_receive_block, 643f2cb8f20SMatthias Ringwald /* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block, 644f2cb8f20SMatthias Ringwald /* int (*get_supported_sleep_modes); */ NULL, 645f2cb8f20SMatthias Ringwald /* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL, 646f2cb8f20SMatthias Ringwald /* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL, 647f2cb8f20SMatthias Ringwald 648f2cb8f20SMatthias Ringwald #ifdef ENABLE_H5 649f2cb8f20SMatthias Ringwald /* void (*set_frame_received)(void (*handler)(uint16_t frame_size); */ &btstack_uart_slip_posix_set_frame_received, 650f2cb8f20SMatthias Ringwald /* void (*set_fraae_sent)(void (*handler)(void)); */ &btstack_uart_slip_posix_set_frame_sent, 651f2cb8f20SMatthias Ringwald /* void (*receive_frame)(uint8_t *buffer, uint16_t len); */ &btstack_uart_slip_posix_receive_frame, 652f2cb8f20SMatthias Ringwald /* void (*send_frame)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_slip_posix_send_frame, 653f2cb8f20SMatthias Ringwald #else 654f2cb8f20SMatthias Ringwald NULL, NULL, NULL, NULL, 655f2cb8f20SMatthias Ringwald #endif 656f2cb8f20SMatthias Ringwald }; 657f2cb8f20SMatthias Ringwald 658f2cb8f20SMatthias Ringwald const btstack_uart_t * btstack_uart_posix_instance(void){ 659f2cb8f20SMatthias Ringwald return &btstack_uart_posix; 660f2cb8f20SMatthias Ringwald } 661