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 block_received = block_handler; 376 } 377 378 static void btstack_uart_posix_set_block_sent( void (*block_handler)(void)){ 379 block_sent = block_handler; 380 } 381 382 static void btstack_uart_posix_send_block(const uint8_t *data, uint16_t size){ 383 btstack_assert(btstack_uart_block_write_bytes_len == 0); 384 385 // setup async write 386 btstack_uart_block_write_bytes_data = data; 387 btstack_uart_block_write_bytes_len = size; 388 btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE); 389 } 390 391 static void btstack_uart_posix_receive_block(uint8_t *buffer, uint16_t len){ 392 btstack_assert(btstack_uart_block_read_bytes_len == 0); 393 394 // setup async read 395 btstack_uart_block_read_bytes_data = buffer; 396 btstack_uart_block_read_bytes_len = len; 397 btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ); 398 } 399 400 #ifdef ENABLE_H5 401 402 // SLIP Implementation Start 403 #include "btstack_slip.h" 404 405 // max size of outgoing SLIP chunks 406 #define SLIP_TX_CHUNK_LEN 128 407 408 #define SLIP_RECEIVE_BUFFER_SIZE 128 409 410 // encoded SLIP chunk 411 static uint8_t btstack_uart_slip_outgoing_buffer[SLIP_TX_CHUNK_LEN+1]; 412 413 // block write 414 static int btstack_uart_slip_write_bytes_len; 415 static const uint8_t * btstack_uart_slip_write_bytes_data; 416 static int btstack_uart_slip_write_active; 417 418 // block read 419 static uint8_t btstack_uart_slip_receive_buffer[SLIP_RECEIVE_BUFFER_SIZE]; 420 static uint16_t btstack_uart_slip_receive_pos; 421 static uint16_t btstack_uart_slip_receive_len; 422 static uint8_t btstack_uart_slip_receive_track_start; 423 static uint32_t btstack_uart_slip_receive_start_time; 424 static int btstack_uart_slip_receive_active; 425 426 // callbacks 427 static void (*frame_sent)(void); 428 static void (*frame_received)(uint16_t frame_size); 429 430 static void btstack_uart_slip_posix_block_sent(void); 431 432 static void btstack_uart_slip_posix_process_write(btstack_data_source_t *ds) { 433 434 if (btstack_uart_slip_write_bytes_len == 0) return; 435 436 uint32_t start = btstack_run_loop_get_time_ms(); 437 438 // write up to btstack_uart_slip_write_bytes_len to fd 439 int bytes_written = (int) write(ds->source.fd, btstack_uart_slip_write_bytes_data, btstack_uart_slip_write_bytes_len); 440 if (bytes_written < 0) { 441 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 442 return; 443 } 444 445 uint32_t end = btstack_run_loop_get_time_ms(); 446 if (end - start > 10){ 447 log_info("write took %u ms", end - start); 448 } 449 450 btstack_uart_slip_write_bytes_data += bytes_written; 451 btstack_uart_slip_write_bytes_len -= bytes_written; 452 453 if (btstack_uart_slip_write_bytes_len){ 454 btstack_run_loop_enable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 455 return; 456 } 457 458 btstack_run_loop_disable_data_source_callbacks(ds, DATA_SOURCE_CALLBACK_WRITE); 459 460 // done with TX chunk 461 btstack_uart_slip_posix_block_sent(); 462 } 463 464 // @returns frame size if complete frame decoded and delivered 465 static uint16_t btstack_uart_slip_posix_process_buffer(void){ 466 log_debug("process buffer: pos %u, len %u", btstack_uart_slip_receive_pos, btstack_uart_slip_receive_len); 467 468 uint16_t frame_size = 0; 469 while (btstack_uart_slip_receive_pos < btstack_uart_slip_receive_len && frame_size == 0){ 470 btstack_slip_decoder_process(btstack_uart_slip_receive_buffer[btstack_uart_slip_receive_pos++]); 471 frame_size = btstack_slip_decoder_frame_size(); 472 } 473 474 // reset buffer if fully processed 475 if (btstack_uart_slip_receive_pos == btstack_uart_slip_receive_len ){ 476 btstack_uart_slip_receive_len = 0; 477 btstack_uart_slip_receive_pos = 0; 478 } 479 480 // deliver frame if frame complete 481 if (frame_size) { 482 483 // receive done 484 btstack_uart_slip_receive_active = 0; 485 486 // only print if read was involved 487 if (btstack_uart_slip_receive_track_start == 0){ 488 log_info("frame receive time %u ms", btstack_run_loop_get_time_ms() - btstack_uart_slip_receive_start_time); 489 btstack_uart_slip_receive_start_time = 0; 490 } 491 492 (*frame_received)(frame_size); 493 } 494 495 return frame_size; 496 } 497 498 static void btstack_uart_slip_posix_process_read(btstack_data_source_t *ds) { 499 500 uint32_t start = btstack_run_loop_get_time_ms(); 501 502 if (btstack_uart_slip_receive_track_start){ 503 btstack_uart_slip_receive_track_start = 0; 504 btstack_uart_slip_receive_start_time = start; 505 } 506 507 // read up to bytes_to_read data in 508 ssize_t bytes_read = read(ds->source.fd, btstack_uart_slip_receive_buffer, SLIP_RECEIVE_BUFFER_SIZE); 509 510 log_debug("requested %u bytes, got %d", SLIP_RECEIVE_BUFFER_SIZE, (int) bytes_read); 511 uint32_t end = btstack_run_loop_get_time_ms(); 512 if (end - start > 10){ 513 log_info("read took %u ms", end - start); 514 } 515 if (bytes_read < 0) return; 516 517 btstack_uart_slip_receive_pos = 0; 518 btstack_uart_slip_receive_len = (uint16_t ) bytes_read; 519 520 btstack_uart_slip_posix_process_buffer(); 521 } 522 523 // ----------------------------- 524 // SLIP ENCODING 525 526 static void btstack_uart_slip_posix_encode_chunk_and_send(void){ 527 uint16_t pos = 0; 528 while (btstack_slip_encoder_has_data() & (pos < SLIP_TX_CHUNK_LEN)) { 529 btstack_uart_slip_outgoing_buffer[pos++] = btstack_slip_encoder_get_byte(); 530 } 531 532 // setup async write and start sending 533 log_debug("slip: send %d bytes", pos); 534 btstack_uart_slip_write_bytes_data = btstack_uart_slip_outgoing_buffer; 535 btstack_uart_slip_write_bytes_len = pos; 536 btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_WRITE); 537 } 538 539 static void btstack_uart_slip_posix_block_sent(void){ 540 // check if more data to send 541 if (btstack_slip_encoder_has_data()){ 542 btstack_uart_slip_posix_encode_chunk_and_send(); 543 return; 544 } 545 546 // write done 547 btstack_uart_slip_write_active = 0; 548 549 // notify done 550 if (frame_sent){ 551 frame_sent(); 552 } 553 } 554 555 static void btstack_uart_slip_posix_send_frame(const uint8_t * frame, uint16_t frame_size){ 556 557 // write started 558 btstack_uart_slip_write_active = 1; 559 560 // Prepare encoding of Header + Packet (+ DIC) 561 btstack_slip_encoder_start(frame, frame_size); 562 563 // Fill rest of chunk from packet and send 564 btstack_uart_slip_posix_encode_chunk_and_send(); 565 } 566 567 // SLIP ENCODING 568 // ----------------------------- 569 570 static void btstack_uart_slip_posix_receive_frame(uint8_t *buffer, uint16_t len){ 571 572 // receive started 573 btstack_uart_slip_receive_active = 1; 574 575 log_debug("receive block, size %u", len); 576 btstack_uart_slip_receive_track_start = 1; 577 578 // setup SLIP decoder 579 btstack_slip_decoder_init(buffer, len); 580 581 // process bytes received in earlier read. might deliver packet, which in turn will call us again. 582 // just make sure to exit right away 583 if (btstack_uart_slip_receive_len){ 584 int frame_found = btstack_uart_slip_posix_process_buffer(); 585 if (frame_found) return; 586 } 587 588 // no frame delivered, enable posix read 589 btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_READ); 590 } 591 592 593 594 static void btstack_uart_slip_posix_set_frame_received( void (*block_handler)(uint16_t frame_size)){ 595 frame_received = block_handler; 596 } 597 598 static void btstack_uart_slip_posix_set_frame_sent( void (*block_handler)(void)){ 599 frame_sent = block_handler; 600 } 601 602 // SLIP Implementation End 603 #endif 604 605 // dispatch into block or SLIP code 606 static void hci_uart_posix_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) { 607 if (ds->source.fd < 0) return; 608 switch (callback_type){ 609 case DATA_SOURCE_CALLBACK_READ: 610 #ifdef ENABLE_H5 611 if (btstack_uart_slip_receive_active){ 612 btstack_uart_slip_posix_process_read(ds); 613 } else 614 #endif 615 { 616 btstack_uart_block_posix_process_read(ds); 617 } 618 break; 619 case DATA_SOURCE_CALLBACK_WRITE: 620 #ifdef ENABLE_H5 621 if (btstack_uart_slip_write_active){ 622 btstack_uart_slip_posix_process_write(ds); 623 } else 624 #endif 625 { 626 btstack_uart_block_posix_process_write(ds); 627 } 628 break; 629 default: 630 break; 631 } 632 } 633 634 static const btstack_uart_t btstack_uart_posix = { 635 /* int (*init)(hci_transport_config_uart_t * config); */ &btstack_uart_posix_init, 636 /* int (*open)(void); */ &btstack_uart_posix_open, 637 /* int (*close)(void); */ &btstack_uart_posix_close_new, 638 /* void (*set_block_received)(void (*handler)(void)); */ &btstack_uart_posix_set_block_received, 639 /* void (*set_block_sent)(void (*handler)(void)); */ &btstack_uart_posix_set_block_sent, 640 /* int (*set_baudrate)(uint32_t baudrate); */ &btstack_uart_posix_set_baudrate, 641 /* int (*set_parity)(int parity); */ &btstack_uart_posix_set_parity, 642 /* int (*set_flowcontrol)(int flowcontrol); */ &btstack_uart_posix_set_flowcontrol, 643 /* void (*receive_block)(uint8_t *buffer, uint16_t len); */ &btstack_uart_posix_receive_block, 644 /* void (*send_block)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_posix_send_block, 645 /* int (*get_supported_sleep_modes); */ NULL, 646 /* void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); */ NULL, 647 /* void (*set_wakeup_handler)(void (*handler)(void)); */ NULL, 648 649 #ifdef ENABLE_H5 650 /* void (*set_frame_received)(void (*handler)(uint16_t frame_size); */ &btstack_uart_slip_posix_set_frame_received, 651 /* void (*set_fraae_sent)(void (*handler)(void)); */ &btstack_uart_slip_posix_set_frame_sent, 652 /* void (*receive_frame)(uint8_t *buffer, uint16_t len); */ &btstack_uart_slip_posix_receive_frame, 653 /* void (*send_frame)(const uint8_t *buffer, uint16_t length); */ &btstack_uart_slip_posix_send_frame, 654 #else 655 NULL, NULL, NULL, NULL, 656 #endif 657 }; 658 659 const btstack_uart_t * btstack_uart_posix_instance(void){ 660 return &btstack_uart_posix; 661 } 662