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