Junichi Katsu / Mbed 2 deprecated BLEControl

Dependencies:   FatFileSystem TB6612FNG2 mbed

Committer:
mbed_Cookbook_SE
Date:
Mon Nov 30 09:32:15 2015 +0000
Revision:
0:de03cbbcd0ff
??

Who changed what in which revision?

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