1 /* 2 * Copyright (C) 2009 by Matthias Ringwald 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 * 17 * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 21 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 27 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 /* 33 * hci.c 34 * 35 * Created by Matthias Ringwald on 4/29/09. 36 * 37 */ 38 39 #include "hci.h" 40 41 #include <unistd.h> 42 #include <stdarg.h> 43 #include <string.h> 44 #include <stdio.h> 45 46 #include "debug.h" 47 #include "hci_dump.h" 48 49 #include "../include/btstack/hci_cmds.h" 50 #include "../include/btstack/version.h" 51 52 // temp 53 #include "l2cap.h" 54 55 #define HCI_CONNECTION_TIMEOUT_MS 10000 56 57 // the STACK is here 58 static hci_stack_t hci_stack; 59 60 /** 61 * get connection for a given handle 62 * 63 * @return connection OR NULL, if not found 64 */ 65 hci_connection_t * connection_for_handle(hci_con_handle_t con_handle){ 66 linked_item_t *it; 67 for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next){ 68 if ( ((hci_connection_t *) it)->con_handle == con_handle){ 69 return (hci_connection_t *) it; 70 } 71 } 72 return NULL; 73 } 74 75 static void hci_connection_timeout_handler(timer_source_t *timer){ 76 hci_connection_t * connection = linked_item_get_user(&timer->item); 77 struct timeval tv; 78 gettimeofday(&tv, NULL); 79 if (tv.tv_sec >= connection->timestamp.tv_sec + HCI_CONNECTION_TIMEOUT_MS/1000) { 80 // connections might be timed out 81 hci_emit_l2cap_check_timeout(connection); 82 run_loop_set_timer(timer, HCI_CONNECTION_TIMEOUT_MS); 83 } else { 84 // next timeout check at 85 timer->timeout.tv_sec = connection->timestamp.tv_sec + HCI_CONNECTION_TIMEOUT_MS/1000; 86 } 87 run_loop_add_timer(timer); 88 } 89 90 static void hci_connection_timestamp(hci_connection_t *connection){ 91 gettimeofday(&connection->timestamp, NULL); 92 } 93 94 /** 95 * create connection for given address 96 * 97 * @return connection OR NULL, if not found 98 */ 99 static hci_connection_t * create_connection_for_addr(bd_addr_t addr){ 100 hci_connection_t * conn = malloc( sizeof(hci_connection_t) ); 101 if (!conn) return NULL; 102 BD_ADDR_COPY(conn->address, addr); 103 conn->con_handle = 0xffff; 104 conn->flags = 0; 105 linked_item_set_user(&conn->timeout.item, conn); 106 conn->timeout.process = hci_connection_timeout_handler; 107 hci_connection_timestamp(conn); 108 conn->acl_recombination_length = 0; 109 conn->acl_recombination_pos = 0; 110 conn->num_acl_packets_sent = 0; 111 linked_list_add(&hci_stack.connections, (linked_item_t *) conn); 112 return conn; 113 } 114 115 /** 116 * get connection for given address 117 * 118 * @return connection OR NULL, if not found 119 */ 120 static hci_connection_t * connection_for_address(bd_addr_t address){ 121 linked_item_t *it; 122 for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next){ 123 if ( ! BD_ADDR_CMP( ((hci_connection_t *) it)->address, address) ){ 124 return (hci_connection_t *) it; 125 } 126 } 127 return NULL; 128 } 129 130 /** 131 * count connections 132 */ 133 static int nr_hci_connections(){ 134 int count = 0; 135 linked_item_t *it; 136 for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next, count++); 137 return count; 138 } 139 140 /** 141 * Dummy handler called by HCI 142 */ 143 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ 144 } 145 146 /** 147 * Dummy control handler 148 */ 149 static int null_control_function(void *config){ 150 return 0; 151 } 152 static const char * null_control_name(void *config){ 153 return "Hardware unknown"; 154 } 155 static bt_control_t null_control = { 156 null_control_function, 157 null_control_function, 158 null_control_function, 159 null_control_name 160 }; 161 162 uint8_t hci_number_outgoing_packets(hci_con_handle_t handle){ 163 hci_connection_t * connection = connection_for_handle(handle); 164 if (!connection) { 165 log_err("hci_number_outgoing_packets connectino for handle %u does not exist!\n", handle); 166 return 0; 167 } 168 return connection->num_acl_packets_sent; 169 } 170 171 uint8_t hci_number_free_acl_slots(){ 172 uint8_t free_slots = hci_stack.total_num_acl_packets; 173 linked_item_t *it; 174 for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next){ 175 hci_connection_t * connection = (hci_connection_t *) it; 176 if (free_slots < connection->num_acl_packets_sent) { 177 log_err("hci_number_free_acl_slots: sum of outgoing packets > total acl packets!\n"); 178 return 0; 179 } 180 free_slots -= connection->num_acl_packets_sent; 181 } 182 return free_slots; 183 } 184 185 int hci_ready_to_send(hci_con_handle_t handle){ 186 return hci_number_free_acl_slots() && hci_number_outgoing_packets(handle) < 2; 187 } 188 189 int hci_send_acl_packet(uint8_t *packet, int size){ 190 191 // check for free places on BT module 192 if (!hci_number_free_acl_slots()) return -1; 193 194 hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(packet); 195 hci_connection_t *connection = connection_for_handle( con_handle); 196 if (!connection) return 0; 197 hci_connection_timestamp(connection); 198 199 // count packet 200 connection->num_acl_packets_sent++; 201 // log_dbg("hci_send_acl_packet - handle %u, sent %u\n", connection->con_handle, connection->num_acl_packets_sent); 202 203 // send packet - ignore errors 204 hci_stack.hci_transport->send_acl_packet(packet, size); 205 206 return 0; 207 } 208 209 static void acl_handler(uint8_t *packet, int size){ 210 211 // get info 212 hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(packet); 213 hci_connection_t *conn = connection_for_handle(con_handle); 214 uint8_t acl_flags = READ_ACL_FLAGS(packet); 215 uint16_t acl_length = READ_ACL_LENGTH(packet); 216 217 // ignore non-registered handle 218 if (!conn){ 219 log_err( "hci.c: acl_handler called with non-registered handle %u!\n" , con_handle); 220 return; 221 } 222 223 // update idle timestamp 224 hci_connection_timestamp(conn); 225 226 // handle different packet types 227 switch (acl_flags & 0x03) { 228 229 case 0x01: // continuation fragment 230 231 // sanity check 232 if (conn->acl_recombination_pos == 0) { 233 log_err( "ACL Cont Fragment but no first fragment for handle 0x%02x\n", con_handle); 234 return; 235 } 236 237 // append fragment payload (header already stored) 238 memcpy(&conn->acl_recombination_buffer[conn->acl_recombination_pos], &packet[4], acl_length ); 239 conn->acl_recombination_pos += acl_length; 240 241 // log_err( "ACL Cont Fragment: acl_len %u, combined_len %u, l2cap_len %u\n", 242 // acl_length, connection->acl_recombination_pos, connection->acl_recombination_length); 243 244 // forward complete L2CAP packet if complete. 245 if (conn->acl_recombination_pos >= conn->acl_recombination_length + 4 + 4){ // pos already incl. ACL header 246 247 hci_stack.packet_handler(HCI_ACL_DATA_PACKET, conn->acl_recombination_buffer, conn->acl_recombination_pos); 248 // reset recombination buffer 249 conn->acl_recombination_length = 0; 250 conn->acl_recombination_pos = 0; 251 } 252 break; 253 254 case 0x02: { // first fragment 255 256 // sanity check 257 if (conn->acl_recombination_pos) { 258 log_err( "ACL First Fragment but data in buffer for handle 0x%02x\n", con_handle); 259 return; 260 } 261 262 // peek into L2CAP packet! 263 uint16_t l2cap_length = READ_L2CAP_LENGTH( packet ); 264 265 // compare fragment size to L2CAP packet size 266 if (acl_length >= l2cap_length + 4){ 267 268 // forward fragment as L2CAP packet 269 hci_stack.packet_handler(HCI_ACL_DATA_PACKET, packet, acl_length + 4); 270 271 } else { 272 // store first fragment and tweak acl length for complete package 273 memcpy(conn->acl_recombination_buffer, packet, acl_length + 4); 274 conn->acl_recombination_pos = acl_length + 4; 275 conn->acl_recombination_length = l2cap_length; 276 bt_store_16(conn->acl_recombination_buffer, 2, acl_length +4); 277 // log_err( "ACL First Fragment: acl_len %u, l2cap_len %u\n", acl_length, l2cap_length); 278 } 279 break; 280 281 } 282 default: 283 log_err( "hci.c: acl_handler called with invalid packet boundary flags %u\n", acl_flags & 0x03); 284 return; 285 } 286 287 // execute main loop 288 hci_run(); 289 } 290 291 static void event_handler(uint8_t *packet, int size){ 292 bd_addr_t addr; 293 hci_con_handle_t handle; 294 hci_connection_t * conn; 295 int i; 296 297 // get num_cmd_packets 298 if (packet[0] == HCI_EVENT_COMMAND_COMPLETE || packet[0] == HCI_EVENT_COMMAND_STATUS){ 299 // Get Num_HCI_Command_Packets 300 hci_stack.num_cmd_packets = packet[2]; 301 } 302 303 switch (packet[0]) { 304 305 case HCI_EVENT_COMMAND_COMPLETE: 306 if (COMMAND_COMPLETE_EVENT(packet, hci_read_buffer_size)){ 307 // from offset 5 308 // status 309 hci_stack.acl_data_packet_length = READ_BT_16(packet, 6); 310 // ignore: SCO data packet len (8) 311 hci_stack.total_num_acl_packets = packet[9]; 312 // ignore: total num SCO packets 313 if (hci_stack.state == HCI_STATE_INITIALIZING){ 314 log_dbg("hci_read_buffer_size: size %u, count %u\n", hci_stack.acl_data_packet_length, hci_stack.total_num_acl_packets); 315 } 316 } 317 break; 318 319 case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS: 320 for (i=0; i<packet[2];i++){ 321 handle = READ_BT_16(packet, 3 + 2*i); 322 uint16_t num_packets = READ_BT_16(packet, 3 + packet[2]*2 + 2*i); 323 conn = connection_for_handle(handle); 324 if (!conn){ 325 log_err("hci_number_completed_packet lists unused con handle %u\n", handle); 326 continue; 327 } 328 conn->num_acl_packets_sent -= num_packets; 329 // log_dbg("hci_number_completed_packet %u processed for handle %u, outstanding %u\n", num_packets, handle, conn->num_acl_packets_sent); 330 } 331 break; 332 333 case HCI_EVENT_CONNECTION_REQUEST: 334 bt_flip_addr(addr, &packet[2]); 335 // TODO: eval COD 8-10 336 uint8_t link_type = packet[11]; 337 log_dbg("Connection_incoming: "); print_bd_addr(addr); log_dbg(", type %u\n", link_type); 338 if (link_type == 1) { // ACL 339 conn = connection_for_address(addr); 340 if (!conn) { 341 conn = create_connection_for_addr(addr); 342 } 343 // TODO: check for malloc failure 344 conn->state = ACCEPTED_CONNECTION_REQUEST; 345 hci_send_cmd(&hci_accept_connection_request, addr, 1); 346 } else { 347 // TODO: decline request 348 } 349 break; 350 351 case HCI_EVENT_CONNECTION_COMPLETE: 352 // Connection management 353 bt_flip_addr(addr, &packet[5]); 354 log_dbg("Connection_complete (status=%u)", packet[2]); print_bd_addr(addr); log_dbg("\n"); 355 conn = connection_for_address(addr); 356 if (conn) { 357 if (!packet[2]){ 358 conn->state = OPEN; 359 conn->con_handle = READ_BT_16(packet, 3); 360 conn->flags = 0; 361 362 gettimeofday(&conn->timestamp, NULL); 363 run_loop_set_timer(&conn->timeout, HCI_CONNECTION_TIMEOUT_MS); 364 run_loop_add_timer(&conn->timeout); 365 366 log_dbg("New connection: handle %u, ", conn->con_handle); 367 print_bd_addr( conn->address ); 368 log_dbg("\n"); 369 370 hci_emit_nr_connections_changed(); 371 } else { 372 // connection failed, remove entry 373 linked_list_remove(&hci_stack.connections, (linked_item_t *) conn); 374 free( conn ); 375 } 376 } 377 break; 378 379 case HCI_EVENT_DISCONNECTION_COMPLETE: 380 if (!packet[2]){ 381 handle = READ_BT_16(packet, 3); 382 hci_connection_t * conn = connection_for_handle(handle); 383 if (conn) { 384 log_dbg("Connection closed: handle %u, ", conn->con_handle); 385 print_bd_addr( conn->address ); 386 log_dbg("\n"); 387 run_loop_remove_timer(&conn->timeout); 388 linked_list_remove(&hci_stack.connections, (linked_item_t *) conn); 389 free( conn ); 390 hci_emit_nr_connections_changed(); 391 } 392 } 393 break; 394 395 default: 396 break; 397 } 398 399 // handle BT initialization 400 if (hci_stack.state == HCI_STATE_INITIALIZING){ 401 // handle H4 synchronization loss on restart 402 // if (hci_stack.substate == 1 && packet[0] == HCI_EVENT_HARDWARE_ERROR){ 403 // hci_stack.substate = 0; 404 // } 405 // handle normal init sequence 406 if (hci_stack.substate % 2){ 407 // odd: waiting for event 408 if (packet[0] == HCI_EVENT_COMMAND_COMPLETE){ 409 hci_stack.substate++; 410 } 411 } 412 } 413 414 hci_stack.packet_handler(HCI_EVENT_PACKET, packet, size); 415 416 // execute main loop 417 hci_run(); 418 } 419 420 void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){ 421 switch (packet_type) { 422 case HCI_EVENT_PACKET: 423 event_handler(packet, size); 424 break; 425 case HCI_ACL_DATA_PACKET: 426 acl_handler(packet, size); 427 break; 428 default: 429 break; 430 } 431 } 432 433 /** Register HCI packet handlers */ 434 void hci_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ 435 hci_stack.packet_handler = handler; 436 } 437 438 void hci_init(hci_transport_t *transport, void *config, bt_control_t *control){ 439 440 // reference to use transport layer implementation 441 hci_stack.hci_transport = transport; 442 443 // references to used control implementation 444 if (control) { 445 hci_stack.control = control; 446 } else { 447 hci_stack.control = &null_control; 448 } 449 450 // reference to used config 451 hci_stack.config = config; 452 453 // no connections yet 454 hci_stack.connections = NULL; 455 456 // empty cmd buffer 457 hci_stack.hci_cmd_buffer = malloc(3+255); 458 459 // higher level handler 460 hci_stack.packet_handler = dummy_handler; 461 462 // register packet handlers with transport 463 transport->register_packet_handler(&packet_handler); 464 } 465 466 int hci_power_control(HCI_POWER_MODE power_mode){ 467 if (power_mode == HCI_POWER_ON && hci_stack.state == HCI_STATE_OFF) { 468 469 // power on 470 int err = hci_stack.control->on(hci_stack.config); 471 if (err){ 472 log_err( "POWER_ON failed\n"); 473 hci_emit_hci_open_failed(); 474 return err; 475 } 476 477 // open low-level device 478 err = hci_stack.hci_transport->open(hci_stack.config); 479 if (err){ 480 log_err( "HCI_INIT failed, turning Bluetooth off again\n"); 481 hci_stack.control->off(hci_stack.config); 482 hci_emit_hci_open_failed(); 483 return err; 484 } 485 486 // set up state machine 487 hci_stack.num_cmd_packets = 1; // assume that one cmd can be sent 488 hci_stack.state = HCI_STATE_INITIALIZING; 489 hci_stack.substate = 0; 490 491 } else if (power_mode == HCI_POWER_OFF && hci_stack.state == HCI_STATE_WORKING){ 492 493 // close low-level device 494 hci_stack.hci_transport->close(hci_stack.config); 495 496 // power off 497 hci_stack.control->off(hci_stack.config); 498 499 // we're off now 500 hci_stack.state = HCI_STATE_OFF; 501 } 502 503 // create internal event 504 hci_emit_state(); 505 506 // trigger next/first action 507 hci_run(); 508 509 return 0; 510 } 511 512 void hci_run(){ 513 switch (hci_stack.state){ 514 case HCI_STATE_INITIALIZING: 515 if (hci_stack.substate % 2) { 516 // odd: waiting for command completion 517 return; 518 } 519 if (hci_stack.num_cmd_packets == 0) { 520 // cannot send command yet 521 return; 522 } 523 switch (hci_stack.substate >> 1){ 524 case 0: 525 hci_send_cmd(&hci_reset); 526 break; 527 case 1: 528 // custom initialization 529 if (hci_stack.control && hci_stack.control->next_command){ 530 uint8_t * cmd = (*hci_stack.control->next_command)(hci_stack.config); 531 if (cmd) { 532 int size = 3 + cmd[2]; 533 hci_stack.hci_transport->send_cmd_packet(cmd, size); 534 break; 535 } 536 } 537 // @NOTE fall through, if no command to send anymore 538 hci_stack.substate += 2; 539 case 2: 540 hci_send_cmd(&hci_read_bd_addr); 541 break; 542 case 3: 543 hci_send_cmd(&hci_read_buffer_size); 544 break; 545 case 4: 546 // ca. 15 sec 547 hci_send_cmd(&hci_write_page_timeout, 0x6000); 548 break; 549 case 5: 550 hci_send_cmd(&hci_write_scan_enable, 3); // 3 inq scan + page scan 551 break; 552 case 6: 553 // done. 554 hci_stack.state = HCI_STATE_WORKING; 555 hci_emit_state(); 556 break; 557 default: 558 break; 559 } 560 hci_stack.substate++; 561 break; 562 default: 563 break; 564 } 565 } 566 567 int hci_send_cmd_packet(uint8_t *packet, int size){ 568 bd_addr_t addr; 569 hci_connection_t * conn; 570 // house-keeping 571 572 // create_connection? 573 if (IS_COMMAND(packet, hci_create_connection)){ 574 bt_flip_addr(addr, &packet[3]); 575 log_dbg("Create_connection to "); print_bd_addr(addr); log_dbg("\n"); 576 conn = connection_for_address(addr); 577 if (conn) { 578 // if connection exists 579 if (conn->state == OPEN) { 580 // if OPEN, emit connection complete command 581 hci_emit_connection_complete(conn); 582 } 583 // otherwise, just ignore 584 return 0; // don't sent packet to controller 585 586 } else{ 587 conn = create_connection_for_addr(addr); 588 if (conn){ 589 // create connection struct and register, state = SENT_CREATE_CONNECTION 590 conn->state = SENT_CREATE_CONNECTION; 591 } 592 } 593 } 594 595 // accept connection 596 597 // reject connection 598 599 // close_connection? 600 // set state = SENT_DISCONNECT 601 602 hci_stack.num_cmd_packets--; 603 return hci_stack.hci_transport->send_cmd_packet(packet, size); 604 } 605 606 /** 607 * pre: numcmds >= 0 - it's allowed to send a command to the controller 608 */ 609 int hci_send_cmd(hci_cmd_t *cmd, ...){ 610 va_list argptr; 611 va_start(argptr, cmd); 612 uint8_t * hci_cmd_buffer = hci_stack.hci_cmd_buffer; 613 uint16_t size = hci_create_cmd_internal(hci_stack.hci_cmd_buffer, cmd, argptr); 614 va_end(argptr); 615 return hci_send_cmd_packet(hci_cmd_buffer, size); 616 } 617 618 // Create various non-HCI events. 619 // TODO: generalize, use table similar to hci_create_command 620 621 void hci_emit_state(){ 622 uint8_t len = 3; 623 uint8_t event[len]; 624 event[0] = BTSTACK_EVENT_STATE; 625 event[1] = len - 3; 626 event[2] = hci_stack.state; 627 hci_dump_packet( HCI_EVENT_PACKET, 0, event, len); 628 hci_stack.packet_handler(HCI_EVENT_PACKET, event, len); 629 } 630 631 void hci_emit_connection_complete(hci_connection_t *conn){ 632 uint8_t len = 13; 633 uint8_t event[len]; 634 event[0] = HCI_EVENT_CONNECTION_COMPLETE; 635 event[1] = len - 3; 636 event[2] = 0; // status = OK 637 bt_store_16(event, 3, conn->con_handle); 638 bt_flip_addr(&event[5], conn->address); 639 event[11] = 1; // ACL connection 640 event[12] = 0; // encryption disabled 641 hci_dump_packet( HCI_EVENT_PACKET, 0, event, len); 642 hci_stack.packet_handler(HCI_EVENT_PACKET, event, len); 643 } 644 645 void hci_emit_l2cap_check_timeout(hci_connection_t *conn){ 646 uint8_t len = 4; 647 uint8_t event[len]; 648 event[0] = L2CAP_EVENT_TIMEOUT_CHECK; 649 event[1] = len - 2; 650 bt_store_16(event, 2, conn->con_handle); 651 hci_dump_packet( HCI_EVENT_PACKET, 0, event, len); 652 hci_stack.packet_handler(HCI_EVENT_PACKET, event, len); 653 } 654 655 void hci_emit_nr_connections_changed(){ 656 uint8_t len = 3; 657 uint8_t event[len]; 658 event[0] = BTSTACK_EVENT_NR_CONNECTIONS_CHANGED; 659 event[1] = len - 2; 660 event[2] = nr_hci_connections(); 661 hci_dump_packet( HCI_EVENT_PACKET, 0, event, len); 662 hci_stack.packet_handler(HCI_EVENT_PACKET, event, len); 663 } 664 665 void hci_emit_hci_open_failed(){ 666 uint8_t len = 2; 667 uint8_t event[len]; 668 event[0] = BTSTACK_EVENT_POWERON_FAILED; 669 event[1] = len - 2; 670 hci_dump_packet( HCI_EVENT_PACKET, 0, event, len); 671 hci_stack.packet_handler(HCI_EVENT_PACKET, event, len); 672 } 673 674 675 void hci_emit_btstack_version() { 676 uint8_t len = 6; 677 uint8_t event[len]; 678 event[0] = BTSTACK_EVENT_VERSION; 679 event[1] = len - 2; 680 event[len++] = BTSTACK_MAJOR; 681 event[len++] = BTSTACK_MINOR; 682 bt_store_16(event, len, BTSTACK_REVISION); 683 hci_dump_packet( HCI_EVENT_PACKET, 0, event, len); 684 hci_stack.packet_handler(HCI_EVENT_PACKET, event, len); 685 } 686 687 void hci_emit_system_bluetooth_enabled(uint8_t enabled){ 688 uint8_t len = 3; 689 uint8_t event[len]; 690 event[0] = BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED; 691 event[1] = len - 2; 692 event[2] = enabled; 693 hci_dump_packet( HCI_EVENT_PACKET, 0, event, len); 694 hci_stack.packet_handler(HCI_EVENT_PACKET, event, len); 695 } 696