BTstack for Nucleo F401RE/FRDM-KL46Z example program

Dependencies:   F401RE-USBHost mbed

The usage is the same as KL46Z-BTstack_example.
使い方はKL46Z-BTstack_exampleと同じです。
/media/uploads/va009039/f401re-btstack.jpg

Committer:
va009039
Date:
Mon Jun 09 09:03:25 2014 +0000
Revision:
0:a05a07cd6fdf
first commit

Who changed what in which revision?

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