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