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