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