1 /* 2 * Copyright (C) 2014 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 MATTHIAS 24 * RINGWALD 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__ "hci_transport_h4.c" 39 40 /* 41 * hci_h4_transport.c 42 * 43 * HCI Transport API implementation for H4 protocol over POSIX with optional support for eHCILL 44 * 45 * Created by Matthias Ringwald on 4/29/09. 46 */ 47 48 #include <inttypes.h> 49 50 #include "btstack_config.h" 51 52 #include "btstack_debug.h" 53 #include "hci.h" 54 #include "hci_transport.h" 55 #include "bluetooth_company_id.h" 56 #include "btstack_uart_block.h" 57 58 #define ENABLE_LOG_EHCILL 59 60 #ifdef ENABLE_EHCILL 61 62 // eHCILL commands 63 enum EHCILL_MESSAGES { 64 EHCILL_GO_TO_SLEEP_IND = 0x030, 65 EHCILL_GO_TO_SLEEP_ACK = 0x031, 66 EHCILL_WAKE_UP_IND = 0x032, 67 EHCILL_WAKE_UP_ACK = 0x033, 68 EHCILL_WAKEUP_SIGNAL = 0x034, 69 }; 70 71 static int hci_transport_h4_ehcill_outgoing_packet_ready(void); 72 static void hci_transport_h4_echill_send_wakeup_ind(void); 73 static void hci_transport_h4_ehcill_handle_command(uint8_t action); 74 static void hci_transport_h4_ehcill_handle_ehcill_command_sent(void); 75 static void hci_transport_h4_ehcill_handle_packet_sent(void); 76 static void hci_transport_h4_ehcill_open(void); 77 static void hci_transport_h4_ehcill_reset_statemachine(void); 78 static void hci_transport_h4_ehcill_send_ehcill_command(void); 79 static void hci_transport_h4_ehcill_sleep_ack_timer_setup(void); 80 static void hci_transport_h4_ehcill_trigger_wakeup(void); 81 82 typedef enum { 83 EHCILL_STATE_W2_SEND_SLEEP_ACK, 84 EHCILL_STATE_SLEEP, 85 EHCILL_STATE_W4_WAKEUP_IND_OR_ACK, 86 EHCILL_STATE_AWAKE 87 } EHCILL_STATE; 88 89 // eHCILL state machine 90 static EHCILL_STATE ehcill_state; 91 static uint8_t ehcill_command_to_send; 92 93 static btstack_uart_sleep_mode_t btstack_uart_sleep_mode; 94 95 // work around for eHCILL problem 96 static btstack_timer_source_t ehcill_sleep_ack_timer; 97 98 #endif 99 100 101 // assert pre-buffer for packet type is available 102 #if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE == 0) 103 #error HCI_OUTGOING_PRE_BUFFER_SIZE not defined. Please update hci.h 104 #endif 105 106 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size); 107 108 typedef enum { 109 H4_OFF, 110 H4_W4_PACKET_TYPE, 111 H4_W4_EVENT_HEADER, 112 H4_W4_ACL_HEADER, 113 H4_W4_SCO_HEADER, 114 H4_W4_PAYLOAD, 115 } H4_STATE; 116 117 typedef enum { 118 TX_OFF, 119 TX_IDLE, 120 TX_W4_PACKET_SENT, 121 #ifdef ENABLE_EHCILL 122 TX_W4_WAKEUP, 123 TX_W2_EHCILL_SEND, 124 TX_W4_EHCILL_SENT, 125 #endif 126 } TX_STATE; 127 128 // UART Driver + Config 129 static const btstack_uart_block_t * btstack_uart; 130 static btstack_uart_config_t uart_config; 131 132 // write state 133 static TX_STATE tx_state; 134 #ifdef ENABLE_EHCILL 135 static uint8_t * ehcill_tx_data; 136 static uint16_t ehcill_tx_len; // 0 == no outgoing packet 137 #endif 138 139 static uint8_t packet_sent_event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0}; 140 141 static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler; 142 143 // packet reader state machine 144 static H4_STATE h4_state; 145 static uint16_t bytes_to_read; 146 static uint16_t read_pos; 147 148 // incoming packet buffer 149 static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + HCI_INCOMING_PACKET_BUFFER_SIZE + 1]; // packet type + max(acl header + acl payload, event header + event data) 150 static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE]; 151 152 // Baudrate change bugs in TI CC256x and CYW20704 153 #ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 154 #define ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 155 static const uint8_t baud_rate_command_prefix[] = { 0x01, 0x36, 0xff, 0x04}; 156 #endif 157 158 #ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 159 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 160 #error "Please enable either ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND or ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND" 161 #endif 162 #define ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 163 static const uint8_t baud_rate_command_prefix[] = { 0x01, 0x18, 0xfc, 0x06}; 164 #endif 165 166 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 167 static const uint8_t local_version_event_prefix[] = { 0x04, 0x0e, 0x0c, 0x01, 0x01, 0x10}; 168 static enum { 169 BAUDRATE_CHANGE_WORKAROUND_IDLE, 170 BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED, 171 BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT, 172 BAUDRATE_CHANGE_WORKAROUND_DONE 173 } baudrate_change_workaround_state; 174 #endif 175 176 static int hci_transport_h4_set_baudrate(uint32_t baudrate){ 177 log_info("hci_transport_h4_set_baudrate %"PRIu32, baudrate); 178 return btstack_uart->set_baudrate(baudrate); 179 } 180 181 static void hci_transport_h4_reset_statemachine(void){ 182 h4_state = H4_W4_PACKET_TYPE; 183 read_pos = 0; 184 bytes_to_read = 1; 185 } 186 187 static void hci_transport_h4_trigger_next_read(void){ 188 // log_info("hci_transport_h4_trigger_next_read: %u bytes", bytes_to_read); 189 btstack_uart->receive_block(&hci_packet[read_pos], bytes_to_read); 190 } 191 192 static void hci_transport_h4_block_read(void){ 193 194 uint16_t packet_len; 195 196 read_pos += bytes_to_read; 197 198 switch (h4_state) { 199 case H4_W4_PACKET_TYPE: 200 switch (hci_packet[0]){ 201 case HCI_EVENT_PACKET: 202 bytes_to_read = HCI_EVENT_HEADER_SIZE; 203 h4_state = H4_W4_EVENT_HEADER; 204 break; 205 case HCI_ACL_DATA_PACKET: 206 bytes_to_read = HCI_ACL_HEADER_SIZE; 207 h4_state = H4_W4_ACL_HEADER; 208 break; 209 case HCI_SCO_DATA_PACKET: 210 bytes_to_read = HCI_SCO_HEADER_SIZE; 211 h4_state = H4_W4_SCO_HEADER; 212 break; 213 #ifdef ENABLE_EHCILL 214 case EHCILL_GO_TO_SLEEP_IND: 215 case EHCILL_GO_TO_SLEEP_ACK: 216 case EHCILL_WAKE_UP_IND: 217 case EHCILL_WAKE_UP_ACK: 218 hci_transport_h4_ehcill_handle_command(hci_packet[0]); 219 hci_transport_h4_reset_statemachine(); 220 break; 221 #endif 222 default: 223 log_error("hci_transport_h4: invalid packet type 0x%02x", hci_packet[0]); 224 hci_transport_h4_reset_statemachine(); 225 break; 226 } 227 break; 228 229 case H4_W4_EVENT_HEADER: 230 bytes_to_read = hci_packet[2]; 231 // check Event length 232 if (bytes_to_read > (HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_EVENT_HEADER_SIZE)){ 233 log_error("hci_transport_h4: invalid Event len %d - only space for %u", bytes_to_read, HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_EVENT_HEADER_SIZE); 234 hci_transport_h4_reset_statemachine(); 235 break; 236 } 237 h4_state = H4_W4_PAYLOAD; 238 break; 239 240 case H4_W4_ACL_HEADER: 241 bytes_to_read = little_endian_read_16( hci_packet, 3); 242 // check ACL length 243 if (bytes_to_read > (HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE)){ 244 log_error("hci_transport_h4: invalid ACL payload len %d - only space for %u", bytes_to_read, HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE); 245 hci_transport_h4_reset_statemachine(); 246 break; 247 } 248 h4_state = H4_W4_PAYLOAD; 249 break; 250 251 case H4_W4_SCO_HEADER: 252 bytes_to_read = hci_packet[3]; 253 // check SCO length 254 if (bytes_to_read > (HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_SCO_HEADER_SIZE)){ 255 log_error("hci_transport_h4: invalid SCO payload len %d - only space for %u", bytes_to_read, HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_SCO_HEADER_SIZE); 256 hci_transport_h4_reset_statemachine(); 257 break; 258 } 259 h4_state = H4_W4_PAYLOAD; 260 break; 261 262 case H4_W4_PAYLOAD: 263 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 264 if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_IDLE 265 && memcmp(hci_packet, local_version_event_prefix, sizeof(local_version_event_prefix)) == 0){ 266 #ifdef ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 267 if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC){ 268 // detect TI CC256x controller based on manufacturer 269 log_info("Detected CC256x controller"); 270 baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED; 271 } else { 272 // work around not needed 273 log_info("Bluetooth controller not by TI"); 274 baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE; 275 } 276 #endif 277 #ifdef ENABLE_CYPRESS_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 278 if (little_endian_read_16(hci_packet, 11) == BLUETOOTH_COMPANY_ID_CYPRESS_SEMICONDUCTOR){ 279 // detect Cypress controller based on manufacturer 280 log_info("Detected Cypress controller"); 281 baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED; 282 } else { 283 // work around not needed 284 log_info("Bluetooth controller not by Cypress"); 285 baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_DONE; 286 } 287 #endif 288 } 289 #endif 290 packet_len = read_pos-1; 291 292 // reset state machine before delivering packet to stack as it might close the transport 293 hci_transport_h4_reset_statemachine(); 294 packet_handler(hci_packet[0], &hci_packet[1], packet_len); 295 break; 296 297 case H4_OFF: 298 bytes_to_read = 0; 299 break; 300 } 301 302 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 303 if (baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT){ 304 baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_IDLE; 305 // avoid flowcontrol problem by reading expected hci command complete event of 7 bytes in a single block read 306 h4_state = H4_W4_PAYLOAD; 307 bytes_to_read = 7; 308 } 309 #endif 310 311 if (h4_state != H4_OFF) { 312 hci_transport_h4_trigger_next_read(); 313 } 314 } 315 316 static void hci_transport_h4_block_sent(void){ 317 switch (tx_state){ 318 case TX_W4_PACKET_SENT: 319 // packet fully sent, reset state 320 #ifdef ENABLE_EHCILL 321 ehcill_tx_len = 0; 322 #endif 323 tx_state = TX_IDLE; 324 325 #ifdef ENABLE_EHCILL 326 // notify eHCILL engine 327 hci_transport_h4_ehcill_handle_packet_sent(); 328 #endif 329 // notify upper stack that it can send again 330 packet_handler(HCI_EVENT_PACKET, &packet_sent_event[0], sizeof(packet_sent_event)); 331 break; 332 333 #ifdef ENABLE_EHCILL 334 case TX_W4_EHCILL_SENT: 335 case TX_W4_WAKEUP: 336 hci_transport_h4_ehcill_handle_ehcill_command_sent(); 337 break; 338 #endif 339 340 default: 341 break; 342 } 343 } 344 345 static int hci_transport_h4_can_send_now(uint8_t packet_type){ 346 return tx_state == TX_IDLE; 347 } 348 349 static int hci_transport_h4_send_packet(uint8_t packet_type, uint8_t * packet, int size){ 350 351 // store packet type before actual data and increase size 352 size++; 353 packet--; 354 *packet = packet_type; 355 356 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 357 if ((baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED) 358 && (memcmp(packet, baud_rate_command_prefix, sizeof(baud_rate_command_prefix)) == 0)) { 359 log_info("Baud rate command detected, expect command complete event next"); 360 baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT; 361 } 362 #endif 363 364 #ifdef ENABLE_EHCILL 365 // store request for later 366 ehcill_tx_len = size; 367 ehcill_tx_data = packet; 368 switch (ehcill_state){ 369 case EHCILL_STATE_SLEEP: 370 hci_transport_h4_ehcill_trigger_wakeup(); 371 return 0; 372 case EHCILL_STATE_W2_SEND_SLEEP_ACK: 373 log_info("eHILL: send next packet, state EHCILL_STATE_W2_SEND_SLEEP_ACK"); 374 return 0; 375 default: 376 break; 377 } 378 #endif 379 380 // start sending 381 tx_state = TX_W4_PACKET_SENT; 382 btstack_uart->send_block(packet, size); 383 return 0; 384 } 385 386 static void hci_transport_h4_init(const void * transport_config){ 387 // check for hci_transport_config_uart_t 388 if (!transport_config) { 389 log_error("hci_transport_h4: no config!"); 390 return; 391 } 392 if (((hci_transport_config_t*)transport_config)->type != HCI_TRANSPORT_CONFIG_UART) { 393 log_error("hci_transport_h4: config not of type != HCI_TRANSPORT_CONFIG_UART!"); 394 return; 395 } 396 397 // extract UART config from transport config 398 hci_transport_config_uart_t * hci_transport_config_uart = (hci_transport_config_uart_t*) transport_config; 399 uart_config.baudrate = hci_transport_config_uart->baudrate_init; 400 uart_config.flowcontrol = hci_transport_config_uart->flowcontrol; 401 uart_config.device_name = hci_transport_config_uart->device_name; 402 403 // set state to off 404 tx_state = TX_OFF; 405 h4_state = H4_OFF; 406 407 // setup UART driver 408 btstack_uart->init(&uart_config); 409 btstack_uart->set_block_received(&hci_transport_h4_block_read); 410 btstack_uart->set_block_sent(&hci_transport_h4_block_sent); 411 } 412 413 static int hci_transport_h4_open(void){ 414 // open uart driver 415 int res = btstack_uart->open(); 416 if (res){ 417 return res; 418 } 419 420 // init rx + tx state machines 421 hci_transport_h4_reset_statemachine(); 422 hci_transport_h4_trigger_next_read(); 423 tx_state = TX_IDLE; 424 425 #ifdef ENABLE_EHCILL 426 hci_transport_h4_ehcill_open(); 427 #endif 428 return 0; 429 } 430 431 static int hci_transport_h4_close(void){ 432 // set state to off 433 tx_state = TX_OFF; 434 h4_state = H4_OFF; 435 436 // close uart driver 437 return btstack_uart->close(); 438 } 439 440 static void hci_transport_h4_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ 441 packet_handler = handler; 442 } 443 444 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ 445 } 446 447 // 448 // --- main part of eHCILL implementation --- 449 // 450 451 #ifdef ENABLE_EHCILL 452 453 static void hci_transport_h4_ehcill_emit_sleep_state(int sleep_active){ 454 static int last_state = 0; 455 if (sleep_active == last_state) return; 456 last_state = sleep_active; 457 458 log_info("hci_transport_h4_ehcill_emit_sleep_state: %u", sleep_active); 459 uint8_t event[3]; 460 event[0] = HCI_EVENT_TRANSPORT_SLEEP_MODE; 461 event[1] = sizeof(event) - 2; 462 event[2] = sleep_active; 463 packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); 464 } 465 466 static void hci_transport_h4_ehcill_wakeup_handler(void){ 467 #ifdef ENABLE_LOG_EHCILL 468 log_info("eHCILL: UART wakeup received"); 469 #endif 470 hci_transport_h4_ehcill_handle_command(EHCILL_WAKEUP_SIGNAL); 471 } 472 473 static void hci_transport_h4_ehcill_open(void){ 474 hci_transport_h4_ehcill_reset_statemachine(); 475 476 // find best sleep mode to use: wake on CTS, wake on RX, none 477 btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_OFF; 478 int supported_sleep_modes = 0; 479 if (btstack_uart->get_supported_sleep_modes){ 480 supported_sleep_modes = btstack_uart->get_supported_sleep_modes(); 481 } 482 if (supported_sleep_modes & BTSTACK_UART_SLEEP_MASK_RTS_HIGH_WAKE_ON_CTS_PULSE){ 483 log_info("eHCILL: using wake on CTS"); 484 btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_RTS_HIGH_WAKE_ON_CTS_PULSE; 485 } else if (supported_sleep_modes & BTSTACK_UART_SLEEP_MASK_RTS_LOW_WAKE_ON_RX_EDGE){ 486 log_info("eHCILL: using wake on RX"); 487 btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_RTS_LOW_WAKE_ON_RX_EDGE; 488 } else { 489 log_info("eHCILL: UART driver does not provide compatible sleep mode"); 490 } 491 if (btstack_uart->set_wakeup_handler){ 492 btstack_uart->set_wakeup_handler(&hci_transport_h4_ehcill_wakeup_handler); 493 } 494 } 495 496 static void hci_transport_h4_echill_send_wakeup_ind(void){ 497 #ifdef ENABLE_LOG_EHCILL 498 log_info("eHCILL: send WAKEUP_IND"); 499 #endif 500 // update state 501 tx_state = TX_W4_WAKEUP; 502 ehcill_state = EHCILL_STATE_W4_WAKEUP_IND_OR_ACK; 503 ehcill_command_to_send = EHCILL_WAKE_UP_IND; 504 btstack_uart->send_block(&ehcill_command_to_send, 1); 505 } 506 507 static int hci_transport_h4_ehcill_outgoing_packet_ready(void){ 508 return ehcill_tx_len != 0; 509 } 510 511 static void hci_transport_h4_ehcill_reset_statemachine(void){ 512 ehcill_state = EHCILL_STATE_AWAKE; 513 } 514 515 static void hci_transport_h4_ehcill_send_ehcill_command(void){ 516 #ifdef ENABLE_LOG_EHCILL 517 log_info("eHCILL: send command %02x", ehcill_command_to_send); 518 #endif 519 tx_state = TX_W4_EHCILL_SENT; 520 if (ehcill_command_to_send == EHCILL_GO_TO_SLEEP_ACK){ 521 ehcill_state = EHCILL_STATE_SLEEP; 522 } 523 btstack_uart->send_block(&ehcill_command_to_send, 1); 524 } 525 526 static void hci_transport_h4_ehcill_sleep_ack_timer_handler(btstack_timer_source_t * timer){ 527 UNUSED(timer); 528 #ifdef ENABLE_LOG_EHCILL 529 log_info("eHCILL: timer triggered"); 530 #endif 531 hci_transport_h4_ehcill_send_ehcill_command(); 532 } 533 534 static void hci_transport_h4_ehcill_sleep_ack_timer_setup(void){ 535 // setup timer 536 #ifdef ENABLE_LOG_EHCILL 537 log_info("eHCILL: set timer for sending command %02x", ehcill_command_to_send); 538 #endif 539 btstack_run_loop_set_timer_handler(&ehcill_sleep_ack_timer, &hci_transport_h4_ehcill_sleep_ack_timer_handler); 540 btstack_run_loop_set_timer(&ehcill_sleep_ack_timer, 50); 541 btstack_run_loop_add_timer(&ehcill_sleep_ack_timer); 542 } 543 544 static void hci_transport_h4_ehcill_trigger_wakeup(void){ 545 switch (tx_state){ 546 case TX_W2_EHCILL_SEND: 547 case TX_W4_EHCILL_SENT: 548 // wake up / sleep ack in progress, nothing to do now 549 return; 550 case TX_IDLE: 551 default: 552 // all clear, prepare for wakeup 553 break; 554 } 555 // UART needed again 556 hci_transport_h4_ehcill_emit_sleep_state(0); 557 if (btstack_uart_sleep_mode){ 558 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 559 } 560 hci_transport_h4_echill_send_wakeup_ind(); 561 } 562 563 static void hci_transport_h4_ehcill_schedule_ehcill_command(uint8_t command){ 564 #ifdef ENABLE_LOG_EHCILL 565 log_info("eHCILL: schedule eHCILL command %02x", command); 566 #endif 567 ehcill_command_to_send = command; 568 switch (tx_state){ 569 case TX_IDLE: 570 if (ehcill_command_to_send == EHCILL_WAKE_UP_ACK){ 571 // send right away 572 hci_transport_h4_ehcill_send_ehcill_command(); 573 } else { 574 // change state so BTstack cannot send and setup timer 575 tx_state = TX_W2_EHCILL_SEND; 576 hci_transport_h4_ehcill_sleep_ack_timer_setup(); 577 } 578 break; 579 default: 580 break; 581 } 582 } 583 584 static void hci_transport_h4_ehcill_handle_command(uint8_t action){ 585 // log_info("hci_transport_h4_ehcill_handle: %x, state %u, defer_rx %u", action, ehcill_state, ehcill_defer_rx_size); 586 switch(ehcill_state){ 587 case EHCILL_STATE_AWAKE: 588 switch(action){ 589 case EHCILL_GO_TO_SLEEP_IND: 590 ehcill_state = EHCILL_STATE_W2_SEND_SLEEP_ACK; 591 #ifdef ENABLE_LOG_EHCILL 592 log_info("eHCILL: Received GO_TO_SLEEP_IND RX"); 593 #endif 594 hci_transport_h4_ehcill_schedule_ehcill_command(EHCILL_GO_TO_SLEEP_ACK); 595 break; 596 default: 597 break; 598 } 599 break; 600 601 case EHCILL_STATE_W2_SEND_SLEEP_ACK: 602 switch(action){ 603 case EHCILL_WAKE_UP_IND: 604 ehcill_state = EHCILL_STATE_AWAKE; 605 hci_transport_h4_ehcill_emit_sleep_state(0); 606 if (btstack_uart_sleep_mode){ 607 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 608 } 609 #ifdef ENABLE_LOG_EHCILL 610 log_info("eHCILL: Received WAKE_UP_IND RX"); 611 #endif 612 hci_transport_h4_ehcill_schedule_ehcill_command(EHCILL_WAKE_UP_ACK); 613 break; 614 615 default: 616 break; 617 } 618 break; 619 620 case EHCILL_STATE_SLEEP: 621 switch(action){ 622 case EHCILL_WAKEUP_SIGNAL: 623 hci_transport_h4_ehcill_emit_sleep_state(0); 624 if (btstack_uart_sleep_mode){ 625 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 626 } 627 break; 628 case EHCILL_WAKE_UP_IND: 629 ehcill_state = EHCILL_STATE_AWAKE; 630 hci_transport_h4_ehcill_emit_sleep_state(0); 631 if (btstack_uart_sleep_mode){ 632 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 633 } 634 #ifdef ENABLE_LOG_EHCILL 635 log_info("eHCILL: Received WAKE_UP_IND RX"); 636 #endif 637 hci_transport_h4_ehcill_schedule_ehcill_command(EHCILL_WAKE_UP_ACK); 638 break; 639 640 default: 641 break; 642 } 643 break; 644 645 case EHCILL_STATE_W4_WAKEUP_IND_OR_ACK: 646 switch(action){ 647 case EHCILL_WAKE_UP_IND: 648 case EHCILL_WAKE_UP_ACK: 649 #ifdef ENABLE_LOG_EHCILL 650 log_info("eHCILL: Received WAKE_UP (%02x)", action); 651 #endif 652 tx_state = TX_W4_PACKET_SENT; 653 ehcill_state = EHCILL_STATE_AWAKE; 654 btstack_uart->send_block(ehcill_tx_data, ehcill_tx_len); 655 break; 656 default: 657 break; 658 } 659 break; 660 } 661 } 662 663 static void hci_transport_h4_ehcill_handle_packet_sent(void){ 664 #ifdef ENABLE_LOG_EHCILL 665 log_info("eHCILL: handle packet sent, command to send %02x", ehcill_command_to_send); 666 #endif 667 // now, send pending ehcill command if neccessary 668 switch (ehcill_command_to_send){ 669 case EHCILL_GO_TO_SLEEP_ACK: 670 hci_transport_h4_ehcill_sleep_ack_timer_setup(); 671 break; 672 case EHCILL_WAKE_UP_IND: 673 hci_transport_h4_ehcill_send_ehcill_command(); 674 break; 675 default: 676 break; 677 } 678 } 679 680 static void hci_transport_h4_ehcill_handle_ehcill_command_sent(void){ 681 tx_state = TX_IDLE; 682 int command = ehcill_command_to_send; 683 ehcill_command_to_send = 0; 684 685 #ifdef ENABLE_LOG_EHCILL 686 log_info("eHCILL: handle eHCILL sent, command was %02x", command); 687 #endif 688 689 if (command == EHCILL_GO_TO_SLEEP_ACK) { 690 #ifdef ENABLE_LOG_EHCILL 691 log_info("eHCILL: GO_TO_SLEEP_ACK sent, enter sleep mode"); 692 #endif 693 // UART not needed after EHCILL_GO_TO_SLEEP_ACK was sent 694 if (btstack_uart_sleep_mode != BTSTACK_UART_SLEEP_OFF){ 695 btstack_uart->set_sleep(btstack_uart_sleep_mode); 696 } 697 hci_transport_h4_ehcill_emit_sleep_state(1); 698 } 699 // already packet ready? then start wakeup 700 if (hci_transport_h4_ehcill_outgoing_packet_ready()){ 701 hci_transport_h4_ehcill_emit_sleep_state(0); 702 if (btstack_uart_sleep_mode != BTSTACK_UART_SLEEP_OFF){ 703 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 704 } 705 if (command != EHCILL_WAKE_UP_IND){ 706 hci_transport_h4_echill_send_wakeup_ind(); 707 } 708 } 709 } 710 711 #endif 712 // --- end of eHCILL implementation --------- 713 714 static const hci_transport_t hci_transport_h4 = { 715 /* const char * name; */ "H4", 716 /* void (*init) (const void *transport_config); */ &hci_transport_h4_init, 717 /* int (*open)(void); */ &hci_transport_h4_open, 718 /* int (*close)(void); */ &hci_transport_h4_close, 719 /* void (*register_packet_handler)(void (*handler)(...); */ &hci_transport_h4_register_packet_handler, 720 /* int (*can_send_packet_now)(uint8_t packet_type); */ &hci_transport_h4_can_send_now, 721 /* int (*send_packet)(...); */ &hci_transport_h4_send_packet, 722 /* int (*set_baudrate)(uint32_t baudrate); */ &hci_transport_h4_set_baudrate, 723 /* void (*reset_link)(void); */ NULL, 724 /* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL, 725 }; 726 727 // configure and return h4 singleton 728 const hci_transport_t * hci_transport_h4_instance(const btstack_uart_block_t * uart_driver) { 729 btstack_uart = uart_driver; 730 return &hci_transport_h4; 731 } 732