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