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 UNUSED(packet_type); 347 return tx_state == TX_IDLE; 348 } 349 350 static int hci_transport_h4_send_packet(uint8_t packet_type, uint8_t * packet, int size){ 351 352 // store packet type before actual data and increase size 353 size++; 354 packet--; 355 *packet = packet_type; 356 357 #ifdef ENABLE_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND 358 if ((baudrate_change_workaround_state == BAUDRATE_CHANGE_WORKAROUND_CHIPSET_DETECTED) 359 && (memcmp(packet, baud_rate_command_prefix, sizeof(baud_rate_command_prefix)) == 0)) { 360 log_info("Baud rate command detected, expect command complete event next"); 361 baudrate_change_workaround_state = BAUDRATE_CHANGE_WORKAROUND_BAUDRATE_COMMAND_SENT; 362 } 363 #endif 364 365 #ifdef ENABLE_EHCILL 366 // store request for later 367 ehcill_tx_len = size; 368 ehcill_tx_data = packet; 369 switch (ehcill_state){ 370 case EHCILL_STATE_SLEEP: 371 hci_transport_h4_ehcill_trigger_wakeup(); 372 return 0; 373 case EHCILL_STATE_W2_SEND_SLEEP_ACK: 374 log_info("eHILL: send next packet, state EHCILL_STATE_W2_SEND_SLEEP_ACK"); 375 return 0; 376 default: 377 break; 378 } 379 #endif 380 381 // start sending 382 tx_state = TX_W4_PACKET_SENT; 383 btstack_uart->send_block(packet, size); 384 return 0; 385 } 386 387 static void hci_transport_h4_init(const void * transport_config){ 388 // check for hci_transport_config_uart_t 389 if (!transport_config) { 390 log_error("hci_transport_h4: no config!"); 391 return; 392 } 393 if (((hci_transport_config_t*)transport_config)->type != HCI_TRANSPORT_CONFIG_UART) { 394 log_error("hci_transport_h4: config not of type != HCI_TRANSPORT_CONFIG_UART!"); 395 return; 396 } 397 398 // extract UART config from transport config 399 hci_transport_config_uart_t * hci_transport_config_uart = (hci_transport_config_uart_t*) transport_config; 400 uart_config.baudrate = hci_transport_config_uart->baudrate_init; 401 uart_config.flowcontrol = hci_transport_config_uart->flowcontrol; 402 uart_config.device_name = hci_transport_config_uart->device_name; 403 404 // set state to off 405 tx_state = TX_OFF; 406 h4_state = H4_OFF; 407 408 // setup UART driver 409 btstack_uart->init(&uart_config); 410 btstack_uart->set_block_received(&hci_transport_h4_block_read); 411 btstack_uart->set_block_sent(&hci_transport_h4_block_sent); 412 } 413 414 static int hci_transport_h4_open(void){ 415 // open uart driver 416 int res = btstack_uart->open(); 417 if (res){ 418 return res; 419 } 420 421 // init rx + tx state machines 422 hci_transport_h4_reset_statemachine(); 423 hci_transport_h4_trigger_next_read(); 424 tx_state = TX_IDLE; 425 426 #ifdef ENABLE_EHCILL 427 hci_transport_h4_ehcill_open(); 428 #endif 429 return 0; 430 } 431 432 static int hci_transport_h4_close(void){ 433 // set state to off 434 tx_state = TX_OFF; 435 h4_state = H4_OFF; 436 437 // close uart driver 438 return btstack_uart->close(); 439 } 440 441 static void hci_transport_h4_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ 442 packet_handler = handler; 443 } 444 445 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ 446 UNUSED(packet_type); 447 UNUSED(packet); 448 UNUSED(size); 449 } 450 451 // 452 // --- main part of eHCILL implementation --- 453 // 454 455 #ifdef ENABLE_EHCILL 456 457 static void hci_transport_h4_ehcill_emit_sleep_state(int sleep_active){ 458 static int last_state = 0; 459 if (sleep_active == last_state) return; 460 last_state = sleep_active; 461 462 log_info("hci_transport_h4_ehcill_emit_sleep_state: %u", sleep_active); 463 uint8_t event[3]; 464 event[0] = HCI_EVENT_TRANSPORT_SLEEP_MODE; 465 event[1] = sizeof(event) - 2; 466 event[2] = sleep_active; 467 packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event)); 468 } 469 470 static void hci_transport_h4_ehcill_wakeup_handler(void){ 471 #ifdef ENABLE_LOG_EHCILL 472 log_info("eHCILL: UART wakeup received"); 473 #endif 474 hci_transport_h4_ehcill_handle_command(EHCILL_WAKEUP_SIGNAL); 475 } 476 477 static void hci_transport_h4_ehcill_open(void){ 478 hci_transport_h4_ehcill_reset_statemachine(); 479 480 // find best sleep mode to use: wake on CTS, wake on RX, none 481 btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_OFF; 482 int supported_sleep_modes = 0; 483 if (btstack_uart->get_supported_sleep_modes){ 484 supported_sleep_modes = btstack_uart->get_supported_sleep_modes(); 485 } 486 if (supported_sleep_modes & BTSTACK_UART_SLEEP_MASK_RTS_HIGH_WAKE_ON_CTS_PULSE){ 487 log_info("eHCILL: using wake on CTS"); 488 btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_RTS_HIGH_WAKE_ON_CTS_PULSE; 489 } else if (supported_sleep_modes & BTSTACK_UART_SLEEP_MASK_RTS_LOW_WAKE_ON_RX_EDGE){ 490 log_info("eHCILL: using wake on RX"); 491 btstack_uart_sleep_mode = BTSTACK_UART_SLEEP_RTS_LOW_WAKE_ON_RX_EDGE; 492 } else { 493 log_info("eHCILL: UART driver does not provide compatible sleep mode"); 494 } 495 if (btstack_uart->set_wakeup_handler){ 496 btstack_uart->set_wakeup_handler(&hci_transport_h4_ehcill_wakeup_handler); 497 } 498 } 499 500 static void hci_transport_h4_echill_send_wakeup_ind(void){ 501 #ifdef ENABLE_LOG_EHCILL 502 log_info("eHCILL: send WAKEUP_IND"); 503 #endif 504 // update state 505 tx_state = TX_W4_WAKEUP; 506 ehcill_state = EHCILL_STATE_W4_WAKEUP_IND_OR_ACK; 507 ehcill_command_to_send = EHCILL_WAKE_UP_IND; 508 btstack_uart->send_block(&ehcill_command_to_send, 1); 509 } 510 511 static int hci_transport_h4_ehcill_outgoing_packet_ready(void){ 512 return ehcill_tx_len != 0; 513 } 514 515 static void hci_transport_h4_ehcill_reset_statemachine(void){ 516 ehcill_state = EHCILL_STATE_AWAKE; 517 } 518 519 static void hci_transport_h4_ehcill_send_ehcill_command(void){ 520 #ifdef ENABLE_LOG_EHCILL 521 log_info("eHCILL: send command %02x", ehcill_command_to_send); 522 #endif 523 tx_state = TX_W4_EHCILL_SENT; 524 if (ehcill_command_to_send == EHCILL_GO_TO_SLEEP_ACK){ 525 ehcill_state = EHCILL_STATE_SLEEP; 526 } 527 btstack_uart->send_block(&ehcill_command_to_send, 1); 528 } 529 530 static void hci_transport_h4_ehcill_sleep_ack_timer_handler(btstack_timer_source_t * timer){ 531 UNUSED(timer); 532 #ifdef ENABLE_LOG_EHCILL 533 log_info("eHCILL: timer triggered"); 534 #endif 535 hci_transport_h4_ehcill_send_ehcill_command(); 536 } 537 538 static void hci_transport_h4_ehcill_sleep_ack_timer_setup(void){ 539 // setup timer 540 #ifdef ENABLE_LOG_EHCILL 541 log_info("eHCILL: set timer for sending command %02x", ehcill_command_to_send); 542 #endif 543 btstack_run_loop_set_timer_handler(&ehcill_sleep_ack_timer, &hci_transport_h4_ehcill_sleep_ack_timer_handler); 544 btstack_run_loop_set_timer(&ehcill_sleep_ack_timer, 50); 545 btstack_run_loop_add_timer(&ehcill_sleep_ack_timer); 546 } 547 548 static void hci_transport_h4_ehcill_trigger_wakeup(void){ 549 switch (tx_state){ 550 case TX_W2_EHCILL_SEND: 551 case TX_W4_EHCILL_SENT: 552 // wake up / sleep ack in progress, nothing to do now 553 return; 554 case TX_IDLE: 555 default: 556 // all clear, prepare for wakeup 557 break; 558 } 559 // UART needed again 560 hci_transport_h4_ehcill_emit_sleep_state(0); 561 if (btstack_uart_sleep_mode){ 562 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 563 } 564 hci_transport_h4_echill_send_wakeup_ind(); 565 } 566 567 static void hci_transport_h4_ehcill_schedule_ehcill_command(uint8_t command){ 568 #ifdef ENABLE_LOG_EHCILL 569 log_info("eHCILL: schedule eHCILL command %02x", command); 570 #endif 571 ehcill_command_to_send = command; 572 switch (tx_state){ 573 case TX_IDLE: 574 if (ehcill_command_to_send == EHCILL_WAKE_UP_ACK){ 575 // send right away 576 hci_transport_h4_ehcill_send_ehcill_command(); 577 } else { 578 // change state so BTstack cannot send and setup timer 579 tx_state = TX_W2_EHCILL_SEND; 580 hci_transport_h4_ehcill_sleep_ack_timer_setup(); 581 } 582 break; 583 default: 584 break; 585 } 586 } 587 588 static void hci_transport_h4_ehcill_handle_command(uint8_t action){ 589 // log_info("hci_transport_h4_ehcill_handle: %x, state %u, defer_rx %u", action, ehcill_state, ehcill_defer_rx_size); 590 switch(ehcill_state){ 591 case EHCILL_STATE_AWAKE: 592 switch(action){ 593 case EHCILL_GO_TO_SLEEP_IND: 594 ehcill_state = EHCILL_STATE_W2_SEND_SLEEP_ACK; 595 #ifdef ENABLE_LOG_EHCILL 596 log_info("eHCILL: Received GO_TO_SLEEP_IND RX"); 597 #endif 598 hci_transport_h4_ehcill_schedule_ehcill_command(EHCILL_GO_TO_SLEEP_ACK); 599 break; 600 default: 601 break; 602 } 603 break; 604 605 case EHCILL_STATE_W2_SEND_SLEEP_ACK: 606 switch(action){ 607 case EHCILL_WAKE_UP_IND: 608 ehcill_state = EHCILL_STATE_AWAKE; 609 hci_transport_h4_ehcill_emit_sleep_state(0); 610 if (btstack_uart_sleep_mode){ 611 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 612 } 613 #ifdef ENABLE_LOG_EHCILL 614 log_info("eHCILL: Received WAKE_UP_IND RX"); 615 #endif 616 hci_transport_h4_ehcill_schedule_ehcill_command(EHCILL_WAKE_UP_ACK); 617 break; 618 619 default: 620 break; 621 } 622 break; 623 624 case EHCILL_STATE_SLEEP: 625 switch(action){ 626 case EHCILL_WAKEUP_SIGNAL: 627 hci_transport_h4_ehcill_emit_sleep_state(0); 628 if (btstack_uart_sleep_mode){ 629 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 630 } 631 break; 632 case EHCILL_WAKE_UP_IND: 633 ehcill_state = EHCILL_STATE_AWAKE; 634 hci_transport_h4_ehcill_emit_sleep_state(0); 635 if (btstack_uart_sleep_mode){ 636 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 637 } 638 #ifdef ENABLE_LOG_EHCILL 639 log_info("eHCILL: Received WAKE_UP_IND RX"); 640 #endif 641 hci_transport_h4_ehcill_schedule_ehcill_command(EHCILL_WAKE_UP_ACK); 642 break; 643 644 default: 645 break; 646 } 647 break; 648 649 case EHCILL_STATE_W4_WAKEUP_IND_OR_ACK: 650 switch(action){ 651 case EHCILL_WAKE_UP_IND: 652 case EHCILL_WAKE_UP_ACK: 653 #ifdef ENABLE_LOG_EHCILL 654 log_info("eHCILL: Received WAKE_UP (%02x)", action); 655 #endif 656 tx_state = TX_W4_PACKET_SENT; 657 ehcill_state = EHCILL_STATE_AWAKE; 658 btstack_uart->send_block(ehcill_tx_data, ehcill_tx_len); 659 break; 660 default: 661 break; 662 } 663 break; 664 } 665 } 666 667 static void hci_transport_h4_ehcill_handle_packet_sent(void){ 668 #ifdef ENABLE_LOG_EHCILL 669 log_info("eHCILL: handle packet sent, command to send %02x", ehcill_command_to_send); 670 #endif 671 // now, send pending ehcill command if neccessary 672 switch (ehcill_command_to_send){ 673 case EHCILL_GO_TO_SLEEP_ACK: 674 hci_transport_h4_ehcill_sleep_ack_timer_setup(); 675 break; 676 case EHCILL_WAKE_UP_IND: 677 hci_transport_h4_ehcill_send_ehcill_command(); 678 break; 679 default: 680 break; 681 } 682 } 683 684 static void hci_transport_h4_ehcill_handle_ehcill_command_sent(void){ 685 tx_state = TX_IDLE; 686 int command = ehcill_command_to_send; 687 ehcill_command_to_send = 0; 688 689 #ifdef ENABLE_LOG_EHCILL 690 log_info("eHCILL: handle eHCILL sent, command was %02x", command); 691 #endif 692 693 if (command == EHCILL_GO_TO_SLEEP_ACK) { 694 #ifdef ENABLE_LOG_EHCILL 695 log_info("eHCILL: GO_TO_SLEEP_ACK sent, enter sleep mode"); 696 #endif 697 // UART not needed after EHCILL_GO_TO_SLEEP_ACK was sent 698 if (btstack_uart_sleep_mode != BTSTACK_UART_SLEEP_OFF){ 699 btstack_uart->set_sleep(btstack_uart_sleep_mode); 700 } 701 hci_transport_h4_ehcill_emit_sleep_state(1); 702 } 703 // already packet ready? then start wakeup 704 if (hci_transport_h4_ehcill_outgoing_packet_ready()){ 705 hci_transport_h4_ehcill_emit_sleep_state(0); 706 if (btstack_uart_sleep_mode != BTSTACK_UART_SLEEP_OFF){ 707 btstack_uart->set_sleep(BTSTACK_UART_SLEEP_OFF); 708 } 709 if (command != EHCILL_WAKE_UP_IND){ 710 hci_transport_h4_echill_send_wakeup_ind(); 711 } 712 } 713 } 714 715 #endif 716 // --- end of eHCILL implementation --------- 717 718 static const hci_transport_t hci_transport_h4 = { 719 /* const char * name; */ "H4", 720 /* void (*init) (const void *transport_config); */ &hci_transport_h4_init, 721 /* int (*open)(void); */ &hci_transport_h4_open, 722 /* int (*close)(void); */ &hci_transport_h4_close, 723 /* void (*register_packet_handler)(void (*handler)(...); */ &hci_transport_h4_register_packet_handler, 724 /* int (*can_send_packet_now)(uint8_t packet_type); */ &hci_transport_h4_can_send_now, 725 /* int (*send_packet)(...); */ &hci_transport_h4_send_packet, 726 /* int (*set_baudrate)(uint32_t baudrate); */ &hci_transport_h4_set_baudrate, 727 /* void (*reset_link)(void); */ NULL, 728 /* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL, 729 }; 730 731 // configure and return h4 singleton 732 const hci_transport_t * hci_transport_h4_instance(const btstack_uart_block_t * uart_driver) { 733 btstack_uart = uart_driver; 734 return &hci_transport_h4; 735 } 736