mbed base bard check program for BlueTooth USB dongle module (3 switches, 6 leds, I2C LCD, A/D)

Dependencies:   USBHost mbed

Fork of BTstack by Norimasa Okamoto

Committer:
va009039
Date:
Fri Mar 22 22:35:57 2013 +0000
Revision:
2:871b41f4789e
Parent:
0:1ed23ab1345f
change to single thread

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:1ed23ab1345f 1 /*
va009039 0:1ed23ab1345f 2 * Copyright (C) 2009-2012 by Matthias Ringwald
va009039 0:1ed23ab1345f 3 *
va009039 0:1ed23ab1345f 4 * Redistribution and use in source and binary forms, with or without
va009039 0:1ed23ab1345f 5 * modification, are permitted provided that the following conditions
va009039 0:1ed23ab1345f 6 * are met:
va009039 0:1ed23ab1345f 7 *
va009039 0:1ed23ab1345f 8 * 1. Redistributions of source code must retain the above copyright
va009039 0:1ed23ab1345f 9 * notice, this list of conditions and the following disclaimer.
va009039 0:1ed23ab1345f 10 * 2. Redistributions in binary form must reproduce the above copyright
va009039 0:1ed23ab1345f 11 * notice, this list of conditions and the following disclaimer in the
va009039 0:1ed23ab1345f 12 * documentation and/or other materials provided with the distribution.
va009039 0:1ed23ab1345f 13 * 3. Neither the name of the copyright holders nor the names of
va009039 0:1ed23ab1345f 14 * contributors may be used to endorse or promote products derived
va009039 0:1ed23ab1345f 15 * from this software without specific prior written permission.
va009039 0:1ed23ab1345f 16 * 4. Any redistribution, use, or modification is done solely for
va009039 0:1ed23ab1345f 17 * personal benefit and not for any commercial purpose or for
va009039 0:1ed23ab1345f 18 * monetary gain.
va009039 0:1ed23ab1345f 19 *
va009039 0:1ed23ab1345f 20 * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
va009039 0:1ed23ab1345f 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
va009039 0:1ed23ab1345f 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
va009039 0:1ed23ab1345f 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
va009039 0:1ed23ab1345f 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
va009039 0:1ed23ab1345f 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
va009039 0:1ed23ab1345f 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
va009039 0:1ed23ab1345f 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
va009039 0:1ed23ab1345f 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
va009039 0:1ed23ab1345f 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
va009039 0:1ed23ab1345f 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
va009039 0:1ed23ab1345f 31 * SUCH DAMAGE.
va009039 0:1ed23ab1345f 32 *
va009039 0:1ed23ab1345f 33 * Please inquire about commercial licensing options at btstack@ringwald.ch
va009039 0:1ed23ab1345f 34 *
va009039 0:1ed23ab1345f 35 */
va009039 0:1ed23ab1345f 36
va009039 0:1ed23ab1345f 37 /*
va009039 0:1ed23ab1345f 38 * hci.c
va009039 0:1ed23ab1345f 39 *
va009039 0:1ed23ab1345f 40 * Created by Matthias Ringwald on 4/29/09.
va009039 0:1ed23ab1345f 41 *
va009039 0:1ed23ab1345f 42 */
va009039 0:1ed23ab1345f 43
va009039 0:1ed23ab1345f 44 #include "config.h"
va009039 0:1ed23ab1345f 45
va009039 0:1ed23ab1345f 46 #include "hci.h"
va009039 0:1ed23ab1345f 47
va009039 0:1ed23ab1345f 48 #include <stdarg.h>
va009039 0:1ed23ab1345f 49 #include <string.h>
va009039 0:1ed23ab1345f 50 #include <stdio.h>
va009039 0:1ed23ab1345f 51
va009039 0:1ed23ab1345f 52 #ifndef EMBEDDED
va009039 0:1ed23ab1345f 53 #include <unistd.h> // gethostbyname
va009039 0:1ed23ab1345f 54 #include <btstack/version.h>
va009039 0:1ed23ab1345f 55 #endif
va009039 0:1ed23ab1345f 56
va009039 0:1ed23ab1345f 57 #include "btstack_memory.h"
va009039 0:1ed23ab1345f 58 #include "debug.h"
va009039 0:1ed23ab1345f 59 #include "hci_dump.h"
va009039 0:1ed23ab1345f 60
va009039 0:1ed23ab1345f 61 #include <btstack/hci_cmds.h>
va009039 0:1ed23ab1345f 62
va009039 0:1ed23ab1345f 63 #define HCI_CONNECTION_TIMEOUT_MS 10000
va009039 0:1ed23ab1345f 64
va009039 0:1ed23ab1345f 65 #ifdef USE_BLUETOOL
va009039 0:1ed23ab1345f 66 #include "bt_control_iphone.h"
va009039 0:1ed23ab1345f 67 #endif
va009039 0:1ed23ab1345f 68
va009039 0:1ed23ab1345f 69 static void hci_update_scan_enable(void);
va009039 0:1ed23ab1345f 70
va009039 0:1ed23ab1345f 71 // the STACK is here
va009039 0:1ed23ab1345f 72 static hci_stack_t hci_stack;
va009039 0:1ed23ab1345f 73
va009039 0:1ed23ab1345f 74 /**
va009039 0:1ed23ab1345f 75 * get connection for a given handle
va009039 0:1ed23ab1345f 76 *
va009039 0:1ed23ab1345f 77 * @return connection OR NULL, if not found
va009039 0:1ed23ab1345f 78 */
va009039 0:1ed23ab1345f 79 hci_connection_t * connection_for_handle(hci_con_handle_t con_handle){
va009039 0:1ed23ab1345f 80 linked_item_t *it;
va009039 0:1ed23ab1345f 81 for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next){
va009039 0:1ed23ab1345f 82 if ( ((hci_connection_t *) it)->con_handle == con_handle){
va009039 0:1ed23ab1345f 83 return (hci_connection_t *) it;
va009039 0:1ed23ab1345f 84 }
va009039 0:1ed23ab1345f 85 }
va009039 0:1ed23ab1345f 86 return NULL;
va009039 0:1ed23ab1345f 87 }
va009039 0:1ed23ab1345f 88
va009039 0:1ed23ab1345f 89 static void hci_connection_timeout_handler(timer_source_t *timer){
va009039 0:1ed23ab1345f 90 hci_connection_t * connection = (hci_connection_t *) linked_item_get_user(&timer->item);
va009039 0:1ed23ab1345f 91 #ifdef HAVE_TIME
va009039 0:1ed23ab1345f 92 struct timeval tv;
va009039 0:1ed23ab1345f 93 gettimeofday(&tv, NULL);
va009039 0:1ed23ab1345f 94 if (tv.tv_sec >= connection->timestamp.tv_sec + HCI_CONNECTION_TIMEOUT_MS/1000) {
va009039 0:1ed23ab1345f 95 // connections might be timed out
va009039 0:1ed23ab1345f 96 hci_emit_l2cap_check_timeout(connection);
va009039 0:1ed23ab1345f 97 }
va009039 0:1ed23ab1345f 98 #endif
va009039 0:1ed23ab1345f 99 #ifdef HAVE_TICK
va009039 0:1ed23ab1345f 100 if (embedded_get_ticks() > connection->timestamp + embedded_ticks_for_ms(HCI_CONNECTION_TIMEOUT_MS)){
va009039 0:1ed23ab1345f 101 // connections might be timed out
va009039 0:1ed23ab1345f 102 hci_emit_l2cap_check_timeout(connection);
va009039 0:1ed23ab1345f 103 }
va009039 0:1ed23ab1345f 104 #endif
va009039 0:1ed23ab1345f 105 run_loop_set_timer(timer, HCI_CONNECTION_TIMEOUT_MS);
va009039 0:1ed23ab1345f 106 run_loop_add_timer(timer);
va009039 0:1ed23ab1345f 107 }
va009039 0:1ed23ab1345f 108
va009039 0:1ed23ab1345f 109 static void hci_connection_timestamp(hci_connection_t *connection){
va009039 0:1ed23ab1345f 110 #ifdef HAVE_TIME
va009039 0:1ed23ab1345f 111 gettimeofday(&connection->timestamp, NULL);
va009039 0:1ed23ab1345f 112 #endif
va009039 0:1ed23ab1345f 113 #ifdef HAVE_TICK
va009039 0:1ed23ab1345f 114 connection->timestamp = embedded_get_ticks();
va009039 0:1ed23ab1345f 115 #endif
va009039 0:1ed23ab1345f 116 }
va009039 0:1ed23ab1345f 117
va009039 0:1ed23ab1345f 118 /**
va009039 0:1ed23ab1345f 119 * create connection for given address
va009039 0:1ed23ab1345f 120 *
va009039 0:1ed23ab1345f 121 * @return connection OR NULL, if no memory left
va009039 0:1ed23ab1345f 122 */
va009039 0:1ed23ab1345f 123 static hci_connection_t * create_connection_for_addr(bd_addr_t addr){
va009039 0:1ed23ab1345f 124 hci_connection_t * conn = (hci_connection_t *) btstack_memory_hci_connection_get();
va009039 0:1ed23ab1345f 125 if (!conn) return NULL;
va009039 0:1ed23ab1345f 126 BD_ADDR_COPY(conn->address, addr);
va009039 0:1ed23ab1345f 127 conn->con_handle = 0xffff;
va009039 0:1ed23ab1345f 128 conn->authentication_flags = AUTH_FLAGS_NONE;
va009039 0:1ed23ab1345f 129 linked_item_set_user(&conn->timeout.item, conn);
va009039 0:1ed23ab1345f 130 conn->timeout.process = hci_connection_timeout_handler;
va009039 0:1ed23ab1345f 131 hci_connection_timestamp(conn);
va009039 0:1ed23ab1345f 132 conn->acl_recombination_length = 0;
va009039 0:1ed23ab1345f 133 conn->acl_recombination_pos = 0;
va009039 0:1ed23ab1345f 134 conn->num_acl_packets_sent = 0;
va009039 0:1ed23ab1345f 135 linked_list_add(&hci_stack.connections, (linked_item_t *) conn);
va009039 0:1ed23ab1345f 136 return conn;
va009039 0:1ed23ab1345f 137 }
va009039 0:1ed23ab1345f 138
va009039 0:1ed23ab1345f 139 /**
va009039 0:1ed23ab1345f 140 * get connection for given address
va009039 0:1ed23ab1345f 141 *
va009039 0:1ed23ab1345f 142 * @return connection OR NULL, if not found
va009039 0:1ed23ab1345f 143 */
va009039 0:1ed23ab1345f 144 static hci_connection_t * connection_for_address(bd_addr_t address){
va009039 0:1ed23ab1345f 145 linked_item_t *it;
va009039 0:1ed23ab1345f 146 for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next){
va009039 0:1ed23ab1345f 147 if ( ! BD_ADDR_CMP( ((hci_connection_t *) it)->address, address) ){
va009039 0:1ed23ab1345f 148 return (hci_connection_t *) it;
va009039 0:1ed23ab1345f 149 }
va009039 0:1ed23ab1345f 150 }
va009039 0:1ed23ab1345f 151 return NULL;
va009039 0:1ed23ab1345f 152 }
va009039 0:1ed23ab1345f 153
va009039 0:1ed23ab1345f 154 inline static void connectionSetAuthenticationFlags(hci_connection_t * conn, hci_authentication_flags_t flags){
va009039 0:1ed23ab1345f 155 conn->authentication_flags = (hci_authentication_flags_t)(conn->authentication_flags | flags);
va009039 0:1ed23ab1345f 156 }
va009039 0:1ed23ab1345f 157
va009039 0:1ed23ab1345f 158 inline static void connectionClearAuthenticationFlags(hci_connection_t * conn, hci_authentication_flags_t flags){
va009039 0:1ed23ab1345f 159 conn->authentication_flags = (hci_authentication_flags_t)(conn->authentication_flags & ~flags);
va009039 0:1ed23ab1345f 160 }
va009039 0:1ed23ab1345f 161
va009039 0:1ed23ab1345f 162
va009039 0:1ed23ab1345f 163 /**
va009039 0:1ed23ab1345f 164 * add authentication flags and reset timer
va009039 0:1ed23ab1345f 165 */
va009039 0:1ed23ab1345f 166 static void hci_add_connection_flags_for_flipped_bd_addr(uint8_t *bd_addr, hci_authentication_flags_t flags){
va009039 0:1ed23ab1345f 167 bd_addr_t addr;
va009039 0:1ed23ab1345f 168 bt_flip_addr(addr, *(bd_addr_t *) bd_addr);
va009039 0:1ed23ab1345f 169 hci_connection_t * conn = connection_for_address(addr);
va009039 0:1ed23ab1345f 170 if (conn) {
va009039 0:1ed23ab1345f 171 connectionSetAuthenticationFlags(conn, flags);
va009039 0:1ed23ab1345f 172 hci_connection_timestamp(conn);
va009039 0:1ed23ab1345f 173 }
va009039 0:1ed23ab1345f 174 }
va009039 0:1ed23ab1345f 175
va009039 0:1ed23ab1345f 176 int hci_authentication_active_for_handle(hci_con_handle_t handle){
va009039 0:1ed23ab1345f 177 hci_connection_t * conn = connection_for_handle(handle);
va009039 0:1ed23ab1345f 178 if (!conn) return 0;
va009039 0:1ed23ab1345f 179 if (!conn->authentication_flags) return 0;
va009039 0:1ed23ab1345f 180 if (conn->authentication_flags & SENT_LINK_KEY_REPLY) return 0;
va009039 0:1ed23ab1345f 181 if (conn->authentication_flags & RECV_LINK_KEY_NOTIFICATION) return 0;
va009039 0:1ed23ab1345f 182 return 1;
va009039 0:1ed23ab1345f 183 }
va009039 0:1ed23ab1345f 184
va009039 0:1ed23ab1345f 185 void hci_drop_link_key_for_bd_addr(bd_addr_t *addr){
va009039 0:1ed23ab1345f 186 if (hci_stack.remote_device_db) {
va009039 0:1ed23ab1345f 187 hci_stack.remote_device_db->delete_link_key(addr);
va009039 0:1ed23ab1345f 188 }
va009039 0:1ed23ab1345f 189 }
va009039 0:1ed23ab1345f 190
va009039 0:1ed23ab1345f 191
va009039 0:1ed23ab1345f 192 /**
va009039 0:1ed23ab1345f 193 * count connections
va009039 0:1ed23ab1345f 194 */
va009039 0:1ed23ab1345f 195 static int nr_hci_connections(void){
va009039 0:1ed23ab1345f 196 int count = 0;
va009039 0:1ed23ab1345f 197 linked_item_t *it;
va009039 0:1ed23ab1345f 198 for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next, count++);
va009039 0:1ed23ab1345f 199 return count;
va009039 0:1ed23ab1345f 200 }
va009039 0:1ed23ab1345f 201
va009039 0:1ed23ab1345f 202 /**
va009039 0:1ed23ab1345f 203 * Dummy handler called by HCI
va009039 0:1ed23ab1345f 204 */
va009039 0:1ed23ab1345f 205 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
va009039 0:1ed23ab1345f 206 }
va009039 0:1ed23ab1345f 207
va009039 0:1ed23ab1345f 208 uint8_t hci_number_outgoing_packets(hci_con_handle_t handle){
va009039 0:1ed23ab1345f 209 hci_connection_t * connection = connection_for_handle(handle);
va009039 0:1ed23ab1345f 210 if (!connection) {
va009039 0:1ed23ab1345f 211 log_error("hci_number_outgoing_packets connectino for handle %u does not exist!\n", handle);
va009039 0:1ed23ab1345f 212 return 0;
va009039 0:1ed23ab1345f 213 }
va009039 0:1ed23ab1345f 214 return connection->num_acl_packets_sent;
va009039 0:1ed23ab1345f 215 }
va009039 0:1ed23ab1345f 216
va009039 0:1ed23ab1345f 217 uint8_t hci_number_free_acl_slots(){
va009039 0:1ed23ab1345f 218 uint8_t free_slots = hci_stack.total_num_acl_packets;
va009039 0:1ed23ab1345f 219 linked_item_t *it;
va009039 0:1ed23ab1345f 220 for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next){
va009039 0:1ed23ab1345f 221 hci_connection_t * connection = (hci_connection_t *) it;
va009039 0:1ed23ab1345f 222 if (free_slots < connection->num_acl_packets_sent) {
va009039 0:1ed23ab1345f 223 log_error("hci_number_free_acl_slots: sum of outgoing packets > total acl packets!\n");
va009039 0:1ed23ab1345f 224 return 0;
va009039 0:1ed23ab1345f 225 }
va009039 0:1ed23ab1345f 226 free_slots -= connection->num_acl_packets_sent;
va009039 0:1ed23ab1345f 227 }
va009039 0:1ed23ab1345f 228 return free_slots;
va009039 0:1ed23ab1345f 229 }
va009039 0:1ed23ab1345f 230
va009039 0:1ed23ab1345f 231 int hci_can_send_packet_now(uint8_t packet_type){
va009039 0:1ed23ab1345f 232
va009039 0:1ed23ab1345f 233 // check for async hci transport implementations
va009039 0:1ed23ab1345f 234 if (hci_stack.hci_transport->can_send_packet_now){
va009039 0:1ed23ab1345f 235 if (!hci_stack.hci_transport->can_send_packet_now(packet_type)){
va009039 0:1ed23ab1345f 236 return 0;
va009039 0:1ed23ab1345f 237 }
va009039 0:1ed23ab1345f 238 }
va009039 0:1ed23ab1345f 239
va009039 0:1ed23ab1345f 240 // check regular Bluetooth flow control
va009039 0:1ed23ab1345f 241 switch (packet_type) {
va009039 0:1ed23ab1345f 242 case HCI_ACL_DATA_PACKET:
va009039 0:1ed23ab1345f 243 return hci_number_free_acl_slots();
va009039 0:1ed23ab1345f 244 case HCI_COMMAND_DATA_PACKET:
va009039 0:1ed23ab1345f 245 return hci_stack.num_cmd_packets;
va009039 0:1ed23ab1345f 246 default:
va009039 0:1ed23ab1345f 247 return 0;
va009039 0:1ed23ab1345f 248 }
va009039 0:1ed23ab1345f 249 }
va009039 0:1ed23ab1345f 250
va009039 0:1ed23ab1345f 251 int hci_send_acl_packet(uint8_t *packet, int size){
va009039 0:1ed23ab1345f 252
va009039 0:1ed23ab1345f 253 // check for free places on BT module
va009039 0:1ed23ab1345f 254 if (!hci_number_free_acl_slots()) return BTSTACK_ACL_BUFFERS_FULL;
va009039 0:1ed23ab1345f 255
va009039 0:1ed23ab1345f 256 hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(packet);
va009039 0:1ed23ab1345f 257 hci_connection_t *connection = connection_for_handle( con_handle);
va009039 0:1ed23ab1345f 258 if (!connection) return 0;
va009039 0:1ed23ab1345f 259 hci_connection_timestamp(connection);
va009039 0:1ed23ab1345f 260
va009039 0:1ed23ab1345f 261 // count packet
va009039 0:1ed23ab1345f 262 connection->num_acl_packets_sent++;
va009039 0:1ed23ab1345f 263 // log_info("hci_send_acl_packet - handle %u, sent %u\n", connection->con_handle, connection->num_acl_packets_sent);
va009039 0:1ed23ab1345f 264
va009039 0:1ed23ab1345f 265 // send packet
va009039 0:1ed23ab1345f 266 int err = hci_stack.hci_transport->send_packet(HCI_ACL_DATA_PACKET, packet, size);
va009039 0:1ed23ab1345f 267
va009039 0:1ed23ab1345f 268 return err;
va009039 0:1ed23ab1345f 269 }
va009039 0:1ed23ab1345f 270
va009039 0:1ed23ab1345f 271 static void acl_handler(uint8_t *packet, int size){
va009039 0:1ed23ab1345f 272
va009039 0:1ed23ab1345f 273 // get info
va009039 0:1ed23ab1345f 274 hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(packet);
va009039 0:1ed23ab1345f 275 hci_connection_t *conn = connection_for_handle(con_handle);
va009039 0:1ed23ab1345f 276 uint8_t acl_flags = READ_ACL_FLAGS(packet);
va009039 0:1ed23ab1345f 277 uint16_t acl_length = READ_ACL_LENGTH(packet);
va009039 0:1ed23ab1345f 278
va009039 0:1ed23ab1345f 279 // ignore non-registered handle
va009039 0:1ed23ab1345f 280 if (!conn){
va009039 0:1ed23ab1345f 281 log_error( "hci.c: acl_handler called with non-registered handle %u!\n" , con_handle);
va009039 0:1ed23ab1345f 282 return;
va009039 0:1ed23ab1345f 283 }
va009039 0:1ed23ab1345f 284
va009039 0:1ed23ab1345f 285 // update idle timestamp
va009039 0:1ed23ab1345f 286 hci_connection_timestamp(conn);
va009039 0:1ed23ab1345f 287
va009039 0:1ed23ab1345f 288 // handle different packet types
va009039 0:1ed23ab1345f 289 switch (acl_flags & 0x03) {
va009039 0:1ed23ab1345f 290
va009039 0:1ed23ab1345f 291 case 0x01: // continuation fragment
va009039 0:1ed23ab1345f 292
va009039 0:1ed23ab1345f 293 // sanity check
va009039 0:1ed23ab1345f 294 if (conn->acl_recombination_pos == 0) {
va009039 0:1ed23ab1345f 295 log_error( "ACL Cont Fragment but no first fragment for handle 0x%02x\n", con_handle);
va009039 0:1ed23ab1345f 296 return;
va009039 0:1ed23ab1345f 297 }
va009039 0:1ed23ab1345f 298
va009039 0:1ed23ab1345f 299 // append fragment payload (header already stored)
va009039 0:1ed23ab1345f 300 memcpy(&conn->acl_recombination_buffer[conn->acl_recombination_pos], &packet[4], acl_length );
va009039 0:1ed23ab1345f 301 conn->acl_recombination_pos += acl_length;
va009039 0:1ed23ab1345f 302
va009039 0:1ed23ab1345f 303 // log_error( "ACL Cont Fragment: acl_len %u, combined_len %u, l2cap_len %u\n", acl_length,
va009039 0:1ed23ab1345f 304 // conn->acl_recombination_pos, conn->acl_recombination_length);
va009039 0:1ed23ab1345f 305
va009039 0:1ed23ab1345f 306 // forward complete L2CAP packet if complete.
va009039 0:1ed23ab1345f 307 if (conn->acl_recombination_pos >= conn->acl_recombination_length + 4 + 4){ // pos already incl. ACL header
va009039 0:1ed23ab1345f 308
va009039 0:1ed23ab1345f 309 hci_stack.packet_handler(HCI_ACL_DATA_PACKET, conn->acl_recombination_buffer, conn->acl_recombination_pos);
va009039 0:1ed23ab1345f 310 // reset recombination buffer
va009039 0:1ed23ab1345f 311 conn->acl_recombination_length = 0;
va009039 0:1ed23ab1345f 312 conn->acl_recombination_pos = 0;
va009039 0:1ed23ab1345f 313 }
va009039 0:1ed23ab1345f 314 break;
va009039 0:1ed23ab1345f 315
va009039 0:1ed23ab1345f 316 case 0x02: { // first fragment
va009039 0:1ed23ab1345f 317
va009039 0:1ed23ab1345f 318 // sanity check
va009039 0:1ed23ab1345f 319 if (conn->acl_recombination_pos) {
va009039 0:1ed23ab1345f 320 log_error( "ACL First Fragment but data in buffer for handle 0x%02x\n", con_handle);
va009039 0:1ed23ab1345f 321 return;
va009039 0:1ed23ab1345f 322 }
va009039 0:1ed23ab1345f 323
va009039 0:1ed23ab1345f 324 // peek into L2CAP packet!
va009039 0:1ed23ab1345f 325 uint16_t l2cap_length = READ_L2CAP_LENGTH( packet );
va009039 0:1ed23ab1345f 326
va009039 0:1ed23ab1345f 327 // log_error( "ACL First Fragment: acl_len %u, l2cap_len %u\n", acl_length, l2cap_length);
va009039 0:1ed23ab1345f 328
va009039 0:1ed23ab1345f 329 // compare fragment size to L2CAP packet size
va009039 0:1ed23ab1345f 330 if (acl_length >= l2cap_length + 4){
va009039 0:1ed23ab1345f 331
va009039 0:1ed23ab1345f 332 // forward fragment as L2CAP packet
va009039 0:1ed23ab1345f 333 hci_stack.packet_handler(HCI_ACL_DATA_PACKET, packet, acl_length + 4);
va009039 0:1ed23ab1345f 334
va009039 0:1ed23ab1345f 335 } else {
va009039 0:1ed23ab1345f 336 // store first fragment and tweak acl length for complete package
va009039 0:1ed23ab1345f 337 memcpy(conn->acl_recombination_buffer, packet, acl_length + 4);
va009039 0:1ed23ab1345f 338 conn->acl_recombination_pos = acl_length + 4;
va009039 0:1ed23ab1345f 339 conn->acl_recombination_length = l2cap_length;
va009039 0:1ed23ab1345f 340 bt_store_16(conn->acl_recombination_buffer, 2, l2cap_length +4);
va009039 0:1ed23ab1345f 341 }
va009039 0:1ed23ab1345f 342 break;
va009039 0:1ed23ab1345f 343
va009039 0:1ed23ab1345f 344 }
va009039 0:1ed23ab1345f 345 default:
va009039 0:1ed23ab1345f 346 log_error( "hci.c: acl_handler called with invalid packet boundary flags %u\n", acl_flags & 0x03);
va009039 0:1ed23ab1345f 347 return;
va009039 0:1ed23ab1345f 348 }
va009039 0:1ed23ab1345f 349
va009039 0:1ed23ab1345f 350 // execute main loop
va009039 0:1ed23ab1345f 351 hci_run();
va009039 0:1ed23ab1345f 352 }
va009039 0:1ed23ab1345f 353
va009039 0:1ed23ab1345f 354 static void hci_shutdown_connection(hci_connection_t *conn){
va009039 0:1ed23ab1345f 355 log_info("Connection closed: handle %u, %s\n", conn->con_handle, bd_addr_to_str(conn->address));
va009039 0:1ed23ab1345f 356
va009039 0:1ed23ab1345f 357 // cancel all l2cap connections
va009039 0:1ed23ab1345f 358 hci_emit_disconnection_complete(conn->con_handle, 0x16); // terminated by local host
va009039 0:1ed23ab1345f 359
va009039 0:1ed23ab1345f 360 run_loop_remove_timer(&conn->timeout);
va009039 0:1ed23ab1345f 361
va009039 0:1ed23ab1345f 362 linked_list_remove(&hci_stack.connections, (linked_item_t *) conn);
va009039 0:1ed23ab1345f 363 btstack_memory_hci_connection_free( conn );
va009039 0:1ed23ab1345f 364
va009039 0:1ed23ab1345f 365 // now it's gone
va009039 0:1ed23ab1345f 366 hci_emit_nr_connections_changed();
va009039 0:1ed23ab1345f 367 }
va009039 0:1ed23ab1345f 368
va009039 0:1ed23ab1345f 369 static const uint16_t packet_type_sizes[] = {
va009039 0:1ed23ab1345f 370 0, HCI_ACL_2DH1_SIZE, HCI_ACL_3DH1_SIZE, HCI_ACL_DM1_SIZE,
va009039 0:1ed23ab1345f 371 HCI_ACL_DH1_SIZE, 0, 0, 0,
va009039 0:1ed23ab1345f 372 HCI_ACL_2DH3_SIZE, HCI_ACL_3DH3_SIZE, HCI_ACL_DM3_SIZE, HCI_ACL_DH3_SIZE,
va009039 0:1ed23ab1345f 373 HCI_ACL_2DH5_SIZE, HCI_ACL_3DH5_SIZE, HCI_ACL_DM5_SIZE, HCI_ACL_DH5_SIZE
va009039 0:1ed23ab1345f 374 };
va009039 0:1ed23ab1345f 375
va009039 0:1ed23ab1345f 376 static uint16_t hci_acl_packet_types_for_buffer_size(uint16_t buffer_size){
va009039 0:1ed23ab1345f 377 uint16_t packet_types = 0;
va009039 0:1ed23ab1345f 378 int i;
va009039 0:1ed23ab1345f 379 for (i=0;i<16;i++){
va009039 0:1ed23ab1345f 380 if (packet_type_sizes[i] == 0) continue;
va009039 0:1ed23ab1345f 381 if (packet_type_sizes[i] <= buffer_size){
va009039 0:1ed23ab1345f 382 packet_types |= 1 << i;
va009039 0:1ed23ab1345f 383 }
va009039 0:1ed23ab1345f 384 }
va009039 0:1ed23ab1345f 385 // flip bits for "may not be used"
va009039 0:1ed23ab1345f 386 packet_types ^= 0x3306;
va009039 0:1ed23ab1345f 387 return packet_types;
va009039 0:1ed23ab1345f 388 }
va009039 0:1ed23ab1345f 389
va009039 0:1ed23ab1345f 390 uint16_t hci_usable_acl_packet_types(void){
va009039 0:1ed23ab1345f 391 return hci_stack.packet_types;
va009039 0:1ed23ab1345f 392 }
va009039 0:1ed23ab1345f 393
va009039 0:1ed23ab1345f 394 uint8_t* hci_get_outgoing_acl_packet_buffer(void){
va009039 0:1ed23ab1345f 395 // hci packet buffer is >= acl data packet length
va009039 0:1ed23ab1345f 396 return hci_stack.hci_packet_buffer;
va009039 0:1ed23ab1345f 397 }
va009039 0:1ed23ab1345f 398
va009039 0:1ed23ab1345f 399 uint16_t hci_max_acl_data_packet_length(){
va009039 0:1ed23ab1345f 400 return hci_stack.acl_data_packet_length;
va009039 0:1ed23ab1345f 401 }
va009039 0:1ed23ab1345f 402
va009039 0:1ed23ab1345f 403 // avoid huge local variables
va009039 0:1ed23ab1345f 404 #ifndef EMBEDDED
va009039 0:1ed23ab1345f 405 static device_name_t device_name;
va009039 0:1ed23ab1345f 406 #endif
va009039 0:1ed23ab1345f 407 static void event_handler(uint8_t *packet, int size){
va009039 0:1ed23ab1345f 408 bd_addr_t addr;
va009039 0:1ed23ab1345f 409 uint8_t link_type;
va009039 0:1ed23ab1345f 410 hci_con_handle_t handle;
va009039 0:1ed23ab1345f 411 hci_connection_t * conn;
va009039 0:1ed23ab1345f 412 int i;
va009039 0:1ed23ab1345f 413
va009039 0:1ed23ab1345f 414 // printf("HCI:EVENT:%02x\n", packet[0]);
va009039 0:1ed23ab1345f 415
va009039 0:1ed23ab1345f 416 switch (packet[0]) {
va009039 0:1ed23ab1345f 417
va009039 0:1ed23ab1345f 418 case HCI_EVENT_COMMAND_COMPLETE:
va009039 0:1ed23ab1345f 419 // get num cmd packets
va009039 0:1ed23ab1345f 420 // log_info("HCI_EVENT_COMMAND_COMPLETE cmds old %u - new %u\n", hci_stack.num_cmd_packets, packet[2]);
va009039 0:1ed23ab1345f 421 hci_stack.num_cmd_packets = packet[2];
va009039 0:1ed23ab1345f 422
va009039 0:1ed23ab1345f 423 if (COMMAND_COMPLETE_EVENT(packet, hci_read_buffer_size)){
va009039 0:1ed23ab1345f 424 // from offset 5
va009039 0:1ed23ab1345f 425 // status
va009039 0:1ed23ab1345f 426 // "The HC_ACL_Data_Packet_Length return parameter will be used to determine the size of the L2CAP segments contained in ACL Data Packets"
va009039 0:1ed23ab1345f 427 hci_stack.acl_data_packet_length = READ_BT_16(packet, 6);
va009039 0:1ed23ab1345f 428 // ignore: SCO data packet len (8)
va009039 0:1ed23ab1345f 429 hci_stack.total_num_acl_packets = packet[9];
va009039 0:1ed23ab1345f 430 // ignore: total num SCO packets
va009039 0:1ed23ab1345f 431 if (hci_stack.state == HCI_STATE_INITIALIZING){
va009039 0:1ed23ab1345f 432 // determine usable ACL payload size
va009039 0:1ed23ab1345f 433 if (HCI_ACL_PAYLOAD_SIZE < hci_stack.acl_data_packet_length){
va009039 0:1ed23ab1345f 434 hci_stack.acl_data_packet_length = HCI_ACL_PAYLOAD_SIZE;
va009039 0:1ed23ab1345f 435 }
va009039 0:1ed23ab1345f 436 // determine usable ACL packet types
va009039 0:1ed23ab1345f 437 hci_stack.packet_types = hci_acl_packet_types_for_buffer_size(hci_stack.acl_data_packet_length);
va009039 0:1ed23ab1345f 438
va009039 0:1ed23ab1345f 439 log_error("hci_read_buffer_size: used size %u, count %u, packet types %04x\n",
va009039 0:1ed23ab1345f 440 hci_stack.acl_data_packet_length, hci_stack.total_num_acl_packets, hci_stack.packet_types);
va009039 0:1ed23ab1345f 441 }
va009039 0:1ed23ab1345f 442 }
va009039 0:1ed23ab1345f 443 // Dump local address
va009039 0:1ed23ab1345f 444 if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)) {
va009039 0:1ed23ab1345f 445 bd_addr_t addr;
va009039 0:1ed23ab1345f 446 bt_flip_addr(addr, &packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1]);
va009039 0:1ed23ab1345f 447 log_info("Local Address, Status: 0x%02x: Addr: %s\n",
va009039 0:1ed23ab1345f 448 packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE], bd_addr_to_str(addr));
va009039 0:1ed23ab1345f 449 }
va009039 0:1ed23ab1345f 450 if (COMMAND_COMPLETE_EVENT(packet, hci_write_scan_enable)){
va009039 0:1ed23ab1345f 451 hci_emit_discoverable_enabled(hci_stack.discoverable);
va009039 0:1ed23ab1345f 452 }
va009039 0:1ed23ab1345f 453 break;
va009039 0:1ed23ab1345f 454
va009039 0:1ed23ab1345f 455 case HCI_EVENT_COMMAND_STATUS:
va009039 0:1ed23ab1345f 456 // get num cmd packets
va009039 0:1ed23ab1345f 457 // log_info("HCI_EVENT_COMMAND_STATUS cmds - old %u - new %u\n", hci_stack.num_cmd_packets, packet[3]);
va009039 0:1ed23ab1345f 458 hci_stack.num_cmd_packets = packet[3];
va009039 0:1ed23ab1345f 459 break;
va009039 0:1ed23ab1345f 460
va009039 0:1ed23ab1345f 461 case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
va009039 0:1ed23ab1345f 462 for (i=0; i<packet[2];i++){
va009039 0:1ed23ab1345f 463 handle = READ_BT_16(packet, 3 + 2*i);
va009039 0:1ed23ab1345f 464 uint16_t num_packets = READ_BT_16(packet, 3 + packet[2]*2 + 2*i);
va009039 0:1ed23ab1345f 465 conn = connection_for_handle(handle);
va009039 0:1ed23ab1345f 466 if (!conn){
va009039 0:1ed23ab1345f 467 log_error("hci_number_completed_packet lists unused con handle %u\n", handle);
va009039 0:1ed23ab1345f 468 continue;
va009039 0:1ed23ab1345f 469 }
va009039 0:1ed23ab1345f 470 conn->num_acl_packets_sent -= num_packets;
va009039 0:1ed23ab1345f 471 // log_info("hci_number_completed_packet %u processed for handle %u, outstanding %u\n", num_packets, handle, conn->num_acl_packets_sent);
va009039 0:1ed23ab1345f 472 }
va009039 0:1ed23ab1345f 473 break;
va009039 0:1ed23ab1345f 474
va009039 0:1ed23ab1345f 475 case HCI_EVENT_CONNECTION_REQUEST:
va009039 0:1ed23ab1345f 476 bt_flip_addr(addr, &packet[2]);
va009039 0:1ed23ab1345f 477 // TODO: eval COD 8-10
va009039 0:1ed23ab1345f 478 link_type = packet[11];
va009039 0:1ed23ab1345f 479 log_info("Connection_incoming: %s, type %u\n", bd_addr_to_str(addr), link_type);
va009039 0:1ed23ab1345f 480 if (link_type == 1) { // ACL
va009039 0:1ed23ab1345f 481 conn = connection_for_address(addr);
va009039 0:1ed23ab1345f 482 if (!conn) {
va009039 0:1ed23ab1345f 483 conn = create_connection_for_addr(addr);
va009039 0:1ed23ab1345f 484 }
va009039 0:1ed23ab1345f 485 if (!conn) {
va009039 0:1ed23ab1345f 486 // CONNECTION REJECTED DUE TO LIMITED RESOURCES (0X0D)
va009039 0:1ed23ab1345f 487 hci_stack.decline_reason = 0x0d;
va009039 0:1ed23ab1345f 488 BD_ADDR_COPY(hci_stack.decline_addr, addr);
va009039 0:1ed23ab1345f 489 break;
va009039 0:1ed23ab1345f 490 }
va009039 0:1ed23ab1345f 491 conn->state = RECEIVED_CONNECTION_REQUEST;
va009039 0:1ed23ab1345f 492 hci_run();
va009039 0:1ed23ab1345f 493 } else {
va009039 0:1ed23ab1345f 494 // SYNCHRONOUS CONNECTION LIMIT TO A DEVICE EXCEEDED (0X0A)
va009039 0:1ed23ab1345f 495 hci_stack.decline_reason = 0x0a;
va009039 0:1ed23ab1345f 496 BD_ADDR_COPY(hci_stack.decline_addr, addr);
va009039 0:1ed23ab1345f 497 }
va009039 0:1ed23ab1345f 498 break;
va009039 0:1ed23ab1345f 499
va009039 0:1ed23ab1345f 500 case HCI_EVENT_CONNECTION_COMPLETE:
va009039 0:1ed23ab1345f 501 // Connection management
va009039 0:1ed23ab1345f 502 bt_flip_addr(addr, &packet[5]);
va009039 0:1ed23ab1345f 503 log_info("Connection_complete (status=%u) %s\n", packet[2], bd_addr_to_str(addr));
va009039 0:1ed23ab1345f 504 conn = connection_for_address(addr);
va009039 0:1ed23ab1345f 505 if (conn) {
va009039 0:1ed23ab1345f 506 if (!packet[2]){
va009039 0:1ed23ab1345f 507 conn->state = OPEN;
va009039 0:1ed23ab1345f 508 conn->con_handle = READ_BT_16(packet, 3);
va009039 0:1ed23ab1345f 509
va009039 0:1ed23ab1345f 510 // restart timer
va009039 0:1ed23ab1345f 511 run_loop_set_timer(&conn->timeout, HCI_CONNECTION_TIMEOUT_MS);
va009039 0:1ed23ab1345f 512 run_loop_add_timer(&conn->timeout);
va009039 0:1ed23ab1345f 513
va009039 0:1ed23ab1345f 514 log_info("New connection: handle %u, %s\n", conn->con_handle, bd_addr_to_str(conn->address));
va009039 0:1ed23ab1345f 515
va009039 0:1ed23ab1345f 516 hci_emit_nr_connections_changed();
va009039 0:1ed23ab1345f 517 } else {
va009039 0:1ed23ab1345f 518 // connection failed, remove entry
va009039 0:1ed23ab1345f 519 linked_list_remove(&hci_stack.connections, (linked_item_t *) conn);
va009039 0:1ed23ab1345f 520 btstack_memory_hci_connection_free( conn );
va009039 0:1ed23ab1345f 521
va009039 0:1ed23ab1345f 522 // if authentication error, also delete link key
va009039 0:1ed23ab1345f 523 if (packet[2] == 0x05) {
va009039 0:1ed23ab1345f 524 hci_drop_link_key_for_bd_addr(&addr);
va009039 0:1ed23ab1345f 525 }
va009039 0:1ed23ab1345f 526 }
va009039 0:1ed23ab1345f 527 }
va009039 0:1ed23ab1345f 528 break;
va009039 0:1ed23ab1345f 529
va009039 0:1ed23ab1345f 530 case HCI_EVENT_LINK_KEY_REQUEST:
va009039 0:1ed23ab1345f 531 log_info("HCI_EVENT_LINK_KEY_REQUEST\n");
va009039 0:1ed23ab1345f 532 hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_LINK_KEY_REQUEST);
va009039 0:1ed23ab1345f 533 if (!hci_stack.remote_device_db) break;
va009039 0:1ed23ab1345f 534 hci_add_connection_flags_for_flipped_bd_addr(&packet[2], HANDLE_LINK_KEY_REQUEST);
va009039 0:1ed23ab1345f 535 hci_run();
va009039 0:1ed23ab1345f 536 // request handled by hci_run() as HANDLE_LINK_KEY_REQUEST gets set
va009039 0:1ed23ab1345f 537 return;
va009039 0:1ed23ab1345f 538
va009039 0:1ed23ab1345f 539 case HCI_EVENT_LINK_KEY_NOTIFICATION:
va009039 0:1ed23ab1345f 540 hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_LINK_KEY_NOTIFICATION);
va009039 0:1ed23ab1345f 541 if (!hci_stack.remote_device_db) break;
va009039 0:1ed23ab1345f 542 bt_flip_addr(addr, &packet[2]);
va009039 0:1ed23ab1345f 543 hci_stack.remote_device_db->put_link_key(&addr, (link_key_t *) &packet[8]);
va009039 0:1ed23ab1345f 544 // still forward event to allow dismiss of pairing dialog
va009039 0:1ed23ab1345f 545 break;
va009039 0:1ed23ab1345f 546
va009039 0:1ed23ab1345f 547 case HCI_EVENT_PIN_CODE_REQUEST:
va009039 0:1ed23ab1345f 548 hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_PIN_CODE_REQUEST);
va009039 0:1ed23ab1345f 549 // PIN CODE REQUEST means the link key request didn't succee -> delete stored link key
va009039 0:1ed23ab1345f 550 if (!hci_stack.remote_device_db) break;
va009039 0:1ed23ab1345f 551 bt_flip_addr(addr, &packet[2]);
va009039 0:1ed23ab1345f 552 hci_stack.remote_device_db->delete_link_key(&addr);
va009039 0:1ed23ab1345f 553 break;
va009039 0:1ed23ab1345f 554
va009039 0:1ed23ab1345f 555 #ifndef EMBEDDED
va009039 0:1ed23ab1345f 556 case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
va009039 0:1ed23ab1345f 557 if (!hci_stack.remote_device_db) break;
va009039 0:1ed23ab1345f 558 if (packet[2]) break; // status not ok
va009039 0:1ed23ab1345f 559 bt_flip_addr(addr, &packet[3]);
va009039 0:1ed23ab1345f 560 // fix for invalid remote names - terminate on 0xff
va009039 0:1ed23ab1345f 561 for (i=0; i<248;i++){
va009039 0:1ed23ab1345f 562 if (packet[9+i] == 0xff){
va009039 0:1ed23ab1345f 563 packet[9+i] = 0;
va009039 0:1ed23ab1345f 564 break;
va009039 0:1ed23ab1345f 565 }
va009039 0:1ed23ab1345f 566 }
va009039 0:1ed23ab1345f 567 memset(&device_name, 0, sizeof(device_name_t));
va009039 0:1ed23ab1345f 568 strncpy((char*) device_name, (char*) &packet[9], 248);
va009039 0:1ed23ab1345f 569 hci_stack.remote_device_db->put_name(&addr, &device_name);
va009039 0:1ed23ab1345f 570 break;
va009039 0:1ed23ab1345f 571
va009039 0:1ed23ab1345f 572 case HCI_EVENT_INQUIRY_RESULT:
va009039 0:1ed23ab1345f 573 case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
va009039 0:1ed23ab1345f 574 if (!hci_stack.remote_device_db) break;
va009039 0:1ed23ab1345f 575 // first send inq result packet
va009039 0:1ed23ab1345f 576 hci_stack.packet_handler(HCI_EVENT_PACKET, packet, size);
va009039 0:1ed23ab1345f 577 // then send cached remote names
va009039 0:1ed23ab1345f 578 for (i=0; i<packet[2];i++){
va009039 0:1ed23ab1345f 579 bt_flip_addr(addr, &packet[3+i*6]);
va009039 0:1ed23ab1345f 580 if (hci_stack.remote_device_db->get_name(&addr, &device_name)){
va009039 0:1ed23ab1345f 581 hci_emit_remote_name_cached(&addr, &device_name);
va009039 0:1ed23ab1345f 582 }
va009039 0:1ed23ab1345f 583 }
va009039 0:1ed23ab1345f 584 return;
va009039 0:1ed23ab1345f 585 #endif
va009039 0:1ed23ab1345f 586
va009039 0:1ed23ab1345f 587 case HCI_EVENT_DISCONNECTION_COMPLETE:
va009039 0:1ed23ab1345f 588 if (!packet[2]){
va009039 0:1ed23ab1345f 589 handle = READ_BT_16(packet, 3);
va009039 0:1ed23ab1345f 590 hci_connection_t * conn = connection_for_handle(handle);
va009039 0:1ed23ab1345f 591 if (conn) {
va009039 0:1ed23ab1345f 592 hci_shutdown_connection(conn);
va009039 0:1ed23ab1345f 593 }
va009039 0:1ed23ab1345f 594 }
va009039 0:1ed23ab1345f 595 break;
va009039 0:1ed23ab1345f 596
va009039 0:1ed23ab1345f 597 case HCI_EVENT_HARDWARE_ERROR:
va009039 0:1ed23ab1345f 598 if(hci_stack.control->hw_error){
va009039 0:1ed23ab1345f 599 (*hci_stack.control->hw_error)();
va009039 0:1ed23ab1345f 600 }
va009039 0:1ed23ab1345f 601 break;
va009039 0:1ed23ab1345f 602
va009039 0:1ed23ab1345f 603 #ifdef HAVE_BLE
va009039 0:1ed23ab1345f 604 case HCI_EVENT_LE_META:
va009039 0:1ed23ab1345f 605 switch (packet[2]) {
va009039 0:1ed23ab1345f 606 case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
va009039 0:1ed23ab1345f 607 // Connection management
va009039 0:1ed23ab1345f 608 bt_flip_addr(addr, &packet[8]);
va009039 0:1ed23ab1345f 609 log_info("LE Connection_complete (status=%u) %s\n", packet[3], bd_addr_to_str(addr));
va009039 0:1ed23ab1345f 610 // LE connections are auto-accepted, so just create a connection if there isn't one already
va009039 0:1ed23ab1345f 611 conn = connection_for_address(addr);
va009039 0:1ed23ab1345f 612 if (packet[3]){
va009039 0:1ed23ab1345f 613 if (conn){
va009039 0:1ed23ab1345f 614 // outgoing connection failed, remove entry
va009039 0:1ed23ab1345f 615 linked_list_remove(&hci_stack.connections, (linked_item_t *) conn);
va009039 0:1ed23ab1345f 616 btstack_memory_hci_connection_free( conn );
va009039 0:1ed23ab1345f 617
va009039 0:1ed23ab1345f 618 }
va009039 0:1ed23ab1345f 619 // if authentication error, also delete link key
va009039 0:1ed23ab1345f 620 if (packet[3] == 0x05) {
va009039 0:1ed23ab1345f 621 hci_drop_link_key_for_bd_addr(&addr);
va009039 0:1ed23ab1345f 622 }
va009039 0:1ed23ab1345f 623 break;
va009039 0:1ed23ab1345f 624 }
va009039 0:1ed23ab1345f 625 if (!conn){
va009039 0:1ed23ab1345f 626 conn = create_connection_for_addr(addr);
va009039 0:1ed23ab1345f 627 }
va009039 0:1ed23ab1345f 628 if (!conn){
va009039 0:1ed23ab1345f 629 // no memory
va009039 0:1ed23ab1345f 630 break;
va009039 0:1ed23ab1345f 631 }
va009039 0:1ed23ab1345f 632
va009039 0:1ed23ab1345f 633 conn->state = OPEN;
va009039 0:1ed23ab1345f 634 conn->con_handle = READ_BT_16(packet, 4);
va009039 0:1ed23ab1345f 635
va009039 0:1ed23ab1345f 636 // TODO: store - role, peer address type, conn_interval, conn_latency, supervision timeout, master clock
va009039 0:1ed23ab1345f 637
va009039 0:1ed23ab1345f 638 // restart timer
va009039 0:1ed23ab1345f 639 // run_loop_set_timer(&conn->timeout, HCI_CONNECTION_TIMEOUT_MS);
va009039 0:1ed23ab1345f 640 // run_loop_add_timer(&conn->timeout);
va009039 0:1ed23ab1345f 641
va009039 0:1ed23ab1345f 642 log_info("New connection: handle %u, %s\n", conn->con_handle, bd_addr_to_str(conn->address));
va009039 0:1ed23ab1345f 643
va009039 0:1ed23ab1345f 644 hci_emit_nr_connections_changed();
va009039 0:1ed23ab1345f 645 break;
va009039 0:1ed23ab1345f 646
va009039 0:1ed23ab1345f 647 default:
va009039 0:1ed23ab1345f 648 break;
va009039 0:1ed23ab1345f 649 }
va009039 0:1ed23ab1345f 650 break;
va009039 0:1ed23ab1345f 651 #endif
va009039 0:1ed23ab1345f 652
va009039 0:1ed23ab1345f 653 default:
va009039 0:1ed23ab1345f 654 break;
va009039 0:1ed23ab1345f 655 }
va009039 0:1ed23ab1345f 656
va009039 0:1ed23ab1345f 657 // handle BT initialization
va009039 0:1ed23ab1345f 658 if (hci_stack.state == HCI_STATE_INITIALIZING){
va009039 0:1ed23ab1345f 659 // handle H4 synchronization loss on restart
va009039 0:1ed23ab1345f 660 // if (hci_stack.substate == 1 && packet[0] == HCI_EVENT_HARDWARE_ERROR){
va009039 0:1ed23ab1345f 661 // hci_stack.substate = 0;
va009039 0:1ed23ab1345f 662 // }
va009039 0:1ed23ab1345f 663 // handle normal init sequence
va009039 0:1ed23ab1345f 664 if (hci_stack.substate % 2){
va009039 0:1ed23ab1345f 665 // odd: waiting for event
va009039 0:1ed23ab1345f 666 if (packet[0] == HCI_EVENT_COMMAND_COMPLETE){
va009039 0:1ed23ab1345f 667 hci_stack.substate++;
va009039 0:1ed23ab1345f 668 }
va009039 0:1ed23ab1345f 669 }
va009039 0:1ed23ab1345f 670 }
va009039 0:1ed23ab1345f 671
va009039 0:1ed23ab1345f 672 // help with BT sleep
va009039 0:1ed23ab1345f 673 if (hci_stack.state == HCI_STATE_FALLING_ASLEEP
va009039 0:1ed23ab1345f 674 && hci_stack.substate == 1
va009039 0:1ed23ab1345f 675 && COMMAND_COMPLETE_EVENT(packet, hci_write_scan_enable)){
va009039 0:1ed23ab1345f 676 hci_stack.substate++;
va009039 0:1ed23ab1345f 677 }
va009039 0:1ed23ab1345f 678
va009039 0:1ed23ab1345f 679 hci_stack.packet_handler(HCI_EVENT_PACKET, packet, size);
va009039 2:871b41f4789e 680
va009039 2:871b41f4789e 681 // execute main loop
va009039 2:871b41f4789e 682 hci_run();
va009039 0:1ed23ab1345f 683 }
va009039 0:1ed23ab1345f 684
va009039 0:1ed23ab1345f 685 void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
va009039 0:1ed23ab1345f 686 switch (packet_type) {
va009039 0:1ed23ab1345f 687 case HCI_EVENT_PACKET:
va009039 0:1ed23ab1345f 688 event_handler(packet, size);
va009039 0:1ed23ab1345f 689 break;
va009039 0:1ed23ab1345f 690 case HCI_ACL_DATA_PACKET:
va009039 0:1ed23ab1345f 691 acl_handler(packet, size);
va009039 0:1ed23ab1345f 692 break;
va009039 0:1ed23ab1345f 693 default:
va009039 0:1ed23ab1345f 694 break;
va009039 0:1ed23ab1345f 695 }
va009039 0:1ed23ab1345f 696 }
va009039 0:1ed23ab1345f 697
va009039 0:1ed23ab1345f 698 /** Register HCI packet handlers */
va009039 0:1ed23ab1345f 699 void hci_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
va009039 0:1ed23ab1345f 700 hci_stack.packet_handler = handler;
va009039 0:1ed23ab1345f 701 }
va009039 0:1ed23ab1345f 702
va009039 0:1ed23ab1345f 703 void hci_init(hci_transport_t *transport, void *config, bt_control_t *control, remote_device_db_t const* remote_device_db){
va009039 0:1ed23ab1345f 704
va009039 0:1ed23ab1345f 705 // reference to use transport layer implementation
va009039 0:1ed23ab1345f 706 hci_stack.hci_transport = transport;
va009039 0:1ed23ab1345f 707
va009039 0:1ed23ab1345f 708 // references to used control implementation
va009039 0:1ed23ab1345f 709 hci_stack.control = control;
va009039 0:1ed23ab1345f 710
va009039 0:1ed23ab1345f 711 // reference to used config
va009039 0:1ed23ab1345f 712 hci_stack.config = config;
va009039 0:1ed23ab1345f 713
va009039 0:1ed23ab1345f 714 // no connections yet
va009039 0:1ed23ab1345f 715 hci_stack.connections = NULL;
va009039 0:1ed23ab1345f 716 hci_stack.discoverable = 0;
va009039 0:1ed23ab1345f 717 hci_stack.connectable = 0;
va009039 0:1ed23ab1345f 718
va009039 0:1ed23ab1345f 719 // no pending cmds
va009039 0:1ed23ab1345f 720 hci_stack.decline_reason = 0;
va009039 0:1ed23ab1345f 721 hci_stack.new_scan_enable_value = 0xff;
va009039 0:1ed23ab1345f 722
va009039 0:1ed23ab1345f 723 // higher level handler
va009039 0:1ed23ab1345f 724 hci_stack.packet_handler = dummy_handler;
va009039 0:1ed23ab1345f 725
va009039 0:1ed23ab1345f 726 // store and open remote device db
va009039 0:1ed23ab1345f 727 hci_stack.remote_device_db = remote_device_db;
va009039 0:1ed23ab1345f 728 if (hci_stack.remote_device_db) {
va009039 0:1ed23ab1345f 729 hci_stack.remote_device_db->open();
va009039 0:1ed23ab1345f 730 }
va009039 0:1ed23ab1345f 731
va009039 0:1ed23ab1345f 732 // max acl payload size defined in config.h
va009039 0:1ed23ab1345f 733 hci_stack.acl_data_packet_length = HCI_ACL_PAYLOAD_SIZE;
va009039 0:1ed23ab1345f 734
va009039 0:1ed23ab1345f 735 // register packet handlers with transport
va009039 0:1ed23ab1345f 736 transport->register_packet_handler(&packet_handler);
va009039 0:1ed23ab1345f 737
va009039 0:1ed23ab1345f 738 hci_stack.state = HCI_STATE_OFF;
va009039 0:1ed23ab1345f 739 }
va009039 0:1ed23ab1345f 740
va009039 0:1ed23ab1345f 741 void hci_close(){
va009039 0:1ed23ab1345f 742 // close remote device db
va009039 0:1ed23ab1345f 743 if (hci_stack.remote_device_db) {
va009039 0:1ed23ab1345f 744 hci_stack.remote_device_db->close();
va009039 0:1ed23ab1345f 745 }
va009039 0:1ed23ab1345f 746 while (hci_stack.connections) {
va009039 0:1ed23ab1345f 747 hci_shutdown_connection((hci_connection_t *) hci_stack.connections);
va009039 0:1ed23ab1345f 748 }
va009039 0:1ed23ab1345f 749 hci_power_control(HCI_POWER_OFF);
va009039 0:1ed23ab1345f 750 }
va009039 0:1ed23ab1345f 751
va009039 0:1ed23ab1345f 752 // State-Module-Driver overview
va009039 0:1ed23ab1345f 753 // state module low-level
va009039 0:1ed23ab1345f 754 // HCI_STATE_OFF off close
va009039 0:1ed23ab1345f 755 // HCI_STATE_INITIALIZING, on open
va009039 0:1ed23ab1345f 756 // HCI_STATE_WORKING, on open
va009039 0:1ed23ab1345f 757 // HCI_STATE_HALTING, on open
va009039 0:1ed23ab1345f 758 // HCI_STATE_SLEEPING, off/sleep close
va009039 0:1ed23ab1345f 759 // HCI_STATE_FALLING_ASLEEP on open
va009039 0:1ed23ab1345f 760
va009039 0:1ed23ab1345f 761 static int hci_power_control_on(void){
va009039 0:1ed23ab1345f 762
va009039 0:1ed23ab1345f 763 // power on
va009039 0:1ed23ab1345f 764 int err = 0;
va009039 0:1ed23ab1345f 765 if (hci_stack.control && hci_stack.control->on){
va009039 0:1ed23ab1345f 766 err = (*hci_stack.control->on)(hci_stack.config);
va009039 0:1ed23ab1345f 767 }
va009039 0:1ed23ab1345f 768 if (err){
va009039 0:1ed23ab1345f 769 log_error( "POWER_ON failed\n");
va009039 0:1ed23ab1345f 770 hci_emit_hci_open_failed();
va009039 0:1ed23ab1345f 771 return err;
va009039 0:1ed23ab1345f 772 }
va009039 0:1ed23ab1345f 773
va009039 0:1ed23ab1345f 774 // open low-level device
va009039 0:1ed23ab1345f 775 err = hci_stack.hci_transport->open(hci_stack.config);
va009039 0:1ed23ab1345f 776 if (err){
va009039 0:1ed23ab1345f 777 log_error( "HCI_INIT failed, turning Bluetooth off again\n");
va009039 0:1ed23ab1345f 778 if (hci_stack.control && hci_stack.control->off){
va009039 0:1ed23ab1345f 779 (*hci_stack.control->off)(hci_stack.config);
va009039 0:1ed23ab1345f 780 }
va009039 0:1ed23ab1345f 781 hci_emit_hci_open_failed();
va009039 0:1ed23ab1345f 782 return err;
va009039 0:1ed23ab1345f 783 }
va009039 0:1ed23ab1345f 784 return 0;
va009039 0:1ed23ab1345f 785 }
va009039 0:1ed23ab1345f 786
va009039 0:1ed23ab1345f 787 static void hci_power_control_off(void){
va009039 0:1ed23ab1345f 788
va009039 0:1ed23ab1345f 789 log_info("hci_power_control_off\n");
va009039 0:1ed23ab1345f 790
va009039 0:1ed23ab1345f 791 // close low-level device
va009039 0:1ed23ab1345f 792 hci_stack.hci_transport->close(hci_stack.config);
va009039 0:1ed23ab1345f 793
va009039 0:1ed23ab1345f 794 log_info("hci_power_control_off - hci_transport closed\n");
va009039 0:1ed23ab1345f 795
va009039 0:1ed23ab1345f 796 // power off
va009039 0:1ed23ab1345f 797 if (hci_stack.control && hci_stack.control->off){
va009039 0:1ed23ab1345f 798 (*hci_stack.control->off)(hci_stack.config);
va009039 0:1ed23ab1345f 799 }
va009039 0:1ed23ab1345f 800
va009039 0:1ed23ab1345f 801 log_info("hci_power_control_off - control closed\n");
va009039 0:1ed23ab1345f 802
va009039 0:1ed23ab1345f 803 hci_stack.state = HCI_STATE_OFF;
va009039 0:1ed23ab1345f 804 }
va009039 0:1ed23ab1345f 805
va009039 0:1ed23ab1345f 806 static void hci_power_control_sleep(void){
va009039 0:1ed23ab1345f 807
va009039 0:1ed23ab1345f 808 log_info("hci_power_control_sleep\n");
va009039 0:1ed23ab1345f 809
va009039 0:1ed23ab1345f 810 #if 0
va009039 0:1ed23ab1345f 811 // don't close serial port during sleep
va009039 0:1ed23ab1345f 812
va009039 0:1ed23ab1345f 813 // close low-level device
va009039 0:1ed23ab1345f 814 hci_stack.hci_transport->close(hci_stack.config);
va009039 0:1ed23ab1345f 815 #endif
va009039 0:1ed23ab1345f 816
va009039 0:1ed23ab1345f 817 // sleep mode
va009039 0:1ed23ab1345f 818 if (hci_stack.control && hci_stack.control->sleep){
va009039 0:1ed23ab1345f 819 (*hci_stack.control->sleep)(hci_stack.config);
va009039 0:1ed23ab1345f 820 }
va009039 0:1ed23ab1345f 821
va009039 0:1ed23ab1345f 822 hci_stack.state = HCI_STATE_SLEEPING;
va009039 0:1ed23ab1345f 823 }
va009039 0:1ed23ab1345f 824
va009039 0:1ed23ab1345f 825 static int hci_power_control_wake(void){
va009039 0:1ed23ab1345f 826
va009039 0:1ed23ab1345f 827 log_info("hci_power_control_wake\n");
va009039 0:1ed23ab1345f 828
va009039 0:1ed23ab1345f 829 // wake on
va009039 0:1ed23ab1345f 830 if (hci_stack.control && hci_stack.control->wake){
va009039 0:1ed23ab1345f 831 (*hci_stack.control->wake)(hci_stack.config);
va009039 0:1ed23ab1345f 832 }
va009039 0:1ed23ab1345f 833
va009039 0:1ed23ab1345f 834 #if 0
va009039 0:1ed23ab1345f 835 // open low-level device
va009039 0:1ed23ab1345f 836 int err = hci_stack.hci_transport->open(hci_stack.config);
va009039 0:1ed23ab1345f 837 if (err){
va009039 0:1ed23ab1345f 838 log_error( "HCI_INIT failed, turning Bluetooth off again\n");
va009039 0:1ed23ab1345f 839 if (hci_stack.control && hci_stack.control->off){
va009039 0:1ed23ab1345f 840 (*hci_stack.control->off)(hci_stack.config);
va009039 0:1ed23ab1345f 841 }
va009039 0:1ed23ab1345f 842 hci_emit_hci_open_failed();
va009039 0:1ed23ab1345f 843 return err;
va009039 0:1ed23ab1345f 844 }
va009039 0:1ed23ab1345f 845 #endif
va009039 0:1ed23ab1345f 846
va009039 0:1ed23ab1345f 847 return 0;
va009039 0:1ed23ab1345f 848 }
va009039 0:1ed23ab1345f 849
va009039 0:1ed23ab1345f 850
va009039 0:1ed23ab1345f 851 int hci_power_control(HCI_POWER_MODE power_mode){
va009039 0:1ed23ab1345f 852
va009039 0:1ed23ab1345f 853 log_info("hci_power_control: %u, current mode %u\n", power_mode, hci_stack.state);
va009039 0:1ed23ab1345f 854
va009039 0:1ed23ab1345f 855 int err = 0;
va009039 0:1ed23ab1345f 856 switch (hci_stack.state){
va009039 0:1ed23ab1345f 857
va009039 0:1ed23ab1345f 858 case HCI_STATE_OFF:
va009039 0:1ed23ab1345f 859 switch (power_mode){
va009039 0:1ed23ab1345f 860 case HCI_POWER_ON:
va009039 0:1ed23ab1345f 861 err = hci_power_control_on();
va009039 0:1ed23ab1345f 862 if (err) return err;
va009039 0:1ed23ab1345f 863 // set up state machine
va009039 0:1ed23ab1345f 864 hci_stack.num_cmd_packets = 1; // assume that one cmd can be sent
va009039 0:1ed23ab1345f 865 hci_stack.state = HCI_STATE_INITIALIZING;
va009039 0:1ed23ab1345f 866 hci_stack.substate = 0;
va009039 0:1ed23ab1345f 867 break;
va009039 0:1ed23ab1345f 868 case HCI_POWER_OFF:
va009039 0:1ed23ab1345f 869 // do nothing
va009039 0:1ed23ab1345f 870 break;
va009039 0:1ed23ab1345f 871 case HCI_POWER_SLEEP:
va009039 0:1ed23ab1345f 872 // do nothing (with SLEEP == OFF)
va009039 0:1ed23ab1345f 873 break;
va009039 0:1ed23ab1345f 874 }
va009039 0:1ed23ab1345f 875 break;
va009039 0:1ed23ab1345f 876
va009039 0:1ed23ab1345f 877 case HCI_STATE_INITIALIZING:
va009039 0:1ed23ab1345f 878 switch (power_mode){
va009039 0:1ed23ab1345f 879 case HCI_POWER_ON:
va009039 0:1ed23ab1345f 880 // do nothing
va009039 0:1ed23ab1345f 881 break;
va009039 0:1ed23ab1345f 882 case HCI_POWER_OFF:
va009039 0:1ed23ab1345f 883 // no connections yet, just turn it off
va009039 0:1ed23ab1345f 884 hci_power_control_off();
va009039 0:1ed23ab1345f 885 break;
va009039 0:1ed23ab1345f 886 case HCI_POWER_SLEEP:
va009039 0:1ed23ab1345f 887 // no connections yet, just turn it off
va009039 0:1ed23ab1345f 888 hci_power_control_sleep();
va009039 0:1ed23ab1345f 889 break;
va009039 0:1ed23ab1345f 890 }
va009039 0:1ed23ab1345f 891 break;
va009039 0:1ed23ab1345f 892
va009039 0:1ed23ab1345f 893 case HCI_STATE_WORKING:
va009039 0:1ed23ab1345f 894 switch (power_mode){
va009039 0:1ed23ab1345f 895 case HCI_POWER_ON:
va009039 0:1ed23ab1345f 896 // do nothing
va009039 0:1ed23ab1345f 897 break;
va009039 0:1ed23ab1345f 898 case HCI_POWER_OFF:
va009039 0:1ed23ab1345f 899 // see hci_run
va009039 0:1ed23ab1345f 900 hci_stack.state = HCI_STATE_HALTING;
va009039 0:1ed23ab1345f 901 break;
va009039 0:1ed23ab1345f 902 case HCI_POWER_SLEEP:
va009039 0:1ed23ab1345f 903 // see hci_run
va009039 0:1ed23ab1345f 904 hci_stack.state = HCI_STATE_FALLING_ASLEEP;
va009039 0:1ed23ab1345f 905 hci_stack.substate = 0;
va009039 0:1ed23ab1345f 906 break;
va009039 0:1ed23ab1345f 907 }
va009039 0:1ed23ab1345f 908 break;
va009039 0:1ed23ab1345f 909
va009039 0:1ed23ab1345f 910 case HCI_STATE_HALTING:
va009039 0:1ed23ab1345f 911 switch (power_mode){
va009039 0:1ed23ab1345f 912 case HCI_POWER_ON:
va009039 0:1ed23ab1345f 913 // set up state machine
va009039 0:1ed23ab1345f 914 hci_stack.state = HCI_STATE_INITIALIZING;
va009039 0:1ed23ab1345f 915 hci_stack.substate = 0;
va009039 0:1ed23ab1345f 916 break;
va009039 0:1ed23ab1345f 917 case HCI_POWER_OFF:
va009039 0:1ed23ab1345f 918 // do nothing
va009039 0:1ed23ab1345f 919 break;
va009039 0:1ed23ab1345f 920 case HCI_POWER_SLEEP:
va009039 0:1ed23ab1345f 921 // see hci_run
va009039 0:1ed23ab1345f 922 hci_stack.state = HCI_STATE_FALLING_ASLEEP;
va009039 0:1ed23ab1345f 923 hci_stack.substate = 0;
va009039 0:1ed23ab1345f 924 break;
va009039 0:1ed23ab1345f 925 }
va009039 0:1ed23ab1345f 926 break;
va009039 0:1ed23ab1345f 927
va009039 0:1ed23ab1345f 928 case HCI_STATE_FALLING_ASLEEP:
va009039 0:1ed23ab1345f 929 switch (power_mode){
va009039 0:1ed23ab1345f 930 case HCI_POWER_ON:
va009039 0:1ed23ab1345f 931
va009039 0:1ed23ab1345f 932 #if defined(USE_POWERMANAGEMENT) && defined(USE_BLUETOOL)
va009039 0:1ed23ab1345f 933 // nothing to do, if H4 supports power management
va009039 0:1ed23ab1345f 934 if (bt_control_iphone_power_management_enabled()){
va009039 0:1ed23ab1345f 935 hci_stack.state = HCI_STATE_INITIALIZING;
va009039 0:1ed23ab1345f 936 hci_stack.substate = 6;
va009039 0:1ed23ab1345f 937 break;
va009039 0:1ed23ab1345f 938 }
va009039 0:1ed23ab1345f 939 #endif
va009039 0:1ed23ab1345f 940 // set up state machine
va009039 0:1ed23ab1345f 941 hci_stack.num_cmd_packets = 1; // assume that one cmd can be sent
va009039 0:1ed23ab1345f 942 hci_stack.state = HCI_STATE_INITIALIZING;
va009039 0:1ed23ab1345f 943 hci_stack.substate = 0;
va009039 0:1ed23ab1345f 944 break;
va009039 0:1ed23ab1345f 945 case HCI_POWER_OFF:
va009039 0:1ed23ab1345f 946 // see hci_run
va009039 0:1ed23ab1345f 947 hci_stack.state = HCI_STATE_HALTING;
va009039 0:1ed23ab1345f 948 break;
va009039 0:1ed23ab1345f 949 case HCI_POWER_SLEEP:
va009039 0:1ed23ab1345f 950 // do nothing
va009039 0:1ed23ab1345f 951 break;
va009039 0:1ed23ab1345f 952 }
va009039 0:1ed23ab1345f 953 break;
va009039 0:1ed23ab1345f 954
va009039 0:1ed23ab1345f 955 case HCI_STATE_SLEEPING:
va009039 0:1ed23ab1345f 956 switch (power_mode){
va009039 0:1ed23ab1345f 957 case HCI_POWER_ON:
va009039 0:1ed23ab1345f 958
va009039 0:1ed23ab1345f 959 #if defined(USE_POWERMANAGEMENT) && defined(USE_BLUETOOL)
va009039 0:1ed23ab1345f 960 // nothing to do, if H4 supports power management
va009039 0:1ed23ab1345f 961 if (bt_control_iphone_power_management_enabled()){
va009039 0:1ed23ab1345f 962 hci_stack.state = HCI_STATE_INITIALIZING;
va009039 0:1ed23ab1345f 963 hci_stack.substate = 6;
va009039 0:1ed23ab1345f 964 hci_update_scan_enable();
va009039 0:1ed23ab1345f 965 break;
va009039 0:1ed23ab1345f 966 }
va009039 0:1ed23ab1345f 967 #endif
va009039 0:1ed23ab1345f 968 err = hci_power_control_wake();
va009039 0:1ed23ab1345f 969 if (err) return err;
va009039 0:1ed23ab1345f 970 // set up state machine
va009039 0:1ed23ab1345f 971 hci_stack.num_cmd_packets = 1; // assume that one cmd can be sent
va009039 0:1ed23ab1345f 972 hci_stack.state = HCI_STATE_INITIALIZING;
va009039 0:1ed23ab1345f 973 hci_stack.substate = 0;
va009039 0:1ed23ab1345f 974 break;
va009039 0:1ed23ab1345f 975 case HCI_POWER_OFF:
va009039 0:1ed23ab1345f 976 hci_stack.state = HCI_STATE_HALTING;
va009039 0:1ed23ab1345f 977 break;
va009039 0:1ed23ab1345f 978 case HCI_POWER_SLEEP:
va009039 0:1ed23ab1345f 979 // do nothing
va009039 0:1ed23ab1345f 980 break;
va009039 0:1ed23ab1345f 981 }
va009039 0:1ed23ab1345f 982 break;
va009039 0:1ed23ab1345f 983 }
va009039 0:1ed23ab1345f 984
va009039 0:1ed23ab1345f 985 // create internal event
va009039 2:871b41f4789e 986 hci_emit_state();
va009039 0:1ed23ab1345f 987
va009039 2:871b41f4789e 988 // trigger next/first action
va009039 2:871b41f4789e 989 hci_run();
va009039 2:871b41f4789e 990
va009039 0:1ed23ab1345f 991 return 0;
va009039 0:1ed23ab1345f 992 }
va009039 0:1ed23ab1345f 993
va009039 0:1ed23ab1345f 994 static void hci_update_scan_enable(void){
va009039 0:1ed23ab1345f 995 // 2 = page scan, 1 = inq scan
va009039 0:1ed23ab1345f 996 hci_stack.new_scan_enable_value = hci_stack.connectable << 1 | hci_stack.discoverable;
va009039 0:1ed23ab1345f 997 hci_run();
va009039 0:1ed23ab1345f 998 }
va009039 0:1ed23ab1345f 999
va009039 0:1ed23ab1345f 1000 void hci_discoverable_control(uint8_t enable){
va009039 0:1ed23ab1345f 1001 if (enable) enable = 1; // normalize argument
va009039 0:1ed23ab1345f 1002
va009039 0:1ed23ab1345f 1003 if (hci_stack.discoverable == enable){
va009039 0:1ed23ab1345f 1004 hci_emit_discoverable_enabled(hci_stack.discoverable);
va009039 0:1ed23ab1345f 1005 return;
va009039 0:1ed23ab1345f 1006 }
va009039 0:1ed23ab1345f 1007
va009039 0:1ed23ab1345f 1008 hci_stack.discoverable = enable;
va009039 0:1ed23ab1345f 1009 hci_update_scan_enable();
va009039 0:1ed23ab1345f 1010 }
va009039 0:1ed23ab1345f 1011
va009039 0:1ed23ab1345f 1012 void hci_connectable_control(uint8_t enable){
va009039 0:1ed23ab1345f 1013 if (enable) enable = 1; // normalize argument
va009039 0:1ed23ab1345f 1014
va009039 0:1ed23ab1345f 1015 // don't emit event
va009039 0:1ed23ab1345f 1016 if (hci_stack.connectable == enable) return;
va009039 0:1ed23ab1345f 1017
va009039 0:1ed23ab1345f 1018 hci_stack.connectable = enable;
va009039 0:1ed23ab1345f 1019 hci_update_scan_enable();
va009039 0:1ed23ab1345f 1020 }
va009039 0:1ed23ab1345f 1021
va009039 0:1ed23ab1345f 1022 void hci_run(){
va009039 0:1ed23ab1345f 1023
va009039 0:1ed23ab1345f 1024 hci_connection_t * connection;
va009039 0:1ed23ab1345f 1025 linked_item_t * it;
va009039 0:1ed23ab1345f 1026
va009039 0:1ed23ab1345f 1027 if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
va009039 0:1ed23ab1345f 1028
va009039 0:1ed23ab1345f 1029 // global/non-connection oriented commands
va009039 0:1ed23ab1345f 1030
va009039 0:1ed23ab1345f 1031 // decline incoming connections
va009039 0:1ed23ab1345f 1032 if (hci_stack.decline_reason){
va009039 0:1ed23ab1345f 1033 uint8_t reason = hci_stack.decline_reason;
va009039 0:1ed23ab1345f 1034 hci_stack.decline_reason = 0;
va009039 0:1ed23ab1345f 1035 hci_send_cmd(&hci_reject_connection_request, hci_stack.decline_addr, reason);
va009039 0:1ed23ab1345f 1036 }
va009039 0:1ed23ab1345f 1037
va009039 0:1ed23ab1345f 1038 if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
va009039 0:1ed23ab1345f 1039
va009039 0:1ed23ab1345f 1040 // send scan enable
va009039 0:1ed23ab1345f 1041 if (hci_stack.new_scan_enable_value != 0xff){
va009039 0:1ed23ab1345f 1042 hci_send_cmd(&hci_write_scan_enable, hci_stack.new_scan_enable_value);
va009039 0:1ed23ab1345f 1043 hci_stack.new_scan_enable_value = 0xff;
va009039 0:1ed23ab1345f 1044 }
va009039 0:1ed23ab1345f 1045
va009039 0:1ed23ab1345f 1046 // send pending HCI commands
va009039 0:1ed23ab1345f 1047 for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next){
va009039 0:1ed23ab1345f 1048
va009039 0:1ed23ab1345f 1049 if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
va009039 0:1ed23ab1345f 1050
va009039 0:1ed23ab1345f 1051 connection = (hci_connection_t *) it;
va009039 0:1ed23ab1345f 1052
va009039 0:1ed23ab1345f 1053 if (connection->state == RECEIVED_CONNECTION_REQUEST){
va009039 0:1ed23ab1345f 1054 log_info("sending hci_accept_connection_request\n");
va009039 0:1ed23ab1345f 1055 hci_send_cmd(&hci_accept_connection_request, connection->address, 1);
va009039 0:1ed23ab1345f 1056 connection->state = ACCEPTED_CONNECTION_REQUEST;
va009039 0:1ed23ab1345f 1057 }
va009039 0:1ed23ab1345f 1058
va009039 0:1ed23ab1345f 1059 if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
va009039 0:1ed23ab1345f 1060
va009039 0:1ed23ab1345f 1061 if (connection->authentication_flags & HANDLE_LINK_KEY_REQUEST){
va009039 0:1ed23ab1345f 1062 link_key_t link_key;
va009039 0:1ed23ab1345f 1063 log_info("responding to link key request\n");
va009039 2:871b41f4789e 1064 if (hci_stack.remote_device_db->get_link_key( &connection->address, &link_key)){
va009039 0:1ed23ab1345f 1065 hci_send_cmd(&hci_link_key_request_reply, connection->address, &link_key);
va009039 0:1ed23ab1345f 1066 } else {
va009039 0:1ed23ab1345f 1067 hci_send_cmd(&hci_link_key_request_negative_reply, connection->address);
va009039 0:1ed23ab1345f 1068 }
va009039 0:1ed23ab1345f 1069 connectionClearAuthenticationFlags(connection, HANDLE_LINK_KEY_REQUEST);
va009039 0:1ed23ab1345f 1070 }
va009039 0:1ed23ab1345f 1071 }
va009039 0:1ed23ab1345f 1072
va009039 0:1ed23ab1345f 1073 if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
va009039 0:1ed23ab1345f 1074
va009039 0:1ed23ab1345f 1075 switch (hci_stack.state){
va009039 0:1ed23ab1345f 1076 case HCI_STATE_INITIALIZING:
va009039 0:1ed23ab1345f 1077 // log_info("hci_init: substate %u\n", hci_stack.substate);
va009039 0:1ed23ab1345f 1078 if (hci_stack.substate % 2) {
va009039 0:1ed23ab1345f 1079 // odd: waiting for command completion
va009039 0:1ed23ab1345f 1080 return;
va009039 0:1ed23ab1345f 1081 }
va009039 0:1ed23ab1345f 1082 switch (hci_stack.substate >> 1){
va009039 0:1ed23ab1345f 1083 case 0: // RESET
va009039 0:1ed23ab1345f 1084 hci_send_cmd(&hci_reset);
va009039 0:1ed23ab1345f 1085 if (hci_stack.config == 0 || ((hci_uart_config_t *)hci_stack.config)->baudrate_main == 0){
va009039 0:1ed23ab1345f 1086 // skip baud change
va009039 0:1ed23ab1345f 1087 hci_stack.substate = 4; // >> 1 = 2
va009039 0:1ed23ab1345f 1088 }
va009039 0:1ed23ab1345f 1089 break;
va009039 0:1ed23ab1345f 1090 case 1: // SEND BAUD CHANGE
va009039 0:1ed23ab1345f 1091 hci_stack.control->baudrate_cmd(hci_stack.config, ((hci_uart_config_t *)hci_stack.config)->baudrate_main, hci_stack.hci_packet_buffer);
va009039 0:1ed23ab1345f 1092 hci_send_cmd_packet(hci_stack.hci_packet_buffer, 3 + hci_stack.hci_packet_buffer[2]);
va009039 0:1ed23ab1345f 1093 break;
va009039 0:1ed23ab1345f 1094 case 2: // LOCAL BAUD CHANGE
va009039 0:1ed23ab1345f 1095 hci_stack.hci_transport->set_baudrate(((hci_uart_config_t *)hci_stack.config)->baudrate_main);
va009039 0:1ed23ab1345f 1096 hci_stack.substate += 2;
va009039 0:1ed23ab1345f 1097 // break missing here for fall through
va009039 0:1ed23ab1345f 1098
va009039 0:1ed23ab1345f 1099 case 3:
va009039 0:1ed23ab1345f 1100 // custom initialization
va009039 0:1ed23ab1345f 1101 if (hci_stack.control && hci_stack.control->next_cmd){
va009039 0:1ed23ab1345f 1102 int valid_cmd = (*hci_stack.control->next_cmd)(hci_stack.config, hci_stack.hci_packet_buffer);
va009039 0:1ed23ab1345f 1103 if (valid_cmd){
va009039 0:1ed23ab1345f 1104 int size = 3 + hci_stack.hci_packet_buffer[2];
va009039 0:1ed23ab1345f 1105 hci_stack.hci_transport->send_packet(HCI_COMMAND_DATA_PACKET, hci_stack.hci_packet_buffer, size);
va009039 0:1ed23ab1345f 1106 hci_stack.substate = 4; // more init commands
va009039 0:1ed23ab1345f 1107 break;
va009039 0:1ed23ab1345f 1108 }
va009039 0:1ed23ab1345f 1109 log_info("hci_run: init script done\n\r");
va009039 0:1ed23ab1345f 1110 }
va009039 0:1ed23ab1345f 1111 // otherwise continue
va009039 2:871b41f4789e 1112 hci_send_cmd(&hci_read_bd_addr);
va009039 2:871b41f4789e 1113 break;
va009039 2:871b41f4789e 1114 case 4:
va009039 2:871b41f4789e 1115 hci_send_cmd(&hci_read_buffer_size);
va009039 2:871b41f4789e 1116 break;
va009039 0:1ed23ab1345f 1117 case 5:
va009039 0:1ed23ab1345f 1118 // ca. 15 sec
va009039 0:1ed23ab1345f 1119 hci_send_cmd(&hci_write_page_timeout, 0x6000);
va009039 0:1ed23ab1345f 1120 break;
va009039 2:871b41f4789e 1121 case 6:
va009039 2:871b41f4789e 1122 hci_send_cmd(&hci_write_scan_enable, (hci_stack.connectable << 1) | hci_stack.discoverable); // page scan
va009039 2:871b41f4789e 1123 break;
va009039 0:1ed23ab1345f 1124 case 7:
va009039 0:1ed23ab1345f 1125 #ifndef EMBEDDED
va009039 0:1ed23ab1345f 1126 {
va009039 0:1ed23ab1345f 1127 char hostname[30];
va009039 0:1ed23ab1345f 1128 gethostname(hostname, 30);
va009039 0:1ed23ab1345f 1129 hostname[29] = '\0';
va009039 0:1ed23ab1345f 1130 hci_send_cmd(&hci_write_local_name, hostname);
va009039 0:1ed23ab1345f 1131 break;
va009039 0:1ed23ab1345f 1132 }
va009039 0:1ed23ab1345f 1133 case 8:
va009039 0:1ed23ab1345f 1134 #ifdef USE_BLUETOOL
va009039 0:1ed23ab1345f 1135 hci_send_cmd(&hci_write_class_of_device, 0x007a020c); // Smartphone
va009039 0:1ed23ab1345f 1136 break;
va009039 0:1ed23ab1345f 1137
va009039 0:1ed23ab1345f 1138 case 9:
va009039 0:1ed23ab1345f 1139 #endif
va009039 0:1ed23ab1345f 1140 #endif
va009039 0:1ed23ab1345f 1141 // done.
va009039 0:1ed23ab1345f 1142 hci_stack.state = HCI_STATE_WORKING;
va009039 0:1ed23ab1345f 1143 hci_emit_state();
va009039 0:1ed23ab1345f 1144 break;
va009039 0:1ed23ab1345f 1145 default:
va009039 0:1ed23ab1345f 1146 break;
va009039 0:1ed23ab1345f 1147 }
va009039 0:1ed23ab1345f 1148 hci_stack.substate++;
va009039 0:1ed23ab1345f 1149 break;
va009039 0:1ed23ab1345f 1150
va009039 0:1ed23ab1345f 1151 case HCI_STATE_HALTING:
va009039 0:1ed23ab1345f 1152
va009039 0:1ed23ab1345f 1153 log_info("HCI_STATE_HALTING\n");
va009039 0:1ed23ab1345f 1154 // close all open connections
va009039 0:1ed23ab1345f 1155 connection = (hci_connection_t *) hci_stack.connections;
va009039 0:1ed23ab1345f 1156 if (connection){
va009039 0:1ed23ab1345f 1157
va009039 0:1ed23ab1345f 1158 // send disconnect
va009039 0:1ed23ab1345f 1159 if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
va009039 0:1ed23ab1345f 1160
va009039 0:1ed23ab1345f 1161 log_info("HCI_STATE_HALTING, connection %p, handle %u\n", connection, (uint16_t)connection->con_handle);
va009039 0:1ed23ab1345f 1162 hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13); // remote closed connection
va009039 0:1ed23ab1345f 1163
va009039 0:1ed23ab1345f 1164 // send disconnected event right away - causes higher layer connections to get closed, too.
va009039 0:1ed23ab1345f 1165 hci_shutdown_connection(connection);
va009039 0:1ed23ab1345f 1166 return;
va009039 0:1ed23ab1345f 1167 }
va009039 0:1ed23ab1345f 1168 log_info("HCI_STATE_HALTING, calling off\n");
va009039 0:1ed23ab1345f 1169
va009039 0:1ed23ab1345f 1170 // switch mode
va009039 0:1ed23ab1345f 1171 hci_power_control_off();
va009039 0:1ed23ab1345f 1172
va009039 0:1ed23ab1345f 1173 log_info("HCI_STATE_HALTING, emitting state\n");
va009039 0:1ed23ab1345f 1174 hci_emit_state();
va009039 0:1ed23ab1345f 1175 log_info("HCI_STATE_HALTING, done\n");
va009039 0:1ed23ab1345f 1176 break;
va009039 0:1ed23ab1345f 1177
va009039 0:1ed23ab1345f 1178 case HCI_STATE_FALLING_ASLEEP:
va009039 0:1ed23ab1345f 1179 switch(hci_stack.substate) {
va009039 0:1ed23ab1345f 1180 case 0:
va009039 0:1ed23ab1345f 1181 log_info("HCI_STATE_FALLING_ASLEEP\n");
va009039 0:1ed23ab1345f 1182 // close all open connections
va009039 0:1ed23ab1345f 1183 connection = (hci_connection_t *) hci_stack.connections;
va009039 0:1ed23ab1345f 1184
va009039 0:1ed23ab1345f 1185 #if defined(USE_POWERMANAGEMENT) && defined(USE_BLUETOOL)
va009039 0:1ed23ab1345f 1186 // don't close connections, if H4 supports power management
va009039 0:1ed23ab1345f 1187 if (bt_control_iphone_power_management_enabled()){
va009039 0:1ed23ab1345f 1188 connection = NULL;
va009039 0:1ed23ab1345f 1189 }
va009039 0:1ed23ab1345f 1190 #endif
va009039 0:1ed23ab1345f 1191 if (connection){
va009039 0:1ed23ab1345f 1192
va009039 0:1ed23ab1345f 1193 // send disconnect
va009039 0:1ed23ab1345f 1194 if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
va009039 0:1ed23ab1345f 1195
va009039 0:1ed23ab1345f 1196 log_info("HCI_STATE_FALLING_ASLEEP, connection %p, handle %u\n", connection, (uint16_t)connection->con_handle);
va009039 0:1ed23ab1345f 1197 hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13); // remote closed connection
va009039 0:1ed23ab1345f 1198
va009039 0:1ed23ab1345f 1199 // send disconnected event right away - causes higher layer connections to get closed, too.
va009039 0:1ed23ab1345f 1200 hci_shutdown_connection(connection);
va009039 0:1ed23ab1345f 1201 return;
va009039 0:1ed23ab1345f 1202 }
va009039 0:1ed23ab1345f 1203
va009039 0:1ed23ab1345f 1204 // disable page and inquiry scan
va009039 0:1ed23ab1345f 1205 if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
va009039 0:1ed23ab1345f 1206
va009039 0:1ed23ab1345f 1207 log_info("HCI_STATE_HALTING, disabling inq cans\n");
va009039 0:1ed23ab1345f 1208 hci_send_cmd(&hci_write_scan_enable, hci_stack.connectable << 1); // drop inquiry scan but keep page scan
va009039 0:1ed23ab1345f 1209
va009039 0:1ed23ab1345f 1210 // continue in next sub state
va009039 0:1ed23ab1345f 1211 hci_stack.substate++;
va009039 0:1ed23ab1345f 1212 break;
va009039 0:1ed23ab1345f 1213 case 1:
va009039 0:1ed23ab1345f 1214 // wait for command complete "hci_write_scan_enable" in event_handler();
va009039 0:1ed23ab1345f 1215 break;
va009039 0:1ed23ab1345f 1216 case 2:
va009039 0:1ed23ab1345f 1217 log_info("HCI_STATE_HALTING, calling sleep\n");
va009039 0:1ed23ab1345f 1218 #if defined(USE_POWERMANAGEMENT) && defined(USE_BLUETOOL)
va009039 0:1ed23ab1345f 1219 // don't actually go to sleep, if H4 supports power management
va009039 0:1ed23ab1345f 1220 if (bt_control_iphone_power_management_enabled()){
va009039 0:1ed23ab1345f 1221 // SLEEP MODE reached
va009039 0:1ed23ab1345f 1222 hci_stack.state = HCI_STATE_SLEEPING;
va009039 0:1ed23ab1345f 1223 hci_emit_state();
va009039 0:1ed23ab1345f 1224 break;
va009039 0:1ed23ab1345f 1225 }
va009039 0:1ed23ab1345f 1226 #endif
va009039 0:1ed23ab1345f 1227 // switch mode
va009039 0:1ed23ab1345f 1228 hci_power_control_sleep(); // changes hci_stack.state to SLEEP
va009039 0:1ed23ab1345f 1229 hci_emit_state();
va009039 0:1ed23ab1345f 1230 break;
va009039 0:1ed23ab1345f 1231
va009039 0:1ed23ab1345f 1232 default:
va009039 0:1ed23ab1345f 1233 break;
va009039 0:1ed23ab1345f 1234 }
va009039 0:1ed23ab1345f 1235 break;
va009039 0:1ed23ab1345f 1236
va009039 0:1ed23ab1345f 1237 default:
va009039 0:1ed23ab1345f 1238 break;
va009039 0:1ed23ab1345f 1239 }
va009039 0:1ed23ab1345f 1240 }
va009039 0:1ed23ab1345f 1241
va009039 0:1ed23ab1345f 1242 int hci_send_cmd_packet(uint8_t *packet, int size){
va009039 0:1ed23ab1345f 1243 bd_addr_t addr;
va009039 0:1ed23ab1345f 1244 hci_connection_t * conn;
va009039 0:1ed23ab1345f 1245 // house-keeping
va009039 0:1ed23ab1345f 1246
va009039 0:1ed23ab1345f 1247 // create_connection?
va009039 0:1ed23ab1345f 1248 if (IS_COMMAND(packet, hci_create_connection)){
va009039 0:1ed23ab1345f 1249 bt_flip_addr(addr, &packet[3]);
va009039 0:1ed23ab1345f 1250 log_info("Create_connection to %s\n", bd_addr_to_str(addr));
va009039 0:1ed23ab1345f 1251 conn = connection_for_address(addr);
va009039 0:1ed23ab1345f 1252 if (conn) {
va009039 0:1ed23ab1345f 1253 // if connection exists
va009039 0:1ed23ab1345f 1254 if (conn->state == OPEN) {
va009039 0:1ed23ab1345f 1255 // and OPEN, emit connection complete command
va009039 0:1ed23ab1345f 1256 hci_emit_connection_complete(conn, 0);
va009039 0:1ed23ab1345f 1257 }
va009039 0:1ed23ab1345f 1258 // otherwise, just ignore as it is already in the open process
va009039 0:1ed23ab1345f 1259 return 0; // don't sent packet to controller
va009039 0:1ed23ab1345f 1260
va009039 0:1ed23ab1345f 1261 }
va009039 0:1ed23ab1345f 1262 // create connection struct and register, state = SENT_CREATE_CONNECTION
va009039 0:1ed23ab1345f 1263 conn = create_connection_for_addr(addr);
va009039 0:1ed23ab1345f 1264 if (!conn){
va009039 0:1ed23ab1345f 1265 // notify client that alloc failed
va009039 0:1ed23ab1345f 1266 hci_emit_connection_complete(conn, BTSTACK_MEMORY_ALLOC_FAILED);
va009039 0:1ed23ab1345f 1267 return 0; // don't sent packet to controller
va009039 0:1ed23ab1345f 1268 }
va009039 0:1ed23ab1345f 1269 conn->state = SENT_CREATE_CONNECTION;
va009039 0:1ed23ab1345f 1270 }
va009039 0:1ed23ab1345f 1271
va009039 0:1ed23ab1345f 1272 if (IS_COMMAND(packet, hci_link_key_request_reply)){
va009039 0:1ed23ab1345f 1273 hci_add_connection_flags_for_flipped_bd_addr(&packet[3], SENT_LINK_KEY_REPLY);
va009039 0:1ed23ab1345f 1274 }
va009039 0:1ed23ab1345f 1275 if (IS_COMMAND(packet, hci_link_key_request_negative_reply)){
va009039 0:1ed23ab1345f 1276 hci_add_connection_flags_for_flipped_bd_addr(&packet[3], SENT_LINK_KEY_NEGATIVE_REQUEST);
va009039 0:1ed23ab1345f 1277 }
va009039 0:1ed23ab1345f 1278 if (IS_COMMAND(packet, hci_pin_code_request_reply)){
va009039 0:1ed23ab1345f 1279 hci_add_connection_flags_for_flipped_bd_addr(&packet[3], SENT_PIN_CODE_REPLY);
va009039 0:1ed23ab1345f 1280 }
va009039 0:1ed23ab1345f 1281 if (IS_COMMAND(packet, hci_pin_code_request_negative_reply)){
va009039 0:1ed23ab1345f 1282 hci_add_connection_flags_for_flipped_bd_addr(&packet[3], SENT_PIN_CODE_NEGATIVE_REPLY);
va009039 0:1ed23ab1345f 1283 }
va009039 0:1ed23ab1345f 1284
va009039 0:1ed23ab1345f 1285 if (IS_COMMAND(packet, hci_delete_stored_link_key)){
va009039 0:1ed23ab1345f 1286 if (hci_stack.remote_device_db){
va009039 0:1ed23ab1345f 1287 bt_flip_addr(addr, &packet[3]);
va009039 0:1ed23ab1345f 1288 hci_stack.remote_device_db->delete_link_key(&addr);
va009039 0:1ed23ab1345f 1289 }
va009039 0:1ed23ab1345f 1290 }
va009039 0:1ed23ab1345f 1291
va009039 0:1ed23ab1345f 1292 hci_stack.num_cmd_packets--;
va009039 0:1ed23ab1345f 1293 return hci_stack.hci_transport->send_packet(HCI_COMMAND_DATA_PACKET, packet, size);
va009039 0:1ed23ab1345f 1294 }
va009039 0:1ed23ab1345f 1295
va009039 0:1ed23ab1345f 1296 /**
va009039 0:1ed23ab1345f 1297 * pre: numcmds >= 0 - it's allowed to send a command to the controller
va009039 0:1ed23ab1345f 1298 */
va009039 0:1ed23ab1345f 1299 int hci_send_cmd(const hci_cmd_t *cmd, ...){
va009039 0:1ed23ab1345f 1300 va_list argptr;
va009039 0:1ed23ab1345f 1301 va_start(argptr, cmd);
va009039 0:1ed23ab1345f 1302 uint16_t size = hci_create_cmd_internal(hci_stack.hci_packet_buffer, cmd, argptr);
va009039 0:1ed23ab1345f 1303 va_end(argptr);
va009039 0:1ed23ab1345f 1304 return hci_send_cmd_packet(hci_stack.hci_packet_buffer, size);
va009039 0:1ed23ab1345f 1305 }
va009039 0:1ed23ab1345f 1306
va009039 0:1ed23ab1345f 1307 // Create various non-HCI events.
va009039 0:1ed23ab1345f 1308 // TODO: generalize, use table similar to hci_create_command
va009039 0:1ed23ab1345f 1309
va009039 0:1ed23ab1345f 1310 void hci_emit_state(){
va009039 0:1ed23ab1345f 1311 uint8_t event[3];
va009039 0:1ed23ab1345f 1312 event[0] = BTSTACK_EVENT_STATE;
va009039 0:1ed23ab1345f 1313 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1314 event[2] = hci_stack.state;
va009039 0:1ed23ab1345f 1315 hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1316 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1317 }
va009039 0:1ed23ab1345f 1318
va009039 0:1ed23ab1345f 1319 void hci_emit_connection_complete(hci_connection_t *conn, uint8_t status){
va009039 0:1ed23ab1345f 1320 uint8_t event[13];
va009039 0:1ed23ab1345f 1321 event[0] = HCI_EVENT_CONNECTION_COMPLETE;
va009039 0:1ed23ab1345f 1322 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1323 event[2] = status;
va009039 0:1ed23ab1345f 1324 bt_store_16(event, 3, conn->con_handle);
va009039 0:1ed23ab1345f 1325 bt_flip_addr(&event[5], conn->address);
va009039 0:1ed23ab1345f 1326 event[11] = 1; // ACL connection
va009039 0:1ed23ab1345f 1327 event[12] = 0; // encryption disabled
va009039 0:1ed23ab1345f 1328 hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1329 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1330 }
va009039 0:1ed23ab1345f 1331
va009039 0:1ed23ab1345f 1332 void hci_emit_disconnection_complete(uint16_t handle, uint8_t reason){
va009039 0:1ed23ab1345f 1333 uint8_t event[6];
va009039 0:1ed23ab1345f 1334 event[0] = HCI_EVENT_DISCONNECTION_COMPLETE;
va009039 0:1ed23ab1345f 1335 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1336 event[2] = 0; // status = OK
va009039 0:1ed23ab1345f 1337 bt_store_16(event, 3, handle);
va009039 0:1ed23ab1345f 1338 event[5] = reason;
va009039 0:1ed23ab1345f 1339 hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1340 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1341 }
va009039 0:1ed23ab1345f 1342
va009039 0:1ed23ab1345f 1343 void hci_emit_l2cap_check_timeout(hci_connection_t *conn){
va009039 0:1ed23ab1345f 1344 uint8_t event[4];
va009039 0:1ed23ab1345f 1345 event[0] = L2CAP_EVENT_TIMEOUT_CHECK;
va009039 0:1ed23ab1345f 1346 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1347 bt_store_16(event, 2, conn->con_handle);
va009039 0:1ed23ab1345f 1348 hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1349 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1350 }
va009039 0:1ed23ab1345f 1351
va009039 0:1ed23ab1345f 1352 void hci_emit_nr_connections_changed(){
va009039 0:1ed23ab1345f 1353 uint8_t event[3];
va009039 0:1ed23ab1345f 1354 event[0] = BTSTACK_EVENT_NR_CONNECTIONS_CHANGED;
va009039 0:1ed23ab1345f 1355 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1356 event[2] = nr_hci_connections();
va009039 0:1ed23ab1345f 1357 hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1358 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1359 }
va009039 0:1ed23ab1345f 1360
va009039 0:1ed23ab1345f 1361 void hci_emit_hci_open_failed(){
va009039 0:1ed23ab1345f 1362 uint8_t event[2];
va009039 0:1ed23ab1345f 1363 event[0] = BTSTACK_EVENT_POWERON_FAILED;
va009039 0:1ed23ab1345f 1364 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1365 hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1366 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1367 }
va009039 0:1ed23ab1345f 1368
va009039 0:1ed23ab1345f 1369 #ifndef EMBEDDED
va009039 0:1ed23ab1345f 1370 void hci_emit_btstack_version() {
va009039 0:1ed23ab1345f 1371 uint8_t event[6];
va009039 0:1ed23ab1345f 1372 event[0] = BTSTACK_EVENT_VERSION;
va009039 0:1ed23ab1345f 1373 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1374 event[2] = BTSTACK_MAJOR;
va009039 0:1ed23ab1345f 1375 event[3] = BTSTACK_MINOR;
va009039 0:1ed23ab1345f 1376 bt_store_16(event, 4, BTSTACK_REVISION);
va009039 0:1ed23ab1345f 1377 hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1378 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1379 }
va009039 0:1ed23ab1345f 1380 #endif
va009039 0:1ed23ab1345f 1381
va009039 0:1ed23ab1345f 1382 void hci_emit_system_bluetooth_enabled(uint8_t enabled){
va009039 0:1ed23ab1345f 1383 uint8_t event[3];
va009039 0:1ed23ab1345f 1384 event[0] = BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED;
va009039 0:1ed23ab1345f 1385 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1386 event[2] = enabled;
va009039 0:1ed23ab1345f 1387 hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1388 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1389 }
va009039 0:1ed23ab1345f 1390
va009039 0:1ed23ab1345f 1391 void hci_emit_remote_name_cached(bd_addr_t *addr, device_name_t *name){
va009039 0:1ed23ab1345f 1392 uint8_t event[2+1+6+248];
va009039 0:1ed23ab1345f 1393 event[0] = BTSTACK_EVENT_REMOTE_NAME_CACHED;
va009039 0:1ed23ab1345f 1394 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1395 event[2] = 0; // just to be compatible with HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE
va009039 0:1ed23ab1345f 1396 bt_flip_addr(&event[3], *addr);
va009039 0:1ed23ab1345f 1397 memcpy(&event[9], name, 248);
va009039 0:1ed23ab1345f 1398 hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1399 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1400 }
va009039 0:1ed23ab1345f 1401
va009039 0:1ed23ab1345f 1402 void hci_emit_discoverable_enabled(uint8_t enabled){
va009039 0:1ed23ab1345f 1403 uint8_t event[3];
va009039 0:1ed23ab1345f 1404 event[0] = BTSTACK_EVENT_DISCOVERABLE_ENABLED;
va009039 0:1ed23ab1345f 1405 event[1] = sizeof(event) - 2;
va009039 0:1ed23ab1345f 1406 event[2] = enabled;
va009039 0:1ed23ab1345f 1407 hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
va009039 0:1ed23ab1345f 1408 hci_stack.packet_handler(HCI_EVENT_PACKET, event, sizeof(event));
va009039 0:1ed23ab1345f 1409 }