うおーるぼっとをWiiリモコンでコントロールする新しいプログラムです。 以前のものより、Wiiリモコンが早く繋がる様になりました。 It is a program which controls A with the Wii remote. ※ A Bluetooth dongle and a Wii remote control are needed.

Dependencies:   USBHost mbed FATFileSystem mbed-rtos

Committer:
jksoft
Date:
Mon Jun 10 16:01:50 2013 +0000
Revision:
0:fccb789424fc
1.0

Who changed what in which revision?

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