xref: /btstack/src/hci.c (revision 61f37892ce2f663897f046830ee9796ac9611c6c)
11f504dbdSmatthias.ringwald /*
2a0c35809S[email protected]  * Copyright (C) 2014 BlueKitchen GmbH
31713bceaSmatthias.ringwald  *
41713bceaSmatthias.ringwald  * Redistribution and use in source and binary forms, with or without
51713bceaSmatthias.ringwald  * modification, are permitted provided that the following conditions
61713bceaSmatthias.ringwald  * are met:
71713bceaSmatthias.ringwald  *
81713bceaSmatthias.ringwald  * 1. Redistributions of source code must retain the above copyright
91713bceaSmatthias.ringwald  *    notice, this list of conditions and the following disclaimer.
101713bceaSmatthias.ringwald  * 2. Redistributions in binary form must reproduce the above copyright
111713bceaSmatthias.ringwald  *    notice, this list of conditions and the following disclaimer in the
121713bceaSmatthias.ringwald  *    documentation and/or other materials provided with the distribution.
131713bceaSmatthias.ringwald  * 3. Neither the name of the copyright holders nor the names of
141713bceaSmatthias.ringwald  *    contributors may be used to endorse or promote products derived
151713bceaSmatthias.ringwald  *    from this software without specific prior written permission.
166b64433eSmatthias.ringwald  * 4. Any redistribution, use, or modification is done solely for
176b64433eSmatthias.ringwald  *    personal benefit and not for any commercial purpose or for
186b64433eSmatthias.ringwald  *    monetary gain.
191713bceaSmatthias.ringwald  *
20a0c35809S[email protected]  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
211713bceaSmatthias.ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
221713bceaSmatthias.ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
231713bceaSmatthias.ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
241713bceaSmatthias.ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
251713bceaSmatthias.ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
261713bceaSmatthias.ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
271713bceaSmatthias.ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
281713bceaSmatthias.ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
291713bceaSmatthias.ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
301713bceaSmatthias.ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311713bceaSmatthias.ringwald  * SUCH DAMAGE.
321713bceaSmatthias.ringwald  *
33a0c35809S[email protected]  * Please inquire about commercial licensing options at
34a0c35809S[email protected]  * [email protected]
356b64433eSmatthias.ringwald  *
361713bceaSmatthias.ringwald  */
371713bceaSmatthias.ringwald 
38ab2c6ae4SMatthias Ringwald #define __BTSTACK_FILE__ "hci.c"
39ab2c6ae4SMatthias Ringwald 
401713bceaSmatthias.ringwald /*
411f504dbdSmatthias.ringwald  *  hci.c
421f504dbdSmatthias.ringwald  *
431f504dbdSmatthias.ringwald  *  Created by Matthias Ringwald on 4/29/09.
441f504dbdSmatthias.ringwald  *
451f504dbdSmatthias.ringwald  */
461f504dbdSmatthias.ringwald 
477907f069SMatthias Ringwald #include "btstack_config.h"
4828171530Smatthias.ringwald 
497f2435e6Smatthias.ringwald 
5006b9e820SMatthias Ringwald #ifdef ENABLE_CLASSIC
51aec7654dSMatthias Ringwald #ifdef HAVE_EMBEDDED_TICK
528f2a52f4SMatthias Ringwald #include "btstack_run_loop_embedded.h"
53a484130cSMatthias Ringwald #endif
5406b9e820SMatthias Ringwald #endif
55a484130cSMatthias Ringwald 
564a3574a1SMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
57d0b87befSMatthias Ringwald #include "../port/ios/src/btstack_control_iphone.h"
584a3574a1SMatthias Ringwald #endif
594a3574a1SMatthias Ringwald 
60a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
61472a5742SMatthias Ringwald #include "gap.h"
6245c102fdSMatthias Ringwald #endif
6345c102fdSMatthias Ringwald 
6493b8dc03Smatthias.ringwald #include <stdarg.h>
6593b8dc03Smatthias.ringwald #include <string.h>
6656fe0872Smatthias.ringwald #include <stdio.h>
675838a2edSMatthias Ringwald #include <inttypes.h>
687f2435e6Smatthias.ringwald 
6916ece135SMatthias Ringwald #include "btstack_debug.h"
700e2df43fSMatthias Ringwald #include "btstack_event.h"
714a3574a1SMatthias Ringwald #include "btstack_linked_list.h"
724a3574a1SMatthias Ringwald #include "btstack_memory.h"
73*61f37892SMatthias Ringwald #include "bluetooth_company_id.h"
744a3574a1SMatthias Ringwald #include "gap.h"
754a3574a1SMatthias Ringwald #include "hci.h"
764a3574a1SMatthias Ringwald #include "hci_cmd.h"
77d8905019Smatthias.ringwald #include "hci_dump.h"
7893b8dc03Smatthias.ringwald 
791b0e3922Smatthias.ringwald 
80169f8b28Smatthias.ringwald #define HCI_CONNECTION_TIMEOUT_MS 10000
81659d758cSMatthias Ringwald #define HCI_RESET_RESEND_TIMEOUT_MS 200
82ee091cf1Smatthias.ringwald 
83b83d5eabSMatthias Ringwald // prototypes
8435454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
85758b46ceSmatthias.ringwald static void hci_update_scan_enable(void);
8635454696SMatthias Ringwald static void hci_emit_discoverable_enabled(uint8_t enabled);
8735454696SMatthias Ringwald static int  hci_local_ssp_activated(void);
8835454696SMatthias Ringwald static int  hci_remote_ssp_supported(hci_con_handle_t con_handle);
8935454696SMatthias Ringwald static void hci_notify_if_sco_can_send_now(void);
9035454696SMatthias Ringwald static void hci_emit_connection_complete(bd_addr_t address, hci_con_handle_t con_handle, uint8_t status);
91a00031e2S[email protected] static gap_security_level_t gap_security_level_for_connection(hci_connection_t * connection);
9235454696SMatthias Ringwald static void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t level);
93ec820d77SMatthias Ringwald static void hci_connection_timeout_handler(btstack_timer_source_t *timer);
9496a45072S[email protected] static void hci_connection_timestamp(hci_connection_t *connection);
9552db98b2SMatthias Ringwald static void hci_emit_l2cap_check_timeout(hci_connection_t *conn);
9652db98b2SMatthias Ringwald #endif
977586ee35S[email protected] static int  hci_power_control_on(void);
987586ee35S[email protected] static void hci_power_control_off(void);
996da48142SSean Wilson static void hci_state_reset(void);
100fc64f94aSMatthias Ringwald static void hci_emit_disconnection_complete(hci_con_handle_t con_handle, uint8_t reason);
101b83d5eabSMatthias Ringwald static void hci_emit_nr_connections_changed(void);
102b83d5eabSMatthias Ringwald static void hci_emit_hci_open_failed(void);
103b83d5eabSMatthias Ringwald static void hci_emit_dedicated_bonding_result(bd_addr_t address, uint8_t status);
104b83d5eabSMatthias Ringwald static void hci_emit_event(uint8_t * event, uint16_t size, int dump);
105b83d5eabSMatthias Ringwald static void hci_emit_acl_packet(uint8_t * packet, uint16_t size);
10695d71764SMatthias Ringwald static void hci_run(void);
10795d71764SMatthias Ringwald static int  hci_is_le_connection(hci_connection_t * connection);
10895d71764SMatthias Ringwald static int  hci_number_free_acl_slots_for_connection_type( bd_addr_type_t address_type);
1095d509858SMatthias Ringwald 
110a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
111e8c8828eSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
11239677e66SMatthias Ringwald // called from test/ble_client/advertising_data_parser.c
11339677e66SMatthias Ringwald void le_handle_advertisement_report(uint8_t *packet, int size);
11442ff5ba1SMatthias Ringwald static void hci_remove_from_whitelist(bd_addr_type_t address_type, bd_addr_t address);
1155d509858SMatthias Ringwald #endif
116d70217a2SMatthias Ringwald #endif
117758b46ceSmatthias.ringwald 
11806b35ec0Smatthias.ringwald // the STACK is here
1193a9fb326S[email protected] #ifndef HAVE_MALLOC
1203a9fb326S[email protected] static hci_stack_t   hci_stack_static;
1213a9fb326S[email protected] #endif
1223a9fb326S[email protected] static hci_stack_t * hci_stack = NULL;
12316833f0aSmatthias.ringwald 
1241c9e5e9dSMatthias Ringwald #ifdef ENABLE_CLASSIC
12566fb9560S[email protected] // test helper
12666fb9560S[email protected] static uint8_t disable_l2cap_timeouts = 0;
1271c9e5e9dSMatthias Ringwald #endif
12866fb9560S[email protected] 
12996a45072S[email protected] /**
13096a45072S[email protected]  * create connection for given address
13196a45072S[email protected]  *
13296a45072S[email protected]  * @return connection OR NULL, if no memory left
13396a45072S[email protected]  */
13496a45072S[email protected] static hci_connection_t * create_connection_for_bd_addr_and_type(bd_addr_t addr, bd_addr_type_t addr_type){
1351a06f663S[email protected]     log_info("create_connection_for_addr %s, type %x", bd_addr_to_str(addr), addr_type);
136bb69aaaeS[email protected]     hci_connection_t * conn = btstack_memory_hci_connection_get();
13796a45072S[email protected]     if (!conn) return NULL;
138c91d150bS[email protected]     memset(conn, 0, sizeof(hci_connection_t));
139058e3d6bSMatthias Ringwald     bd_addr_copy(conn->address, addr);
14096a45072S[email protected]     conn->address_type = addr_type;
14196a45072S[email protected]     conn->con_handle = 0xffff;
14296a45072S[email protected]     conn->authentication_flags = AUTH_FLAGS_NONE;
14396a45072S[email protected]     conn->bonding_flags = 0;
14496a45072S[email protected]     conn->requested_security_level = LEVEL_0;
14552db98b2SMatthias Ringwald #ifdef ENABLE_CLASSIC
14691a977e8SMatthias Ringwald     btstack_run_loop_set_timer_handler(&conn->timeout, hci_connection_timeout_handler);
14791a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&conn->timeout, conn);
14896a45072S[email protected]     hci_connection_timestamp(conn);
14952db98b2SMatthias Ringwald #endif
15096a45072S[email protected]     conn->acl_recombination_length = 0;
15196a45072S[email protected]     conn->acl_recombination_pos = 0;
15296a45072S[email protected]     conn->num_acl_packets_sent = 0;
1531a06f663S[email protected]     conn->num_sco_packets_sent = 0;
154da886c03S[email protected]     conn->le_con_parameter_update_state = CON_PARAMETER_UPDATE_NONE;
155665d90f2SMatthias Ringwald     btstack_linked_list_add(&hci_stack->connections, (btstack_linked_item_t *) conn);
15696a45072S[email protected]     return conn;
15796a45072S[email protected] }
15866fb9560S[email protected] 
159da886c03S[email protected] 
160da886c03S[email protected] /**
161da886c03S[email protected]  * get le connection parameter range
162da886c03S[email protected] *
163da886c03S[email protected]  * @return le connection parameter range struct
164da886c03S[email protected]  */
1654ced4e8cSMatthias Ringwald void gap_get_connection_parameter_range(le_connection_parameter_range_t * range){
1664ced4e8cSMatthias Ringwald     *range = hci_stack->le_connection_parameter_range;
167da886c03S[email protected] }
168da886c03S[email protected] 
169da886c03S[email protected] /**
170da886c03S[email protected]  * set le connection parameter range
171da886c03S[email protected]  *
172da886c03S[email protected]  */
173da886c03S[email protected] 
1744ced4e8cSMatthias Ringwald void gap_set_connection_parameter_range(le_connection_parameter_range_t *range){
1754ced4e8cSMatthias Ringwald     hci_stack->le_connection_parameter_range = *range;
176da886c03S[email protected] }
177da886c03S[email protected] 
178da886c03S[email protected] /**
179da886c03S[email protected]  * get hci connections iterator
180da886c03S[email protected]  *
181da886c03S[email protected]  * @return hci connections iterator
182da886c03S[email protected]  */
183da886c03S[email protected] 
184665d90f2SMatthias Ringwald void hci_connections_get_iterator(btstack_linked_list_iterator_t *it){
185665d90f2SMatthias Ringwald     btstack_linked_list_iterator_init(it, &hci_stack->connections);
186da886c03S[email protected] }
187da886c03S[email protected] 
18897addcc5Smatthias.ringwald /**
189ee091cf1Smatthias.ringwald  * get connection for a given handle
190ee091cf1Smatthias.ringwald  *
191ee091cf1Smatthias.ringwald  * @return connection OR NULL, if not found
192ee091cf1Smatthias.ringwald  */
1935061f3afS[email protected] hci_connection_t * hci_connection_for_handle(hci_con_handle_t con_handle){
194665d90f2SMatthias Ringwald     btstack_linked_list_iterator_t it;
195665d90f2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &hci_stack->connections);
196665d90f2SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
197665d90f2SMatthias Ringwald         hci_connection_t * item = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
1983ac2fe56S[email protected]         if ( item->con_handle == con_handle ) {
199da886c03S[email protected]             return item;
200ee091cf1Smatthias.ringwald         }
201ee091cf1Smatthias.ringwald     }
202ee091cf1Smatthias.ringwald     return NULL;
203ee091cf1Smatthias.ringwald }
204ee091cf1Smatthias.ringwald 
20596a45072S[email protected] /**
20696a45072S[email protected]  * get connection for given address
20796a45072S[email protected]  *
20896a45072S[email protected]  * @return connection OR NULL, if not found
20996a45072S[email protected]  */
2102e77e513S[email protected] hci_connection_t * hci_connection_for_bd_addr_and_type(bd_addr_t  addr, bd_addr_type_t addr_type){
211665d90f2SMatthias Ringwald     btstack_linked_list_iterator_t it;
212665d90f2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &hci_stack->connections);
213665d90f2SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
214665d90f2SMatthias Ringwald         hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
21596a45072S[email protected]         if (connection->address_type != addr_type)  continue;
21696a45072S[email protected]         if (memcmp(addr, connection->address, 6) != 0) continue;
21762bda3fbS[email protected]         return connection;
21862bda3fbS[email protected]     }
21962bda3fbS[email protected]     return NULL;
22062bda3fbS[email protected] }
22162bda3fbS[email protected] 
22252db98b2SMatthias Ringwald 
22352db98b2SMatthias Ringwald #ifdef ENABLE_CLASSIC
22452db98b2SMatthias Ringwald 
225ee752bb8SMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
226ee752bb8SMatthias Ringwald static int hci_number_sco_connections(void){
227ee752bb8SMatthias Ringwald     int connections = 0;
228ee752bb8SMatthias Ringwald     btstack_linked_list_iterator_t it;
229ee752bb8SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &hci_stack->connections);
230ee752bb8SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
231ee752bb8SMatthias Ringwald         hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
232ee752bb8SMatthias Ringwald         if (connection->address_type != BD_ADDR_TYPE_SCO) continue;
233ee752bb8SMatthias Ringwald         connections++;
234ee752bb8SMatthias Ringwald     }
235ee752bb8SMatthias Ringwald     return connections;
236ee752bb8SMatthias Ringwald }
237ee752bb8SMatthias Ringwald #endif
238ee752bb8SMatthias Ringwald 
239ec820d77SMatthias Ringwald static void hci_connection_timeout_handler(btstack_timer_source_t *timer){
24091a977e8SMatthias Ringwald     hci_connection_t * connection = (hci_connection_t *) btstack_run_loop_get_timer_context(timer);
241aec7654dSMatthias Ringwald #ifdef HAVE_EMBEDDED_TICK
242528a4a3bSMatthias Ringwald     if (btstack_run_loop_embedded_get_ticks() > connection->timestamp + btstack_run_loop_embedded_ticks_for_ms(HCI_CONNECTION_TIMEOUT_MS)){
243c785ef68Smatthias.ringwald         // connections might be timed out
244c785ef68Smatthias.ringwald         hci_emit_l2cap_check_timeout(connection);
245c785ef68Smatthias.ringwald     }
246f316a845SMatthias Ringwald #else
247528a4a3bSMatthias Ringwald     if (btstack_run_loop_get_time_ms() > connection->timestamp + HCI_CONNECTION_TIMEOUT_MS){
2485f26aadcSMatthias Ringwald         // connections might be timed out
2495f26aadcSMatthias Ringwald         hci_emit_l2cap_check_timeout(connection);
2505f26aadcSMatthias Ringwald     }
2515f26aadcSMatthias Ringwald #endif
252c785ef68Smatthias.ringwald }
253ee091cf1Smatthias.ringwald 
254ee091cf1Smatthias.ringwald static void hci_connection_timestamp(hci_connection_t *connection){
255aec7654dSMatthias Ringwald #ifdef HAVE_EMBEDDED_TICK
256528a4a3bSMatthias Ringwald     connection->timestamp = btstack_run_loop_embedded_get_ticks();
257f316a845SMatthias Ringwald #else
258528a4a3bSMatthias Ringwald     connection->timestamp = btstack_run_loop_get_time_ms();
2595f26aadcSMatthias Ringwald #endif
260ee091cf1Smatthias.ringwald }
261ee091cf1Smatthias.ringwald 
26228ca2b46S[email protected] inline static void connectionSetAuthenticationFlags(hci_connection_t * conn, hci_authentication_flags_t flags){
26328ca2b46S[email protected]     conn->authentication_flags = (hci_authentication_flags_t)(conn->authentication_flags | flags);
26428ca2b46S[email protected] }
26528ca2b46S[email protected] 
26635454696SMatthias Ringwald 
26728ca2b46S[email protected] inline static void connectionClearAuthenticationFlags(hci_connection_t * conn, hci_authentication_flags_t flags){
26828ca2b46S[email protected]     conn->authentication_flags = (hci_authentication_flags_t)(conn->authentication_flags & ~flags);
26928ca2b46S[email protected] }
27028ca2b46S[email protected] 
27143bfb1bdSmatthias.ringwald /**
27280ca58a0Smatthias.ringwald  * add authentication flags and reset timer
27396a45072S[email protected]  * @note: assumes classic connection
2742e77e513S[email protected]  * @note: bd_addr is passed in as litle endian uint8_t * as it is called from parsing packets
2757fde4af9Smatthias.ringwald  */
2767fde4af9Smatthias.ringwald static void hci_add_connection_flags_for_flipped_bd_addr(uint8_t *bd_addr, hci_authentication_flags_t flags){
2777fde4af9Smatthias.ringwald     bd_addr_t addr;
278724d70a2SMatthias Ringwald     reverse_bd_addr(bd_addr, addr);
2792e77e513S[email protected]     hci_connection_t * conn = hci_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_CLASSIC);
2807fde4af9Smatthias.ringwald     if (conn) {
28128ca2b46S[email protected]         connectionSetAuthenticationFlags(conn, flags);
28280ca58a0Smatthias.ringwald         hci_connection_timestamp(conn);
2837fde4af9Smatthias.ringwald     }
2847fde4af9Smatthias.ringwald }
2857fde4af9Smatthias.ringwald 
28680ca58a0Smatthias.ringwald int  hci_authentication_active_for_handle(hci_con_handle_t handle){
2875061f3afS[email protected]     hci_connection_t * conn = hci_connection_for_handle(handle);
28880ca58a0Smatthias.ringwald     if (!conn) return 0;
2896724cd9eS[email protected]     if (conn->authentication_flags & LEGACY_PAIRING_ACTIVE) return 1;
2906724cd9eS[email protected]     if (conn->authentication_flags & SSP_PAIRING_ACTIVE) return 1;
2916724cd9eS[email protected]     return 0;
29280ca58a0Smatthias.ringwald }
29380ca58a0Smatthias.ringwald 
29415a95bd5SMatthias Ringwald void gap_drop_link_key_for_bd_addr(bd_addr_t addr){
29555597469SMatthias Ringwald     if (!hci_stack->link_key_db) return;
2962bacf595SMatthias Ringwald     log_info("gap_drop_link_key_for_bd_addr: %s", bd_addr_to_str(addr));
297a98592bcSMatthias Ringwald     hci_stack->link_key_db->delete_link_key(addr);
298c12e46e7Smatthias.ringwald }
29955597469SMatthias Ringwald 
30055597469SMatthias Ringwald void gap_store_link_key_for_bd_addr(bd_addr_t addr, link_key_t link_key, link_key_type_t type){
30155597469SMatthias Ringwald     if (!hci_stack->link_key_db) return;
3022bacf595SMatthias Ringwald     log_info("gap_store_link_key_for_bd_addr: %s, type %u", bd_addr_to_str(addr), type);
30355597469SMatthias Ringwald     hci_stack->link_key_db->put_link_key(addr, link_key, type);
304c12e46e7Smatthias.ringwald }
30535454696SMatthias Ringwald #endif
306c12e46e7Smatthias.ringwald 
30795d71764SMatthias Ringwald static int hci_is_le_connection(hci_connection_t * connection){
3080bf6344aS[email protected]     return  connection->address_type == BD_ADDR_TYPE_LE_PUBLIC ||
3090bf6344aS[email protected]     connection->address_type == BD_ADDR_TYPE_LE_RANDOM;
3100bf6344aS[email protected] }
3110bf6344aS[email protected] 
3127fde4af9Smatthias.ringwald /**
31343bfb1bdSmatthias.ringwald  * count connections
31443bfb1bdSmatthias.ringwald  */
31540d1c7a4Smatthias.ringwald static int nr_hci_connections(void){
31656c253c9Smatthias.ringwald     int count = 0;
317665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
318665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) hci_stack->connections; it ; it = it->next, count++);
31943bfb1bdSmatthias.ringwald     return count;
32043bfb1bdSmatthias.ringwald }
321c8e4258aSmatthias.ringwald 
32295d71764SMatthias Ringwald static int hci_number_free_acl_slots_for_connection_type(bd_addr_type_t address_type){
323ee303eddS[email protected] 
324f04a0c31SMatthias Ringwald     unsigned int num_packets_sent_classic = 0;
325f04a0c31SMatthias Ringwald     unsigned int num_packets_sent_le = 0;
326ee303eddS[email protected] 
327665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
328665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) hci_stack->connections; it ; it = it->next){
329998906cdSmatthias.ringwald         hci_connection_t * connection = (hci_connection_t *) it;
330ee303eddS[email protected]         if (connection->address_type == BD_ADDR_TYPE_CLASSIC){
331ee303eddS[email protected]             num_packets_sent_classic += connection->num_acl_packets_sent;
332ee303eddS[email protected]         } else {
333ee303eddS[email protected]             num_packets_sent_le += connection->num_acl_packets_sent;
334ee303eddS[email protected]         }
335ee303eddS[email protected]     }
336d999b54eSMatthias Ringwald     log_debug("ACL classic buffers: %u used of %u", num_packets_sent_classic, hci_stack->acl_packets_total_num);
337ee303eddS[email protected]     int free_slots_classic = hci_stack->acl_packets_total_num - num_packets_sent_classic;
338ee303eddS[email protected]     int free_slots_le = 0;
339ee303eddS[email protected] 
340ee303eddS[email protected]     if (free_slots_classic < 0){
3419da54300S[email protected]         log_error("hci_number_free_acl_slots: outgoing classic packets (%u) > total classic packets (%u)", num_packets_sent_classic, hci_stack->acl_packets_total_num);
342998906cdSmatthias.ringwald         return 0;
343998906cdSmatthias.ringwald     }
344ee303eddS[email protected] 
345ee303eddS[email protected]     if (hci_stack->le_acl_packets_total_num){
346ee303eddS[email protected]         // if we have LE slots, they are used
347ee303eddS[email protected]         free_slots_le = hci_stack->le_acl_packets_total_num - num_packets_sent_le;
348ee303eddS[email protected]         if (free_slots_le < 0){
3499da54300S[email protected]             log_error("hci_number_free_acl_slots: outgoing le packets (%u) > total le packets (%u)", num_packets_sent_le, hci_stack->le_acl_packets_total_num);
350ee303eddS[email protected]             return 0;
351998906cdSmatthias.ringwald         }
352ee303eddS[email protected]     } else {
353ee303eddS[email protected]         // otherwise, classic slots are used for LE, too
354ee303eddS[email protected]         free_slots_classic -= num_packets_sent_le;
355ee303eddS[email protected]         if (free_slots_classic < 0){
3569da54300S[email protected]             log_error("hci_number_free_acl_slots: outgoing classic + le packets (%u + %u) > total packets (%u)", num_packets_sent_classic, num_packets_sent_le, hci_stack->acl_packets_total_num);
357ee303eddS[email protected]             return 0;
358ee303eddS[email protected]         }
359ee303eddS[email protected]     }
360ee303eddS[email protected] 
361ee303eddS[email protected]     switch (address_type){
362ee303eddS[email protected]         case BD_ADDR_TYPE_UNKNOWN:
3632125de09SMatthias Ringwald             log_error("hci_number_free_acl_slots: unknown address type");
364ee303eddS[email protected]             return 0;
365ee303eddS[email protected] 
366ee303eddS[email protected]         case BD_ADDR_TYPE_CLASSIC:
367ee303eddS[email protected]             return free_slots_classic;
368ee303eddS[email protected] 
369ee303eddS[email protected]         default:
370cb00d3aaS[email protected]            if (hci_stack->le_acl_packets_total_num){
371ee303eddS[email protected]                return free_slots_le;
372ee303eddS[email protected]            }
373cb00d3aaS[email protected]            return free_slots_classic;
374cb00d3aaS[email protected]     }
375998906cdSmatthias.ringwald }
376998906cdSmatthias.ringwald 
3772125de09SMatthias Ringwald int hci_number_free_acl_slots_for_handle(hci_con_handle_t con_handle){
3782125de09SMatthias Ringwald     // get connection type
3792125de09SMatthias Ringwald     hci_connection_t * connection = hci_connection_for_handle(con_handle);
3802125de09SMatthias Ringwald     if (!connection){
3812125de09SMatthias Ringwald         log_error("hci_number_free_acl_slots: handle 0x%04x not in connection list", con_handle);
3822125de09SMatthias Ringwald         return 0;
3832125de09SMatthias Ringwald     }
3842125de09SMatthias Ringwald     return hci_number_free_acl_slots_for_connection_type(connection->address_type);
3852125de09SMatthias Ringwald }
3862125de09SMatthias Ringwald 
38735454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
388701e3307SMatthias Ringwald static int hci_number_free_sco_slots(void){
389f04a0c31SMatthias Ringwald     unsigned int num_sco_packets_sent  = 0;
390665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
391665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) hci_stack->connections; it ; it = it->next){
392e35edcc1S[email protected]         hci_connection_t * connection = (hci_connection_t *) it;
393e35edcc1S[email protected]         num_sco_packets_sent += connection->num_sco_packets_sent;
394e35edcc1S[email protected]     }
395e35edcc1S[email protected]     if (num_sco_packets_sent > hci_stack->sco_packets_total_num){
396701e3307SMatthias Ringwald         log_info("hci_number_free_sco_slots:packets (%u) > total packets (%u)", num_sco_packets_sent, hci_stack->sco_packets_total_num);
39744d0e3d5S[email protected]         return 0;
39844d0e3d5S[email protected]     }
399701e3307SMatthias Ringwald     // log_info("hci_number_free_sco_slots u", handle, num_sco_packets_sent);
400e35edcc1S[email protected]     return hci_stack->sco_packets_total_num - num_sco_packets_sent;
401e35edcc1S[email protected] }
40235454696SMatthias Ringwald #endif
40344d0e3d5S[email protected] 
404ac928cc2S[email protected] // new functions replacing hci_can_send_packet_now[_using_packet_buffer]
405ac928cc2S[email protected] int hci_can_send_command_packet_now(void){
406ac928cc2S[email protected]     if (hci_stack->hci_packet_buffer_reserved) return 0;
407ac928cc2S[email protected] 
408ac928cc2S[email protected]     // check for async hci transport implementations
409ac928cc2S[email protected]     if (hci_stack->hci_transport->can_send_packet_now){
410ac928cc2S[email protected]         if (!hci_stack->hci_transport->can_send_packet_now(HCI_COMMAND_DATA_PACKET)){
411ac928cc2S[email protected]             return 0;
412ac928cc2S[email protected]         }
413ac928cc2S[email protected]     }
414ac928cc2S[email protected] 
415ac928cc2S[email protected]     return hci_stack->num_cmd_packets > 0;
416ac928cc2S[email protected] }
417ac928cc2S[email protected] 
4189d04d3a7SMatthias Ringwald static int hci_transport_can_send_prepared_packet_now(uint8_t packet_type){
419ac928cc2S[email protected]     // check for async hci transport implementations
4209d04d3a7SMatthias Ringwald     if (!hci_stack->hci_transport->can_send_packet_now) return 1;
4219d04d3a7SMatthias Ringwald     return hci_stack->hci_transport->can_send_packet_now(packet_type);
422ac928cc2S[email protected] }
4239d04d3a7SMatthias Ringwald 
4249d04d3a7SMatthias Ringwald static int hci_can_send_prepared_acl_packet_for_address_type(bd_addr_type_t address_type){
4259d04d3a7SMatthias Ringwald     if (!hci_transport_can_send_prepared_packet_now(HCI_ACL_DATA_PACKET)) return 0;
4269d04d3a7SMatthias Ringwald     return hci_number_free_acl_slots_for_connection_type(address_type) > 0;
427ac928cc2S[email protected] }
4289d04d3a7SMatthias Ringwald 
4299d04d3a7SMatthias Ringwald int hci_can_send_acl_le_packet_now(void){
4309d04d3a7SMatthias Ringwald     if (hci_stack->hci_packet_buffer_reserved) return 0;
4319d04d3a7SMatthias Ringwald     return hci_can_send_prepared_acl_packet_for_address_type(BD_ADDR_TYPE_LE_PUBLIC);
4329d04d3a7SMatthias Ringwald }
4339d04d3a7SMatthias Ringwald 
4349d04d3a7SMatthias Ringwald int hci_can_send_prepared_acl_packet_now(hci_con_handle_t con_handle) {
4359d04d3a7SMatthias Ringwald     if (!hci_transport_can_send_prepared_packet_now(HCI_ACL_DATA_PACKET)) return 0;
436e79abdd6S[email protected]     return hci_number_free_acl_slots_for_handle(con_handle) > 0;
437ac928cc2S[email protected] }
438ac928cc2S[email protected] 
439ac928cc2S[email protected] int hci_can_send_acl_packet_now(hci_con_handle_t con_handle){
440ac928cc2S[email protected]     if (hci_stack->hci_packet_buffer_reserved) return 0;
441ac928cc2S[email protected]     return hci_can_send_prepared_acl_packet_now(con_handle);
4426b4af23dS[email protected] }
4436b4af23dS[email protected] 
44435454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
44535454696SMatthias Ringwald int hci_can_send_acl_classic_packet_now(void){
44635454696SMatthias Ringwald     if (hci_stack->hci_packet_buffer_reserved) return 0;
44735454696SMatthias Ringwald     return hci_can_send_prepared_acl_packet_for_address_type(BD_ADDR_TYPE_CLASSIC);
44835454696SMatthias Ringwald }
44935454696SMatthias Ringwald 
450701e3307SMatthias Ringwald int hci_can_send_prepared_sco_packet_now(void){
451d057580eSMatthias Ringwald     if (!hci_transport_can_send_prepared_packet_now(HCI_SCO_DATA_PACKET)) return 0;
452ed361f5fSMatthias Ringwald     if (!hci_stack->synchronous_flow_control_enabled) return 1;
453701e3307SMatthias Ringwald     return hci_number_free_sco_slots() > 0;
45444d0e3d5S[email protected] }
45544d0e3d5S[email protected] 
456701e3307SMatthias Ringwald int hci_can_send_sco_packet_now(void){
457d057580eSMatthias Ringwald     if (hci_stack->hci_packet_buffer_reserved) return 0;
458701e3307SMatthias Ringwald     return hci_can_send_prepared_sco_packet_now();
45944d0e3d5S[email protected] }
46044d0e3d5S[email protected] 
461d057580eSMatthias Ringwald void hci_request_sco_can_send_now_event(void){
462d057580eSMatthias Ringwald     hci_stack->sco_waiting_for_can_send_now = 1;
463d057580eSMatthias Ringwald     hci_notify_if_sco_can_send_now();
464d057580eSMatthias Ringwald }
46535454696SMatthias Ringwald #endif
466d057580eSMatthias Ringwald 
46795d71764SMatthias Ringwald // used for internal checks in l2cap.c
468c8b9416aS[email protected] int hci_is_packet_buffer_reserved(void){
469c8b9416aS[email protected]     return hci_stack->hci_packet_buffer_reserved;
470c8b9416aS[email protected] }
471c8b9416aS[email protected] 
4726b4af23dS[email protected] // reserves outgoing packet buffer. @returns 1 if successful
4736b4af23dS[email protected] int hci_reserve_packet_buffer(void){
4749d14b626S[email protected]     if (hci_stack->hci_packet_buffer_reserved) {
4759d14b626S[email protected]         log_error("hci_reserve_packet_buffer called but buffer already reserved");
4769d14b626S[email protected]         return 0;
4779d14b626S[email protected]     }
4786b4af23dS[email protected]     hci_stack->hci_packet_buffer_reserved = 1;
4796b4af23dS[email protected]     return 1;
4806b4af23dS[email protected] }
4816b4af23dS[email protected] 
48268a0fcf7S[email protected] void hci_release_packet_buffer(void){
48368a0fcf7S[email protected]     hci_stack->hci_packet_buffer_reserved = 0;
48468a0fcf7S[email protected] }
48568a0fcf7S[email protected] 
4866b4af23dS[email protected] // assumption: synchronous implementations don't provide can_send_packet_now as they don't keep the buffer after the call
4877f02f414SMatthias Ringwald static int hci_transport_synchronous(void){
4886b4af23dS[email protected]     return hci_stack->hci_transport->can_send_packet_now == NULL;
4896b4af23dS[email protected] }
4906b4af23dS[email protected] 
491452cf3bbS[email protected] static int hci_send_acl_packet_fragments(hci_connection_t *connection){
492452cf3bbS[email protected] 
493452cf3bbS[email protected]     // log_info("hci_send_acl_packet_fragments  %u/%u (con 0x%04x)", hci_stack->acl_fragmentation_pos, hci_stack->acl_fragmentation_total_size, connection->con_handle);
494452cf3bbS[email protected] 
495452cf3bbS[email protected]     // max ACL data packet length depends on connection type (LE vs. Classic) and available buffers
496452cf3bbS[email protected]     uint16_t max_acl_data_packet_length = hci_stack->acl_data_packet_length;
497452cf3bbS[email protected]     if (hci_is_le_connection(connection) && hci_stack->le_data_packets_length > 0){
498452cf3bbS[email protected]         max_acl_data_packet_length = hci_stack->le_data_packets_length;
499452cf3bbS[email protected]     }
500452cf3bbS[email protected] 
501452cf3bbS[email protected]     // testing: reduce buffer to minimum
502452cf3bbS[email protected]     // max_acl_data_packet_length = 52;
503452cf3bbS[email protected] 
504d999b54eSMatthias Ringwald     log_debug("hci_send_acl_packet_fragments entered");
505d999b54eSMatthias Ringwald 
506452cf3bbS[email protected]     int err;
507452cf3bbS[email protected]     // multiple packets could be send on a synchronous HCI transport
508452cf3bbS[email protected]     while (1){
509452cf3bbS[email protected] 
510d999b54eSMatthias Ringwald         log_debug("hci_send_acl_packet_fragments loop entered");
511d999b54eSMatthias Ringwald 
512452cf3bbS[email protected]         // get current data
513452cf3bbS[email protected]         const uint16_t acl_header_pos = hci_stack->acl_fragmentation_pos - 4;
514452cf3bbS[email protected]         int current_acl_data_packet_length = hci_stack->acl_fragmentation_total_size - hci_stack->acl_fragmentation_pos;
515452cf3bbS[email protected]         int more_fragments = 0;
516452cf3bbS[email protected] 
517452cf3bbS[email protected]         // if ACL packet is larger than Bluetooth packet buffer, only send max_acl_data_packet_length
518452cf3bbS[email protected]         if (current_acl_data_packet_length > max_acl_data_packet_length){
519452cf3bbS[email protected]             more_fragments = 1;
520452cf3bbS[email protected]             current_acl_data_packet_length = max_acl_data_packet_length;
521452cf3bbS[email protected]         }
522452cf3bbS[email protected] 
523452cf3bbS[email protected]         // copy handle_and_flags if not first fragment and update packet boundary flags to be 01 (continuing fragmnent)
524452cf3bbS[email protected]         if (acl_header_pos > 0){
525f8fbdce0SMatthias Ringwald             uint16_t handle_and_flags = little_endian_read_16(hci_stack->hci_packet_buffer, 0);
526452cf3bbS[email protected]             handle_and_flags = (handle_and_flags & 0xcfff) | (1 << 12);
527f8fbdce0SMatthias Ringwald             little_endian_store_16(hci_stack->hci_packet_buffer, acl_header_pos, handle_and_flags);
528452cf3bbS[email protected]         }
529452cf3bbS[email protected] 
530452cf3bbS[email protected]         // update header len
531f8fbdce0SMatthias Ringwald         little_endian_store_16(hci_stack->hci_packet_buffer, acl_header_pos + 2, current_acl_data_packet_length);
532452cf3bbS[email protected] 
533452cf3bbS[email protected]         // count packet
534452cf3bbS[email protected]         connection->num_acl_packets_sent++;
535f04a0c31SMatthias Ringwald         log_debug("hci_send_acl_packet_fragments loop before send (more fragments %d)", more_fragments);
536d999b54eSMatthias Ringwald 
537d999b54eSMatthias Ringwald         // update state for next fragment (if any) as "transport done" might be sent during send_packet already
538d999b54eSMatthias Ringwald         if (more_fragments){
539d999b54eSMatthias Ringwald             // update start of next fragment to send
540d999b54eSMatthias Ringwald             hci_stack->acl_fragmentation_pos += current_acl_data_packet_length;
541d999b54eSMatthias Ringwald         } else {
542d999b54eSMatthias Ringwald             // done
543d999b54eSMatthias Ringwald             hci_stack->acl_fragmentation_pos = 0;
544d999b54eSMatthias Ringwald             hci_stack->acl_fragmentation_total_size = 0;
545d999b54eSMatthias Ringwald         }
546452cf3bbS[email protected] 
547452cf3bbS[email protected]         // send packet
548452cf3bbS[email protected]         uint8_t * packet = &hci_stack->hci_packet_buffer[acl_header_pos];
549452cf3bbS[email protected]         const int size = current_acl_data_packet_length + 4;
5505bb5bc3eS[email protected]         hci_dump_packet(HCI_ACL_DATA_PACKET, 0, packet, size);
551452cf3bbS[email protected]         err = hci_stack->hci_transport->send_packet(HCI_ACL_DATA_PACKET, packet, size);
552452cf3bbS[email protected] 
553f04a0c31SMatthias Ringwald         log_debug("hci_send_acl_packet_fragments loop after send (more fragments %d)", more_fragments);
554d999b54eSMatthias Ringwald 
555452cf3bbS[email protected]         // done yet?
556452cf3bbS[email protected]         if (!more_fragments) break;
557452cf3bbS[email protected] 
558452cf3bbS[email protected]         // can send more?
559452cf3bbS[email protected]         if (!hci_can_send_prepared_acl_packet_now(connection->con_handle)) return err;
560452cf3bbS[email protected]     }
561452cf3bbS[email protected] 
562d999b54eSMatthias Ringwald     log_debug("hci_send_acl_packet_fragments loop over");
563452cf3bbS[email protected] 
564d051460cS[email protected]     // release buffer now for synchronous transport
565203bace6S[email protected]     if (hci_transport_synchronous()){
566452cf3bbS[email protected]         hci_release_packet_buffer();
56763fa3374SMatthias Ringwald         // notify upper stack that it might be possible to send again
56863fa3374SMatthias Ringwald         uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
569d6b06661SMatthias Ringwald         hci_emit_event(&event[0], sizeof(event), 0);  // don't dump
570452cf3bbS[email protected]     }
571452cf3bbS[email protected] 
572452cf3bbS[email protected]     return err;
573452cf3bbS[email protected] }
574452cf3bbS[email protected] 
575826f7347S[email protected] // pre: caller has reserved the packet buffer
576826f7347S[email protected] int hci_send_acl_packet_buffer(int size){
5777856c818Smatthias.ringwald 
578452cf3bbS[email protected]     // log_info("hci_send_acl_packet_buffer size %u", size);
579452cf3bbS[email protected] 
580826f7347S[email protected]     if (!hci_stack->hci_packet_buffer_reserved) {
581826f7347S[email protected]         log_error("hci_send_acl_packet_buffer called without reserving packet buffer");
582826f7347S[email protected]         return 0;
583826f7347S[email protected]     }
584826f7347S[email protected] 
585d713a683S[email protected]     uint8_t * packet = hci_stack->hci_packet_buffer;
586d713a683S[email protected]     hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(packet);
587d713a683S[email protected] 
588826f7347S[email protected]     // check for free places on Bluetooth module
589d713a683S[email protected]     if (!hci_can_send_prepared_acl_packet_now(con_handle)) {
590826f7347S[email protected]         log_error("hci_send_acl_packet_buffer called but no free ACL buffers on controller");
59197b61c7bS[email protected]         hci_release_packet_buffer();
59297b61c7bS[email protected]         return BTSTACK_ACL_BUFFERS_FULL;
59397b61c7bS[email protected]     }
5946218e6f1Smatthias.ringwald 
5955061f3afS[email protected]     hci_connection_t *connection = hci_connection_for_handle( con_handle);
59697b61c7bS[email protected]     if (!connection) {
5975fa0b7cfS[email protected]         log_error("hci_send_acl_packet_buffer called but no connection for handle 0x%04x", con_handle);
59897b61c7bS[email protected]         hci_release_packet_buffer();
59997b61c7bS[email protected]         return 0;
60097b61c7bS[email protected]     }
60152db98b2SMatthias Ringwald 
60252db98b2SMatthias Ringwald #ifdef ENABLE_CLASSIC
60356cf178bSmatthias.ringwald     hci_connection_timestamp(connection);
60452db98b2SMatthias Ringwald #endif
60556cf178bSmatthias.ringwald 
606452cf3bbS[email protected]     // hci_dump_packet( HCI_ACL_DATA_PACKET, 0, packet, size);
6077856c818Smatthias.ringwald 
608452cf3bbS[email protected]     // setup data
609452cf3bbS[email protected]     hci_stack->acl_fragmentation_total_size = size;
610452cf3bbS[email protected]     hci_stack->acl_fragmentation_pos = 4;   // start of L2CAP packet
6116218e6f1Smatthias.ringwald 
612452cf3bbS[email protected]     return hci_send_acl_packet_fragments(connection);
613ee091cf1Smatthias.ringwald }
614ee091cf1Smatthias.ringwald 
61535454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
61644d0e3d5S[email protected] // pre: caller has reserved the packet buffer
61744d0e3d5S[email protected] int hci_send_sco_packet_buffer(int size){
61844d0e3d5S[email protected] 
61944d0e3d5S[email protected]     // log_info("hci_send_acl_packet_buffer size %u", size);
62044d0e3d5S[email protected] 
62144d0e3d5S[email protected]     if (!hci_stack->hci_packet_buffer_reserved) {
62244d0e3d5S[email protected]         log_error("hci_send_acl_packet_buffer called without reserving packet buffer");
62344d0e3d5S[email protected]         return 0;
62444d0e3d5S[email protected]     }
62544d0e3d5S[email protected] 
62644d0e3d5S[email protected]     uint8_t * packet = hci_stack->hci_packet_buffer;
6274b3e1e19SMatthias Ringwald 
6284b3e1e19SMatthias Ringwald     // skip checks in loopback mode
6294b3e1e19SMatthias Ringwald     if (!hci_stack->loopback_mode){
63044d0e3d5S[email protected]         hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(packet);   // same for ACL and SCO
63144d0e3d5S[email protected] 
63244d0e3d5S[email protected]         // check for free places on Bluetooth module
633701e3307SMatthias Ringwald         if (!hci_can_send_prepared_sco_packet_now()) {
63444d0e3d5S[email protected]             log_error("hci_send_sco_packet_buffer called but no free ACL buffers on controller");
63544d0e3d5S[email protected]             hci_release_packet_buffer();
63644d0e3d5S[email protected]             return BTSTACK_ACL_BUFFERS_FULL;
63744d0e3d5S[email protected]         }
63844d0e3d5S[email protected] 
639e35edcc1S[email protected]         // track send packet in connection struct
640e35edcc1S[email protected]         hci_connection_t *connection = hci_connection_for_handle( con_handle);
641e35edcc1S[email protected]         if (!connection) {
642e35edcc1S[email protected]             log_error("hci_send_sco_packet_buffer called but no connection for handle 0x%04x", con_handle);
643e35edcc1S[email protected]             hci_release_packet_buffer();
644e35edcc1S[email protected]             return 0;
645e35edcc1S[email protected]         }
646e35edcc1S[email protected]         connection->num_sco_packets_sent++;
6474b3e1e19SMatthias Ringwald     }
64844d0e3d5S[email protected] 
64944d0e3d5S[email protected]     hci_dump_packet( HCI_SCO_DATA_PACKET, 0, packet, size);
650543e835cSMatthias Ringwald     int err = hci_stack->hci_transport->send_packet(HCI_SCO_DATA_PACKET, packet, size);
651543e835cSMatthias Ringwald 
652543e835cSMatthias Ringwald     if (hci_transport_synchronous()){
653543e835cSMatthias Ringwald         hci_release_packet_buffer();
65463fa3374SMatthias Ringwald         // notify upper stack that it might be possible to send again
65563fa3374SMatthias Ringwald         uint8_t event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
656d6b06661SMatthias Ringwald         hci_emit_event(&event[0], sizeof(event), 0);    // don't dump
657543e835cSMatthias Ringwald     }
658543e835cSMatthias Ringwald 
659543e835cSMatthias Ringwald     return err;
66044d0e3d5S[email protected] }
66135454696SMatthias Ringwald #endif
66244d0e3d5S[email protected] 
66316833f0aSmatthias.ringwald static void acl_handler(uint8_t *packet, int size){
6647856c818Smatthias.ringwald 
665e76a89eeS[email protected]     // log_info("acl_handler: size %u", size);
666e76a89eeS[email protected] 
6677856c818Smatthias.ringwald     // get info
6687856c818Smatthias.ringwald     hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(packet);
6695061f3afS[email protected]     hci_connection_t *conn      = hci_connection_for_handle(con_handle);
6707856c818Smatthias.ringwald     uint8_t  acl_flags          = READ_ACL_FLAGS(packet);
6717856c818Smatthias.ringwald     uint16_t acl_length         = READ_ACL_LENGTH(packet);
6727856c818Smatthias.ringwald 
6737856c818Smatthias.ringwald     // ignore non-registered handle
6747856c818Smatthias.ringwald     if (!conn){
6759da54300S[email protected]         log_error( "hci.c: acl_handler called with non-registered handle %u!" , con_handle);
6767856c818Smatthias.ringwald         return;
6777856c818Smatthias.ringwald     }
6787856c818Smatthias.ringwald 
679e76a89eeS[email protected]     // assert packet is complete
6809ecc3e17S[email protected]     if (acl_length + 4 != size){
681f04a0c31SMatthias Ringwald         log_error("hci.c: acl_handler called with ACL packet of wrong size %d, expected %u => dropping packet", size, acl_length + 4);
682e76a89eeS[email protected]         return;
683e76a89eeS[email protected]     }
684e76a89eeS[email protected] 
68552db98b2SMatthias Ringwald #ifdef ENABLE_CLASSIC
6867856c818Smatthias.ringwald     // update idle timestamp
6877856c818Smatthias.ringwald     hci_connection_timestamp(conn);
68852db98b2SMatthias Ringwald #endif
6897856c818Smatthias.ringwald 
6907856c818Smatthias.ringwald     // handle different packet types
6917856c818Smatthias.ringwald     switch (acl_flags & 0x03) {
6927856c818Smatthias.ringwald 
6937856c818Smatthias.ringwald         case 0x01: // continuation fragment
6947856c818Smatthias.ringwald 
6950ca847afS[email protected]             // sanity checks
6967856c818Smatthias.ringwald             if (conn->acl_recombination_pos == 0) {
6979da54300S[email protected]                 log_error( "ACL Cont Fragment but no first fragment for handle 0x%02x", con_handle);
6987856c818Smatthias.ringwald                 return;
6997856c818Smatthias.ringwald             }
7000ca847afS[email protected]             if (conn->acl_recombination_pos + acl_length > 4 + HCI_ACL_BUFFER_SIZE){
7010ca847afS[email protected]                 log_error( "ACL Cont Fragment to large: combined packet %u > buffer size %u for handle 0x%02x",
7020ca847afS[email protected]                     conn->acl_recombination_pos + acl_length, 4 + HCI_ACL_BUFFER_SIZE, con_handle);
7030ca847afS[email protected]                 conn->acl_recombination_pos = 0;
7040ca847afS[email protected]                 return;
7050ca847afS[email protected]             }
7067856c818Smatthias.ringwald 
7077856c818Smatthias.ringwald             // append fragment payload (header already stored)
708ec6321eeS[email protected]             memcpy(&conn->acl_recombination_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + conn->acl_recombination_pos], &packet[4], acl_length );
7097856c818Smatthias.ringwald             conn->acl_recombination_pos += acl_length;
7107856c818Smatthias.ringwald 
7119da54300S[email protected]             // log_error( "ACL Cont Fragment: acl_len %u, combined_len %u, l2cap_len %u", acl_length,
712decc01a8Smatthias.ringwald             //        conn->acl_recombination_pos, conn->acl_recombination_length);
7137856c818Smatthias.ringwald 
7147856c818Smatthias.ringwald             // forward complete L2CAP packet if complete.
7157856c818Smatthias.ringwald             if (conn->acl_recombination_pos >= conn->acl_recombination_length + 4 + 4){ // pos already incl. ACL header
716d6b06661SMatthias Ringwald                 hci_emit_acl_packet(&conn->acl_recombination_buffer[HCI_INCOMING_PRE_BUFFER_SIZE], conn->acl_recombination_pos);
7177856c818Smatthias.ringwald                 // reset recombination buffer
7187856c818Smatthias.ringwald                 conn->acl_recombination_length = 0;
7197856c818Smatthias.ringwald                 conn->acl_recombination_pos = 0;
7207856c818Smatthias.ringwald             }
7217856c818Smatthias.ringwald             break;
7227856c818Smatthias.ringwald 
7237856c818Smatthias.ringwald         case 0x02: { // first fragment
7247856c818Smatthias.ringwald 
72523a77e1aS[email protected]             // sanity check
72623a77e1aS[email protected]             if (conn->acl_recombination_pos) {
72723a77e1aS[email protected]                 log_error( "ACL First Fragment but data in buffer for handle 0x%02x, dropping stale fragments", con_handle);
72823a77e1aS[email protected]                 conn->acl_recombination_pos = 0;
72923a77e1aS[email protected]             }
73023a77e1aS[email protected] 
7317856c818Smatthias.ringwald             // peek into L2CAP packet!
7327856c818Smatthias.ringwald             uint16_t l2cap_length = READ_L2CAP_LENGTH( packet );
7337856c818Smatthias.ringwald 
7349da54300S[email protected]             // log_info( "ACL First Fragment: acl_len %u, l2cap_len %u", acl_length, l2cap_length);
735decc01a8Smatthias.ringwald 
7367856c818Smatthias.ringwald             // compare fragment size to L2CAP packet size
7377856c818Smatthias.ringwald             if (acl_length >= l2cap_length + 4){
7387856c818Smatthias.ringwald                 // forward fragment as L2CAP packet
739d6b06661SMatthias Ringwald                 hci_emit_acl_packet(packet, acl_length + 4);
7407856c818Smatthias.ringwald             } else {
7410ca847afS[email protected] 
7420ca847afS[email protected]                 if (acl_length > HCI_ACL_BUFFER_SIZE){
7430ca847afS[email protected]                     log_error( "ACL First Fragment to large: fragment %u > buffer size %u for handle 0x%02x",
7440ca847afS[email protected]                         4 + acl_length, 4 + HCI_ACL_BUFFER_SIZE, con_handle);
7450ca847afS[email protected]                     return;
7460ca847afS[email protected]                 }
7470ca847afS[email protected] 
7487856c818Smatthias.ringwald                 // store first fragment and tweak acl length for complete package
749ec6321eeS[email protected]                 memcpy(&conn->acl_recombination_buffer[HCI_INCOMING_PRE_BUFFER_SIZE], packet, acl_length + 4);
7507856c818Smatthias.ringwald                 conn->acl_recombination_pos    = acl_length + 4;
7517856c818Smatthias.ringwald                 conn->acl_recombination_length = l2cap_length;
752f8fbdce0SMatthias Ringwald                 little_endian_store_16(conn->acl_recombination_buffer, HCI_INCOMING_PRE_BUFFER_SIZE + 2, l2cap_length +4);
7537856c818Smatthias.ringwald             }
7547856c818Smatthias.ringwald             break;
7557856c818Smatthias.ringwald 
7567856c818Smatthias.ringwald         }
7577856c818Smatthias.ringwald         default:
7589da54300S[email protected]             log_error( "hci.c: acl_handler called with invalid packet boundary flags %u", acl_flags & 0x03);
7597856c818Smatthias.ringwald             return;
7607856c818Smatthias.ringwald     }
76194ab26f8Smatthias.ringwald 
76294ab26f8Smatthias.ringwald     // execute main loop
76394ab26f8Smatthias.ringwald     hci_run();
76416833f0aSmatthias.ringwald }
76522909952Smatthias.ringwald 
76667a3e8ecSmatthias.ringwald static void hci_shutdown_connection(hci_connection_t *conn){
7679da54300S[email protected]     log_info("Connection closed: handle 0x%x, %s", conn->con_handle, bd_addr_to_str(conn->address));
7683c4d4b90Smatthias.ringwald 
769ee752bb8SMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
770ee752bb8SMatthias Ringwald     int addr_type = conn->address_type;
771ee752bb8SMatthias Ringwald #endif
772ee752bb8SMatthias Ringwald 
773528a4a3bSMatthias Ringwald     btstack_run_loop_remove_timer(&conn->timeout);
774c785ef68Smatthias.ringwald 
775665d90f2SMatthias Ringwald     btstack_linked_list_remove(&hci_stack->connections, (btstack_linked_item_t *) conn);
776a3b02b71Smatthias.ringwald     btstack_memory_hci_connection_free( conn );
7773c4d4b90Smatthias.ringwald 
7783c4d4b90Smatthias.ringwald     // now it's gone
779c7e0c5f6Smatthias.ringwald     hci_emit_nr_connections_changed();
780ee752bb8SMatthias Ringwald 
781034e9b53SMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
782ee752bb8SMatthias Ringwald     // update SCO
783ee752bb8SMatthias Ringwald     if (addr_type == BD_ADDR_TYPE_SCO && hci_stack->hci_transport && hci_stack->hci_transport->set_sco_config){
784ee752bb8SMatthias Ringwald         hci_stack->hci_transport->set_sco_config(hci_stack->sco_voice_setting_active, hci_number_sco_connections());
785ee752bb8SMatthias Ringwald     }
786034e9b53SMatthias Ringwald #endif
787c7e0c5f6Smatthias.ringwald }
788c7e0c5f6Smatthias.ringwald 
78935454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
79035454696SMatthias Ringwald 
7910c042179S[email protected] static const uint16_t packet_type_sizes[] = {
7928f8108aaSmatthias.ringwald     0, HCI_ACL_2DH1_SIZE, HCI_ACL_3DH1_SIZE, HCI_ACL_DM1_SIZE,
7938f8108aaSmatthias.ringwald     HCI_ACL_DH1_SIZE, 0, 0, 0,
7948f8108aaSmatthias.ringwald     HCI_ACL_2DH3_SIZE, HCI_ACL_3DH3_SIZE, HCI_ACL_DM3_SIZE, HCI_ACL_DH3_SIZE,
7958f8108aaSmatthias.ringwald     HCI_ACL_2DH5_SIZE, HCI_ACL_3DH5_SIZE, HCI_ACL_DM5_SIZE, HCI_ACL_DH5_SIZE
7968f8108aaSmatthias.ringwald };
79765389bfcS[email protected] static const uint8_t  packet_type_feature_requirement_bit[] = {
79865389bfcS[email protected]      0, // 3 slot packets
79965389bfcS[email protected]      1, // 5 slot packets
80065389bfcS[email protected]     25, // EDR 2 mpbs
80165389bfcS[email protected]     26, // EDR 3 mbps
80265389bfcS[email protected]     39, // 3 slot EDR packts
80365389bfcS[email protected]     40, // 5 slot EDR packet
80465389bfcS[email protected] };
80565389bfcS[email protected] static const uint16_t packet_type_feature_packet_mask[] = {
80665389bfcS[email protected]     0x0f00, // 3 slot packets
80765389bfcS[email protected]     0xf000, // 5 slot packets
80865389bfcS[email protected]     0x1102, // EDR 2 mpbs
80965389bfcS[email protected]     0x2204, // EDR 3 mbps
81065389bfcS[email protected]     0x0300, // 3 slot EDR packts
81165389bfcS[email protected]     0x3000, // 5 slot EDR packet
81265389bfcS[email protected] };
8138f8108aaSmatthias.ringwald 
81465389bfcS[email protected] static uint16_t hci_acl_packet_types_for_buffer_size_and_local_features(uint16_t buffer_size, uint8_t * local_supported_features){
81565389bfcS[email protected]     // enable packet types based on size
8168f8108aaSmatthias.ringwald     uint16_t packet_types = 0;
817f16a69bbS[email protected]     unsigned int i;
8188f8108aaSmatthias.ringwald     for (i=0;i<16;i++){
8198f8108aaSmatthias.ringwald         if (packet_type_sizes[i] == 0) continue;
8208f8108aaSmatthias.ringwald         if (packet_type_sizes[i] <= buffer_size){
8218f8108aaSmatthias.ringwald             packet_types |= 1 << i;
8228f8108aaSmatthias.ringwald         }
8238f8108aaSmatthias.ringwald     }
82465389bfcS[email protected]     // disable packet types due to missing local supported features
82565389bfcS[email protected]     for (i=0;i<sizeof(packet_type_feature_requirement_bit);i++){
826f04a0c31SMatthias Ringwald         unsigned int bit_idx = packet_type_feature_requirement_bit[i];
82765389bfcS[email protected]         int feature_set = (local_supported_features[bit_idx >> 3] & (1<<(bit_idx & 7))) != 0;
82865389bfcS[email protected]         if (feature_set) continue;
82965389bfcS[email protected]         log_info("Features bit %02u is not set, removing packet types 0x%04x", bit_idx, packet_type_feature_packet_mask[i]);
83065389bfcS[email protected]         packet_types &= ~packet_type_feature_packet_mask[i];
83165389bfcS[email protected]     }
8328f8108aaSmatthias.ringwald     // flip bits for "may not be used"
8338f8108aaSmatthias.ringwald     packet_types ^= 0x3306;
8348f8108aaSmatthias.ringwald     return packet_types;
8358f8108aaSmatthias.ringwald }
8368f8108aaSmatthias.ringwald 
8378f8108aaSmatthias.ringwald uint16_t hci_usable_acl_packet_types(void){
8383a9fb326S[email protected]     return hci_stack->packet_types;
8398f8108aaSmatthias.ringwald }
84035454696SMatthias Ringwald #endif
8418f8108aaSmatthias.ringwald 
842facf93fdS[email protected] uint8_t* hci_get_outgoing_packet_buffer(void){
8437dc17943Smatthias.ringwald     // hci packet buffer is >= acl data packet length
8443a9fb326S[email protected]     return hci_stack->hci_packet_buffer;
8457dc17943Smatthias.ringwald }
8467dc17943Smatthias.ringwald 
847f5d8d141S[email protected] uint16_t hci_max_acl_data_packet_length(void){
8483a9fb326S[email protected]     return hci_stack->acl_data_packet_length;
8497dc17943Smatthias.ringwald }
8507dc17943Smatthias.ringwald 
85106b9e820SMatthias Ringwald #ifdef ENABLE_CLASSIC
8523e68d23dSMatthias Ringwald int hci_extended_sco_link_supported(void){
8533e68d23dSMatthias Ringwald     // No. 31, byte 3, bit 7
8543e68d23dSMatthias Ringwald     return (hci_stack->local_supported_features[3] & (1 << 7)) != 0;
8553e68d23dSMatthias Ringwald }
85606b9e820SMatthias Ringwald #endif
8573e68d23dSMatthias Ringwald 
8586ac9a97eS[email protected] int hci_non_flushable_packet_boundary_flag_supported(void){
8596ac9a97eS[email protected]     // No. 54, byte 6, bit 6
8606ac9a97eS[email protected]     return (hci_stack->local_supported_features[6] & (1 << 6)) != 0;
8616ac9a97eS[email protected] }
8626ac9a97eS[email protected] 
86315a95bd5SMatthias Ringwald static int gap_ssp_supported(void){
8646ac9a97eS[email protected]     // No. 51, byte 6, bit 3
8653a9fb326S[email protected]     return (hci_stack->local_supported_features[6] & (1 << 3)) != 0;
866f5d8d141S[email protected] }
867f5d8d141S[email protected] 
8687f02f414SMatthias Ringwald static int hci_classic_supported(void){
86935454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
8706ac9a97eS[email protected]     // No. 37, byte 4, bit 5, = No BR/EDR Support
8713a9fb326S[email protected]     return (hci_stack->local_supported_features[4] & (1 << 5)) == 0;
87235454696SMatthias Ringwald #else
87335454696SMatthias Ringwald     return 0;
87435454696SMatthias Ringwald #endif
875f5d8d141S[email protected] }
876f5d8d141S[email protected] 
8777f02f414SMatthias Ringwald static int hci_le_supported(void){
878a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
8796ac9a97eS[email protected]     // No. 37, byte 4, bit 6 = LE Supported (Controller)
8803a9fb326S[email protected]     return (hci_stack->local_supported_features[4] & (1 << 6)) != 0;
881f5d8d141S[email protected] #else
882f5d8d141S[email protected]     return 0;
883f5d8d141S[email protected] #endif
884f5d8d141S[email protected] }
885f5d8d141S[email protected] 
886b95a5a35SMatthias Ringwald #ifdef ENABLE_BLE
887b95a5a35SMatthias Ringwald 
888b95a5a35SMatthias Ringwald /**
889b95a5a35SMatthias Ringwald  * @brief Get addr type and address used for LE in Advertisements, Scan Responses,
890b95a5a35SMatthias Ringwald  */
891b95a5a35SMatthias Ringwald void gap_le_get_own_address(uint8_t * addr_type, bd_addr_t addr){
892b95a5a35SMatthias Ringwald     *addr_type = hci_stack->le_own_addr_type;
893b95a5a35SMatthias Ringwald     if (hci_stack->le_own_addr_type){
894b95a5a35SMatthias Ringwald         memcpy(addr, hci_stack->le_random_address, 6);
89569a97523S[email protected]     } else {
8963a9fb326S[email protected]         memcpy(addr, hci_stack->local_bd_addr, 6);
89769a97523S[email protected]     }
89869a97523S[email protected] }
89969a97523S[email protected] 
900e8c8828eSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
90139677e66SMatthias Ringwald void le_handle_advertisement_report(uint8_t *packet, int size){
9029ec2630cSMatthias Ringwald 
9039ec2630cSMatthias Ringwald     UNUSED(size);
9049ec2630cSMatthias Ringwald 
905d1dc057bS[email protected]     int offset = 3;
906d1dc057bS[email protected]     int num_reports = packet[offset];
907d1dc057bS[email protected]     offset += 1;
908d1dc057bS[email protected] 
90957c9da5bS[email protected]     int i;
9104f4e0224SMatthias Ringwald     // log_info("HCI: handle adv report with num reports: %d", num_reports);
91103fbe9c6S[email protected]     uint8_t event[12 + LE_ADVERTISING_DATA_SIZE]; // use upper bound to avoid var size automatic var
91257c9da5bS[email protected]     for (i=0; i<num_reports;i++){
913210c6774S[email protected]         uint8_t data_length = packet[offset + 8];
914a0aac9c4S[email protected]         uint8_t event_size = 10 + data_length;
915d1dc057bS[email protected]         int pos = 0;
916045013feSMatthias Ringwald         event[pos++] = GAP_EVENT_ADVERTISING_REPORT;
91757c9da5bS[email protected]         event[pos++] = event_size;
918210c6774S[email protected]         memcpy(&event[pos], &packet[offset], 1+1+6); // event type + address type + address
919d1dc057bS[email protected]         offset += 8;
920d1dc057bS[email protected]         pos += 8;
921d1dc057bS[email protected]         event[pos++] = packet[offset + 1 + data_length]; // rssi
922d1dc057bS[email protected]         event[pos++] = packet[offset++]; //data_length;
923d1dc057bS[email protected]         memcpy(&event[pos], &packet[offset], data_length);
92457c9da5bS[email protected]         pos += data_length;
925d1dc057bS[email protected]         offset += data_length + 1; // rssi
926d6b06661SMatthias Ringwald         hci_emit_event(event, pos, 1);
92757c9da5bS[email protected]     }
92857c9da5bS[email protected] }
929b2f949feS[email protected] #endif
930e8c8828eSMatthias Ringwald #endif
93157c9da5bS[email protected] 
932cd77dd38SMatthias Ringwald #if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
93306b9e820SMatthias Ringwald 
93496b53536SMatthias Ringwald static uint32_t hci_transport_uart_get_main_baud_rate(void){
93596b53536SMatthias Ringwald     if (!hci_stack->config) return 0;
9369796ebeaSMatthias Ringwald     uint32_t baud_rate = ((hci_transport_config_uart_t *)hci_stack->config)->baudrate_main;
93796b53536SMatthias Ringwald     // Limit baud rate for Broadcom chipsets to 3 mbps
938*61f37892SMatthias Ringwald     if (hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION && baud_rate > 3000000){
93996b53536SMatthias Ringwald         baud_rate = 3000000;
94096b53536SMatthias Ringwald     }
94196b53536SMatthias Ringwald     return baud_rate;
94296b53536SMatthias Ringwald }
94396b53536SMatthias Ringwald 
944ec820d77SMatthias Ringwald static void hci_initialization_timeout_handler(btstack_timer_source_t * ds){
9459ec2630cSMatthias Ringwald     UNUSED(ds);
9469ec2630cSMatthias Ringwald 
9470305bdeaSMatthias Ringwald     switch (hci_stack->substate){
9480305bdeaSMatthias Ringwald         case HCI_INIT_W4_SEND_RESET:
9497b0d7667SMatthias Ringwald             log_info("Resend HCI Reset");
9500305bdeaSMatthias Ringwald             hci_stack->substate = HCI_INIT_SEND_RESET;
9517b0d7667SMatthias Ringwald             hci_stack->num_cmd_packets = 1;
9520305bdeaSMatthias Ringwald             hci_run();
9530305bdeaSMatthias Ringwald             break;
9549f007422SMatthias Ringwald         case HCI_INIT_W4_CUSTOM_INIT_CSR_WARM_BOOT_LINK_RESET:
9559f007422SMatthias Ringwald             log_info("Resend HCI Reset - CSR Warm Boot with Link Reset");
9569f007422SMatthias Ringwald             if (hci_stack->hci_transport->reset_link){
9579f007422SMatthias Ringwald                 hci_stack->hci_transport->reset_link();
9589f007422SMatthias Ringwald             }
959202c8a4cSMatthias Ringwald             // no break - explicit fallthrough to HCI_INIT_W4_CUSTOM_INIT_CSR_WARM_BOOT
960e47e68c7SMatthias Ringwald         case HCI_INIT_W4_CUSTOM_INIT_CSR_WARM_BOOT:
961e47e68c7SMatthias Ringwald             log_info("Resend HCI Reset - CSR Warm Boot");
962e47e68c7SMatthias Ringwald             hci_stack->substate = HCI_INIT_SEND_RESET_CSR_WARM_BOOT;
963e47e68c7SMatthias Ringwald             hci_stack->num_cmd_packets = 1;
964e47e68c7SMatthias Ringwald             hci_run();
965688c2635SMatthias Ringwald             break;
9667224be7eSMatthias Ringwald         case HCI_INIT_W4_SEND_BAUD_CHANGE:
9677224be7eSMatthias Ringwald             if (hci_stack->hci_transport->set_baudrate){
96896b53536SMatthias Ringwald                 uint32_t baud_rate = hci_transport_uart_get_main_baud_rate();
969cd724cb7SMatthias Ringwald                 log_info("Local baud rate change to %"PRIu32"(timeout handler)", baud_rate);
9707dd9d0ecSMatthias Ringwald                 hci_stack->hci_transport->set_baudrate(baud_rate);
9717224be7eSMatthias Ringwald             }
972772a36d3SMatthias Ringwald             // For CSR, HCI Reset is sent on new baud rate
973*61f37892SMatthias Ringwald             if (hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO){
974772a36d3SMatthias Ringwald                 hci_stack->substate = HCI_INIT_SEND_RESET_CSR_WARM_BOOT;
975772a36d3SMatthias Ringwald                 hci_run();
976772a36d3SMatthias Ringwald             }
9774696bddbSMatthias Ringwald             break;
978559961d0SMatthias Ringwald         case HCI_INIT_W4_CUSTOM_INIT_BCM_DELAY:
979559961d0SMatthias Ringwald             // otherwise continue
980559961d0SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS;
981559961d0SMatthias Ringwald             hci_send_cmd(&hci_read_local_supported_commands);
982559961d0SMatthias Ringwald             break;
9830305bdeaSMatthias Ringwald         default:
9840305bdeaSMatthias Ringwald             break;
9850305bdeaSMatthias Ringwald     }
9860305bdeaSMatthias Ringwald }
98706b9e820SMatthias Ringwald #endif
9880305bdeaSMatthias Ringwald 
98971de195eSMatthias Ringwald static void hci_initializing_next_state(void){
99074b323a9SMatthias Ringwald     hci_stack->substate = (hci_substate_t )( ((int) hci_stack->substate) + 1);
99174b323a9SMatthias Ringwald }
99274b323a9SMatthias Ringwald 
99374b323a9SMatthias Ringwald // assumption: hci_can_send_command_packet_now() == true
99471de195eSMatthias Ringwald static void hci_initializing_run(void){
995148ca237SMatthias Ringwald     log_debug("hci_initializing_run: substate %u, can send %u", hci_stack->substate, hci_can_send_command_packet_now());
99674b323a9SMatthias Ringwald     switch (hci_stack->substate){
99774b323a9SMatthias Ringwald         case HCI_INIT_SEND_RESET:
99874b323a9SMatthias Ringwald             hci_state_reset();
999a0cf2f3fSMatthias Ringwald 
100006b9e820SMatthias Ringwald #if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
10010305bdeaSMatthias Ringwald             // prepare reset if command complete not received in 100ms
1002659d758cSMatthias Ringwald             btstack_run_loop_set_timer(&hci_stack->timeout, HCI_RESET_RESEND_TIMEOUT_MS);
1003528a4a3bSMatthias Ringwald             btstack_run_loop_set_timer_handler(&hci_stack->timeout, hci_initialization_timeout_handler);
1004528a4a3bSMatthias Ringwald             btstack_run_loop_add_timer(&hci_stack->timeout);
1005a0cf2f3fSMatthias Ringwald #endif
10060305bdeaSMatthias Ringwald             // send command
100774b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_SEND_RESET;
10080305bdeaSMatthias Ringwald             hci_send_cmd(&hci_reset);
100974b323a9SMatthias Ringwald             break;
101076fcb19bSMatthias Ringwald         case HCI_INIT_SEND_READ_LOCAL_VERSION_INFORMATION:
101176fcb19bSMatthias Ringwald             hci_send_cmd(&hci_read_local_version_information);
101276fcb19bSMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_SEND_READ_LOCAL_VERSION_INFORMATION;
101376fcb19bSMatthias Ringwald             break;
1014e90bae01SMatthias Ringwald         case HCI_INIT_SEND_READ_LOCAL_NAME:
1015e90bae01SMatthias Ringwald             hci_send_cmd(&hci_read_local_name);
1016e90bae01SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_SEND_READ_LOCAL_NAME;
1017e90bae01SMatthias Ringwald             break;
101806b9e820SMatthias Ringwald 
101906b9e820SMatthias Ringwald #if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
1020e47e68c7SMatthias Ringwald         case HCI_INIT_SEND_RESET_CSR_WARM_BOOT:
1021e47e68c7SMatthias Ringwald             hci_state_reset();
1022e47e68c7SMatthias Ringwald             // prepare reset if command complete not received in 100ms
1023659d758cSMatthias Ringwald             btstack_run_loop_set_timer(&hci_stack->timeout, HCI_RESET_RESEND_TIMEOUT_MS);
1024528a4a3bSMatthias Ringwald             btstack_run_loop_set_timer_handler(&hci_stack->timeout, hci_initialization_timeout_handler);
1025528a4a3bSMatthias Ringwald             btstack_run_loop_add_timer(&hci_stack->timeout);
1026e47e68c7SMatthias Ringwald             // send command
1027e47e68c7SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_CUSTOM_INIT_CSR_WARM_BOOT;
1028e47e68c7SMatthias Ringwald             hci_send_cmd(&hci_reset);
1029e47e68c7SMatthias Ringwald             break;
10308d29070eSMatthias Ringwald         case HCI_INIT_SEND_RESET_ST_WARM_BOOT:
10318d29070eSMatthias Ringwald             hci_state_reset();
10328d29070eSMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_SEND_RESET_ST_WARM_BOOT;
10338d29070eSMatthias Ringwald             hci_send_cmd(&hci_reset);
10348d29070eSMatthias Ringwald             break;
1035fab26ab3SMatthias Ringwald         case HCI_INIT_SEND_BAUD_CHANGE: {
103696b53536SMatthias Ringwald             uint32_t baud_rate = hci_transport_uart_get_main_baud_rate();
10373fb36a29SMatthias Ringwald             hci_stack->chipset->set_baudrate_command(baud_rate, hci_stack->hci_packet_buffer);
1038f8fbdce0SMatthias Ringwald             hci_stack->last_cmd_opcode = little_endian_read_16(hci_stack->hci_packet_buffer, 0);
103974b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_SEND_BAUD_CHANGE;
10400305bdeaSMatthias Ringwald             hci_send_cmd_packet(hci_stack->hci_packet_buffer, 3 + hci_stack->hci_packet_buffer[2]);
10414696bddbSMatthias Ringwald             // STLC25000D: baudrate change happens within 0.5 s after command was send,
10424696bddbSMatthias Ringwald             // use timer to update baud rate after 100 ms (knowing exactly, when command was sent is non-trivial)
1043*61f37892SMatthias Ringwald             if (hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS){
1044659d758cSMatthias Ringwald                 btstack_run_loop_set_timer(&hci_stack->timeout, HCI_RESET_RESEND_TIMEOUT_MS);
1045528a4a3bSMatthias Ringwald                 btstack_run_loop_add_timer(&hci_stack->timeout);
10464696bddbSMatthias Ringwald             }
104774b323a9SMatthias Ringwald             break;
1048fab26ab3SMatthias Ringwald         }
1049fab26ab3SMatthias Ringwald         case HCI_INIT_SEND_BAUD_CHANGE_BCM: {
105096b53536SMatthias Ringwald             uint32_t baud_rate = hci_transport_uart_get_main_baud_rate();
10513fb36a29SMatthias Ringwald             hci_stack->chipset->set_baudrate_command(baud_rate, hci_stack->hci_packet_buffer);
1052f8fbdce0SMatthias Ringwald             hci_stack->last_cmd_opcode = little_endian_read_16(hci_stack->hci_packet_buffer, 0);
1053eb3a5314SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_SEND_BAUD_CHANGE_BCM;
1054eb3a5314SMatthias Ringwald             hci_send_cmd_packet(hci_stack->hci_packet_buffer, 3 + hci_stack->hci_packet_buffer[2]);
1055eb3a5314SMatthias Ringwald             break;
1056fab26ab3SMatthias Ringwald         }
105774b323a9SMatthias Ringwald         case HCI_INIT_CUSTOM_INIT:
105874b323a9SMatthias Ringwald             // Custom initialization
10593fb36a29SMatthias Ringwald             if (hci_stack->chipset && hci_stack->chipset->next_command){
10603fb36a29SMatthias Ringwald                 int valid_cmd = (*hci_stack->chipset->next_command)(hci_stack->hci_packet_buffer);
106174b323a9SMatthias Ringwald                 if (valid_cmd){
106274b323a9SMatthias Ringwald                     int size = 3 + hci_stack->hci_packet_buffer[2];
1063f8fbdce0SMatthias Ringwald                     hci_stack->last_cmd_opcode = little_endian_read_16(hci_stack->hci_packet_buffer, 0);
106474b323a9SMatthias Ringwald                     hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, hci_stack->hci_packet_buffer, size);
1065e47e68c7SMatthias Ringwald                     switch (valid_cmd) {
1066e47e68c7SMatthias Ringwald                         case 1:
1067e47e68c7SMatthias Ringwald                         default:
1068e47e68c7SMatthias Ringwald                             hci_stack->substate = HCI_INIT_W4_CUSTOM_INIT;
1069e47e68c7SMatthias Ringwald                             break;
1070e47e68c7SMatthias Ringwald                         case 2: // CSR Warm Boot: Wait a bit, then send HCI Reset until HCI Command Complete
1071e47e68c7SMatthias Ringwald                             log_info("CSR Warm Boot");
1072659d758cSMatthias Ringwald                             btstack_run_loop_set_timer(&hci_stack->timeout, HCI_RESET_RESEND_TIMEOUT_MS);
1073528a4a3bSMatthias Ringwald                             btstack_run_loop_set_timer_handler(&hci_stack->timeout, hci_initialization_timeout_handler);
1074528a4a3bSMatthias Ringwald                             btstack_run_loop_add_timer(&hci_stack->timeout);
1075*61f37892SMatthias Ringwald                             if (hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO
1076772a36d3SMatthias Ringwald                                 && hci_stack->config
10773fb36a29SMatthias Ringwald                                 && hci_stack->chipset
10783fb36a29SMatthias Ringwald                                 // && hci_stack->chipset->set_baudrate_command -- there's no such command
1079772a36d3SMatthias Ringwald                                 && hci_stack->hci_transport->set_baudrate
10802caefae9SMatthias Ringwald                                 && hci_transport_uart_get_main_baud_rate()){
1081772a36d3SMatthias Ringwald                                 hci_stack->substate = HCI_INIT_W4_SEND_BAUD_CHANGE;
1082772a36d3SMatthias Ringwald                             } else {
10839f007422SMatthias Ringwald                                hci_stack->substate = HCI_INIT_W4_CUSTOM_INIT_CSR_WARM_BOOT_LINK_RESET;
1084772a36d3SMatthias Ringwald                             }
1085e47e68c7SMatthias Ringwald                             break;
1086e47e68c7SMatthias Ringwald                     }
10870305bdeaSMatthias Ringwald                     hci_stack->hci_transport->send_packet(HCI_COMMAND_DATA_PACKET, hci_stack->hci_packet_buffer, size);
108874b323a9SMatthias Ringwald                     break;
108974b323a9SMatthias Ringwald                 }
1090148ca237SMatthias Ringwald                 log_info("Init script done");
109192a0d36dSMatthias Ringwald 
1092559961d0SMatthias Ringwald                 // Init script download on Broadcom chipsets causes:
1093*61f37892SMatthias Ringwald                 if (hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION){
1094559961d0SMatthias Ringwald                     // - baud rate to reset, restore UART baud rate if needed
109592a0d36dSMatthias Ringwald                     int need_baud_change = hci_stack->config
10963fb36a29SMatthias Ringwald                         && hci_stack->chipset
10973fb36a29SMatthias Ringwald                         && hci_stack->chipset->set_baudrate_command
109892a0d36dSMatthias Ringwald                         && hci_stack->hci_transport->set_baudrate
10999796ebeaSMatthias Ringwald                         && ((hci_transport_config_uart_t *)hci_stack->config)->baudrate_main;
110092a0d36dSMatthias Ringwald                     if (need_baud_change) {
11019796ebeaSMatthias Ringwald                         uint32_t baud_rate = ((hci_transport_config_uart_t *)hci_stack->config)->baudrate_init;
1102cd724cb7SMatthias Ringwald                         log_info("Local baud rate change to %"PRIu32" after init script (bcm)", baud_rate);
110392a0d36dSMatthias Ringwald                         hci_stack->hci_transport->set_baudrate(baud_rate);
110492a0d36dSMatthias Ringwald                     }
1105559961d0SMatthias Ringwald 
1106559961d0SMatthias Ringwald                     // - RTS will raise during update, but manual RTS/CTS in WICED port on RedBear Duo cannot handle this
1107559961d0SMatthias Ringwald                     //   -> Work around: wait a few milliseconds here.
1108559961d0SMatthias Ringwald                     log_info("BCM delay after init script");
1109559961d0SMatthias Ringwald                     hci_stack->substate = HCI_INIT_W4_CUSTOM_INIT_BCM_DELAY;
1110559961d0SMatthias Ringwald                     btstack_run_loop_set_timer(&hci_stack->timeout, 10);
1111559961d0SMatthias Ringwald                     btstack_run_loop_set_timer_handler(&hci_stack->timeout, hci_initialization_timeout_handler);
1112559961d0SMatthias Ringwald                     btstack_run_loop_add_timer(&hci_stack->timeout);
1113559961d0SMatthias Ringwald                     break;
111492a0d36dSMatthias Ringwald                 }
111574b323a9SMatthias Ringwald                         }
111674b323a9SMatthias Ringwald             // otherwise continue
1117a828a756SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS;
1118a828a756SMatthias Ringwald             hci_send_cmd(&hci_read_local_supported_commands);
1119a828a756SMatthias Ringwald             break;
112053860077SMatthias Ringwald         case HCI_INIT_SET_BD_ADDR:
112153860077SMatthias Ringwald             log_info("Set Public BD ADDR to %s", bd_addr_to_str(hci_stack->custom_bd_addr));
11223fb36a29SMatthias Ringwald             hci_stack->chipset->set_bd_addr_command(hci_stack->custom_bd_addr, hci_stack->hci_packet_buffer);
1123f8fbdce0SMatthias Ringwald             hci_stack->last_cmd_opcode = little_endian_read_16(hci_stack->hci_packet_buffer, 0);
112453860077SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_SET_BD_ADDR;
112553860077SMatthias Ringwald             hci_send_cmd_packet(hci_stack->hci_packet_buffer, 3 + hci_stack->hci_packet_buffer[2]);
112653860077SMatthias Ringwald             break;
112706b9e820SMatthias Ringwald #endif
112806b9e820SMatthias Ringwald 
112906b9e820SMatthias Ringwald         case HCI_INIT_READ_LOCAL_SUPPORTED_COMMANDS:
113006b9e820SMatthias Ringwald             log_info("Resend hci_read_local_supported_commands after CSR Warm Boot double reset");
113106b9e820SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS;
113206b9e820SMatthias Ringwald             hci_send_cmd(&hci_read_local_supported_commands);
113306b9e820SMatthias Ringwald             break;
113453860077SMatthias Ringwald         case HCI_INIT_READ_BD_ADDR:
113553860077SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_READ_BD_ADDR;
113653860077SMatthias Ringwald             hci_send_cmd(&hci_read_bd_addr);
113753860077SMatthias Ringwald             break;
113874b323a9SMatthias Ringwald         case HCI_INIT_READ_BUFFER_SIZE:
113974b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_READ_BUFFER_SIZE;
11400305bdeaSMatthias Ringwald             hci_send_cmd(&hci_read_buffer_size);
114174b323a9SMatthias Ringwald             break;
114253860077SMatthias Ringwald         case HCI_INIT_READ_LOCAL_SUPPORTED_FEATURES:
114353860077SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_READ_LOCAL_SUPPORTED_FEATURES;
11440305bdeaSMatthias Ringwald             hci_send_cmd(&hci_read_local_supported_features);
114574b323a9SMatthias Ringwald             break;
114674b323a9SMatthias Ringwald         case HCI_INIT_SET_EVENT_MASK:
11470305bdeaSMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_SET_EVENT_MASK;
114874b323a9SMatthias Ringwald             if (hci_le_supported()){
114974b323a9SMatthias Ringwald                 hci_send_cmd(&hci_set_event_mask,0xffffffff, 0x3FFFFFFF);
115074b323a9SMatthias Ringwald             } else {
115174b323a9SMatthias Ringwald                 // Kensington Bluetooth 2.1 USB Dongle (CSR Chipset) returns an error for 0xffff...
115274b323a9SMatthias Ringwald                 hci_send_cmd(&hci_set_event_mask,0xffffffff, 0x1FFFFFFF);
115374b323a9SMatthias Ringwald             }
115474b323a9SMatthias Ringwald             break;
115535454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
115674b323a9SMatthias Ringwald         case HCI_INIT_WRITE_SIMPLE_PAIRING_MODE:
115774b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_SIMPLE_PAIRING_MODE;
11580305bdeaSMatthias Ringwald             hci_send_cmd(&hci_write_simple_pairing_mode, hci_stack->ssp_enable);
115974b323a9SMatthias Ringwald             break;
116074b323a9SMatthias Ringwald         case HCI_INIT_WRITE_PAGE_TIMEOUT:
116174b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_PAGE_TIMEOUT;
11620305bdeaSMatthias Ringwald             hci_send_cmd(&hci_write_page_timeout, 0x6000);  // ca. 15 sec
116374b323a9SMatthias Ringwald             break;
116474b323a9SMatthias Ringwald         case HCI_INIT_WRITE_CLASS_OF_DEVICE:
116574b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_CLASS_OF_DEVICE;
11660305bdeaSMatthias Ringwald             hci_send_cmd(&hci_write_class_of_device, hci_stack->class_of_device);
116774b323a9SMatthias Ringwald             break;
116874b323a9SMatthias Ringwald         case HCI_INIT_WRITE_LOCAL_NAME:
11690305bdeaSMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_LOCAL_NAME;
117074b323a9SMatthias Ringwald             if (hci_stack->local_name){
117174b323a9SMatthias Ringwald                 hci_send_cmd(&hci_write_local_name, hci_stack->local_name);
117274b323a9SMatthias Ringwald             } else {
11737224be7eSMatthias Ringwald                 char local_name[8+17+1];
11747224be7eSMatthias Ringwald                 // BTstack 11:22:33:44:55:66
11757224be7eSMatthias Ringwald                 memcpy(local_name, "BTstack ", 8);
11767224be7eSMatthias Ringwald                 memcpy(&local_name[8], bd_addr_to_str(hci_stack->local_bd_addr), 17);   // strlen(bd_addr_to_str(...)) = 17
11777224be7eSMatthias Ringwald                 local_name[8+17] = '\0';
117893bcd4d0SMatthias Ringwald                 log_info("---> Name %s", local_name);
117993bcd4d0SMatthias Ringwald                 hci_send_cmd(&hci_write_local_name, local_name);
118074b323a9SMatthias Ringwald             }
118174b323a9SMatthias Ringwald             break;
1182ff00ed1cSMatthias Ringwald         case HCI_INIT_WRITE_EIR_DATA:
11838a114470SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_EIR_DATA;
1184ff00ed1cSMatthias Ringwald             hci_send_cmd(&hci_write_extended_inquiry_response, 0, hci_stack->eir_data);
1185ff00ed1cSMatthias Ringwald             break;
1186f6858d14SMatthias Ringwald         case HCI_INIT_WRITE_INQUIRY_MODE:
1187f6858d14SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_INQUIRY_MODE;
11888a114470SMatthias Ringwald             hci_send_cmd(&hci_write_inquiry_mode, (int) hci_stack->inquiry_mode);
1189f6858d14SMatthias Ringwald             break;
119074b323a9SMatthias Ringwald         case HCI_INIT_WRITE_SCAN_ENABLE:
119174b323a9SMatthias Ringwald             hci_send_cmd(&hci_write_scan_enable, (hci_stack->connectable << 1) | hci_stack->discoverable); // page scan
119274b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_SCAN_ENABLE;
119374b323a9SMatthias Ringwald             break;
1194483c5078SMatthias Ringwald         // only sent if ENABLE_SCO_OVER_HCI is defined
1195729ed62eSMatthias Ringwald         case HCI_INIT_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE:
1196729ed62eSMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE;
1197729ed62eSMatthias Ringwald             hci_send_cmd(&hci_write_synchronous_flow_control_enable, 1); // SCO tracking enabled
1198729ed62eSMatthias Ringwald             break;
1199483c5078SMatthias Ringwald         case HCI_INIT_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING:
1200483c5078SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING;
1201483c5078SMatthias Ringwald             hci_send_cmd(&hci_write_default_erroneous_data_reporting, 1);
1202483c5078SMatthias Ringwald             break;
1203a42798c3SMatthias Ringwald         // only sent if ENABLE_SCO_OVER_HCI and manufacturer is Broadcom
1204a42798c3SMatthias Ringwald         case HCI_INIT_BCM_WRITE_SCO_PCM_INT:
1205a42798c3SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_BCM_WRITE_SCO_PCM_INT;
1206a42798c3SMatthias Ringwald             log_info("BCM: Route SCO data via HCI transport");
1207a42798c3SMatthias Ringwald             hci_send_cmd(&hci_bcm_write_sco_pcm_int, 1, 0, 0, 0, 0);
1208a42798c3SMatthias Ringwald             break;
1209a42798c3SMatthias Ringwald 
121035454696SMatthias Ringwald #endif
1211a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
121274b323a9SMatthias Ringwald         // LE INIT
121374b323a9SMatthias Ringwald         case HCI_INIT_LE_READ_BUFFER_SIZE:
121474b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_LE_READ_BUFFER_SIZE;
12150305bdeaSMatthias Ringwald             hci_send_cmd(&hci_le_read_buffer_size);
121674b323a9SMatthias Ringwald             break;
121774b323a9SMatthias Ringwald         case HCI_INIT_WRITE_LE_HOST_SUPPORTED:
121874b323a9SMatthias Ringwald             // LE Supported Host = 1, Simultaneous Host = 0
121974b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_LE_HOST_SUPPORTED;
12200305bdeaSMatthias Ringwald             hci_send_cmd(&hci_write_le_host_supported, 1, 0);
122174b323a9SMatthias Ringwald             break;
1222b95a5a35SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
12233b6d4121SMatthias Ringwald         case HCI_INIT_READ_WHITE_LIST_SIZE:
12243b6d4121SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_READ_WHITE_LIST_SIZE;
12253b6d4121SMatthias Ringwald             hci_send_cmd(&hci_le_read_white_list_size);
12263b6d4121SMatthias Ringwald             break;
122774b323a9SMatthias Ringwald         case HCI_INIT_LE_SET_SCAN_PARAMETERS:
1228b95a5a35SMatthias Ringwald             // LE Scan Parameters: active scanning, 300 ms interval, 30 ms window, own address type, accept all advs
122974b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_LE_SET_SCAN_PARAMETERS;
1230b95a5a35SMatthias Ringwald             hci_send_cmd(&hci_le_set_scan_parameters, 1, 0x1e0, 0x30, hci_stack->le_own_addr_type, 0);
123174b323a9SMatthias Ringwald             break;
123274b323a9SMatthias Ringwald #endif
1233b95a5a35SMatthias Ringwald #endif
123474b323a9SMatthias Ringwald         default:
123574b323a9SMatthias Ringwald             return;
123674b323a9SMatthias Ringwald     }
123755975f88SMatthias Ringwald }
123855975f88SMatthias Ringwald 
1239a650ba4dSMatthias Ringwald static void hci_init_done(void){
1240a650ba4dSMatthias Ringwald     // done. tell the app
1241a650ba4dSMatthias Ringwald     log_info("hci_init_done -> HCI_STATE_WORKING");
1242a650ba4dSMatthias Ringwald     hci_stack->state = HCI_STATE_WORKING;
1243a650ba4dSMatthias Ringwald     hci_emit_state();
1244a650ba4dSMatthias Ringwald     hci_run();
1245a650ba4dSMatthias Ringwald }
1246a650ba4dSMatthias Ringwald 
12476155b3d3S[email protected] static void hci_initializing_event_handler(uint8_t * packet, uint16_t size){
12489ec2630cSMatthias Ringwald     UNUSED(size);
12499ec2630cSMatthias Ringwald 
1250a2481739S[email protected]     uint8_t command_completed = 0;
1251c4633093SMatthias Ringwald 
12520e2df43fSMatthias Ringwald     if (hci_event_packet_get_type(packet) == HCI_EVENT_COMMAND_COMPLETE){
1253f8fbdce0SMatthias Ringwald         uint16_t opcode = little_endian_read_16(packet,3);
12546155b3d3S[email protected]         if (opcode == hci_stack->last_cmd_opcode){
1255a2481739S[email protected]             command_completed = 1;
1256148ca237SMatthias Ringwald             log_debug("Command complete for expected opcode %04x at substate %u", opcode, hci_stack->substate);
12576155b3d3S[email protected]         } else {
1258d58dd308SMatthias Ringwald             log_info("Command complete for different opcode %04x, expected %04x, at substate %u", opcode, hci_stack->last_cmd_opcode, hci_stack->substate);
12596155b3d3S[email protected]         }
12606155b3d3S[email protected]     }
12610f97eae7SMatthias Ringwald 
12620e2df43fSMatthias Ringwald     if (hci_event_packet_get_type(packet) == HCI_EVENT_COMMAND_STATUS){
12636155b3d3S[email protected]         uint8_t  status = packet[2];
1264f8fbdce0SMatthias Ringwald         uint16_t opcode = little_endian_read_16(packet,4);
12656155b3d3S[email protected]         if (opcode == hci_stack->last_cmd_opcode){
12666155b3d3S[email protected]             if (status){
1267a2481739S[email protected]                 command_completed = 1;
1268148ca237SMatthias Ringwald                 log_debug("Command status error 0x%02x for expected opcode %04x at substate %u", status, opcode, hci_stack->substate);
12696155b3d3S[email protected]             } else {
12706155b3d3S[email protected]                 log_info("Command status OK for expected opcode %04x, waiting for command complete", opcode);
12716155b3d3S[email protected]             }
12726155b3d3S[email protected]         } else {
1273148ca237SMatthias Ringwald             log_debug("Command status for opcode %04x, expected %04x", opcode, hci_stack->last_cmd_opcode);
12746155b3d3S[email protected]         }
12756155b3d3S[email protected]     }
12760f97eae7SMatthias Ringwald 
127706b9e820SMatthias Ringwald #if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
127806b9e820SMatthias Ringwald 
1279e47e68c7SMatthias Ringwald     // Vendor == CSR
12800e2df43fSMatthias Ringwald     if (hci_stack->substate == HCI_INIT_W4_CUSTOM_INIT && hci_event_packet_get_type(packet) == HCI_EVENT_VENDOR_SPECIFIC){
1281e47e68c7SMatthias Ringwald         // TODO: track actual command
1282e47e68c7SMatthias Ringwald         command_completed = 1;
1283e47e68c7SMatthias Ringwald     }
1284a2481739S[email protected] 
12854e9daa6fSMatthias Ringwald     // Vendor == Toshiba
12860e2df43fSMatthias Ringwald     if (hci_stack->substate == HCI_INIT_W4_SEND_BAUD_CHANGE && hci_event_packet_get_type(packet) == HCI_EVENT_VENDOR_SPECIFIC){
12874e9daa6fSMatthias Ringwald         // TODO: track actual command
12884e9daa6fSMatthias Ringwald         command_completed = 1;
12894e9daa6fSMatthias Ringwald     }
12904e9daa6fSMatthias Ringwald 
12910f97eae7SMatthias Ringwald     // Late response (> 100 ms) for HCI Reset e.g. on Toshiba TC35661:
12920f97eae7SMatthias Ringwald     // Command complete for HCI Reset arrives after we've resent the HCI Reset command
12930f97eae7SMatthias Ringwald     //
12940f97eae7SMatthias Ringwald     // HCI Reset
12950f97eae7SMatthias Ringwald     // Timeout 100 ms
12960f97eae7SMatthias Ringwald     // HCI Reset
12970f97eae7SMatthias Ringwald     // Command Complete Reset
12980f97eae7SMatthias Ringwald     // HCI Read Local Version Information
12990f97eae7SMatthias Ringwald     // Command Complete Reset - but we expected Command Complete Read Local Version Information
13000f97eae7SMatthias Ringwald     // hang...
13010f97eae7SMatthias Ringwald     //
13020f97eae7SMatthias Ringwald     // Fix: Command Complete for HCI Reset in HCI_INIT_W4_SEND_READ_LOCAL_VERSION_INFORMATION trigger resend
13030f97eae7SMatthias Ringwald     if (!command_completed
13040e2df43fSMatthias Ringwald             && hci_event_packet_get_type(packet) == HCI_EVENT_COMMAND_COMPLETE
13050f97eae7SMatthias Ringwald             && hci_stack->substate == HCI_INIT_W4_SEND_READ_LOCAL_VERSION_INFORMATION){
13060f97eae7SMatthias Ringwald 
1307f8fbdce0SMatthias Ringwald         uint16_t opcode = little_endian_read_16(packet,3);
13080f97eae7SMatthias Ringwald         if (opcode == hci_reset.opcode){
13090f97eae7SMatthias Ringwald             hci_stack->substate = HCI_INIT_SEND_READ_LOCAL_VERSION_INFORMATION;
13100f97eae7SMatthias Ringwald             return;
13110f97eae7SMatthias Ringwald         }
13120f97eae7SMatthias Ringwald     }
13130f97eae7SMatthias Ringwald 
13149f007422SMatthias Ringwald     // CSR & H5
13159f007422SMatthias Ringwald     // Fix: Command Complete for HCI Reset in HCI_INIT_W4_SEND_READ_LOCAL_VERSION_INFORMATION trigger resend
13169f007422SMatthias Ringwald     if (!command_completed
13179f007422SMatthias Ringwald             && hci_event_packet_get_type(packet) == HCI_EVENT_COMMAND_COMPLETE
13189f007422SMatthias Ringwald             && hci_stack->substate == HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS){
13199f007422SMatthias Ringwald 
13209f007422SMatthias Ringwald         uint16_t opcode = little_endian_read_16(packet,3);
13219f007422SMatthias Ringwald         if (opcode == hci_reset.opcode){
13229f007422SMatthias Ringwald             hci_stack->substate = HCI_INIT_READ_LOCAL_SUPPORTED_COMMANDS;
13239f007422SMatthias Ringwald             return;
13249f007422SMatthias Ringwald         }
13259f007422SMatthias Ringwald     }
13269f007422SMatthias Ringwald 
13279f007422SMatthias Ringwald     // on CSR with BCSP/H5, the reset resend timeout leads to substate == HCI_INIT_SEND_RESET or HCI_INIT_SEND_RESET_CSR_WARM_BOOT
13289f007422SMatthias Ringwald     // fix: Correct substate and behave as command below
13299f007422SMatthias Ringwald     if (command_completed){
13309f007422SMatthias Ringwald         switch (hci_stack->substate){
13319f007422SMatthias Ringwald             case HCI_INIT_SEND_RESET:
13329f007422SMatthias Ringwald                 hci_stack->substate = HCI_INIT_W4_SEND_RESET;
13339f007422SMatthias Ringwald                 break;
13349f007422SMatthias Ringwald             case HCI_INIT_SEND_RESET_CSR_WARM_BOOT:
13359f007422SMatthias Ringwald                 hci_stack->substate = HCI_INIT_W4_CUSTOM_INIT_CSR_WARM_BOOT;
13369f007422SMatthias Ringwald                 break;
13379f007422SMatthias Ringwald             default:
13389f007422SMatthias Ringwald                 break;
13399f007422SMatthias Ringwald         }
13409f007422SMatthias Ringwald     }
13410f97eae7SMatthias Ringwald 
134206b9e820SMatthias Ringwald #endif
13430f97eae7SMatthias Ringwald 
1344a2481739S[email protected]     if (!command_completed) return;
1345a2481739S[email protected] 
134606b9e820SMatthias Ringwald     int need_baud_change = 0;
134706b9e820SMatthias Ringwald     int need_addr_change = 0;
134806b9e820SMatthias Ringwald 
134906b9e820SMatthias Ringwald #if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
135006b9e820SMatthias Ringwald     need_baud_change = hci_stack->config
13513fb36a29SMatthias Ringwald                         && hci_stack->chipset
13523fb36a29SMatthias Ringwald                         && hci_stack->chipset->set_baudrate_command
1353db8bc6ffSMatthias Ringwald                         && hci_stack->hci_transport->set_baudrate
13549796ebeaSMatthias Ringwald                         && ((hci_transport_config_uart_t *)hci_stack->config)->baudrate_main;
1355db8bc6ffSMatthias Ringwald 
135606b9e820SMatthias Ringwald     need_addr_change = hci_stack->custom_bd_addr_set
13573fb36a29SMatthias Ringwald                         && hci_stack->chipset
13583fb36a29SMatthias Ringwald                         && hci_stack->chipset->set_bd_addr_command;
135906b9e820SMatthias Ringwald #endif
1360a80162e9SMatthias Ringwald 
13615c363727SMatthias Ringwald     switch(hci_stack->substate){
136206b9e820SMatthias Ringwald 
136306b9e820SMatthias Ringwald #if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
13649f007422SMatthias Ringwald         case HCI_INIT_SEND_RESET:
1365d58dd308SMatthias Ringwald             // on CSR with BCSP/H5, resend triggers resend of HCI Reset and leads to substate == HCI_INIT_SEND_RESET
13669f007422SMatthias Ringwald             // fix: just correct substate and behave as command below
13679f007422SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_SEND_RESET;
13689f007422SMatthias Ringwald             btstack_run_loop_remove_timer(&hci_stack->timeout);
13699f007422SMatthias Ringwald             break;
137074b323a9SMatthias Ringwald         case HCI_INIT_W4_SEND_RESET:
1371528a4a3bSMatthias Ringwald             btstack_run_loop_remove_timer(&hci_stack->timeout);
137276fcb19bSMatthias Ringwald             break;
1373e90bae01SMatthias Ringwald         case HCI_INIT_W4_SEND_READ_LOCAL_NAME:
1374e90bae01SMatthias Ringwald             log_info("Received local name, need baud change %d", need_baud_change);
13752f48d920SMatthias Ringwald             if (need_baud_change){
13762f48d920SMatthias Ringwald                 hci_stack->substate = HCI_INIT_SEND_BAUD_CHANGE;
13772f48d920SMatthias Ringwald                 return;
13782f48d920SMatthias Ringwald             }
137953860077SMatthias Ringwald             // skip baud change
138074b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_CUSTOM_INIT;
138174b323a9SMatthias Ringwald             return;
1382a80162e9SMatthias Ringwald         case HCI_INIT_W4_SEND_BAUD_CHANGE:
13834696bddbSMatthias Ringwald             // for STLC2500D, baud rate change already happened.
1384fab26ab3SMatthias Ringwald             // for others, baud rate gets changed now
1385*61f37892SMatthias Ringwald             if ((hci_stack->manufacturer != BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS) && need_baud_change){
138696b53536SMatthias Ringwald                 uint32_t baud_rate = hci_transport_uart_get_main_baud_rate();
1387cd724cb7SMatthias Ringwald                 log_info("Local baud rate change to %"PRIu32"(w4_send_baud_change)", baud_rate);
1388fab26ab3SMatthias Ringwald                 hci_stack->hci_transport->set_baudrate(baud_rate);
13894696bddbSMatthias Ringwald             }
139074b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_CUSTOM_INIT;
139174b323a9SMatthias Ringwald             return;
1392a80162e9SMatthias Ringwald         case HCI_INIT_W4_CUSTOM_INIT_CSR_WARM_BOOT:
1393528a4a3bSMatthias Ringwald             btstack_run_loop_remove_timer(&hci_stack->timeout);
1394a80162e9SMatthias Ringwald             hci_stack->substate = HCI_INIT_CUSTOM_INIT;
1395a80162e9SMatthias Ringwald             return;
139674b323a9SMatthias Ringwald         case HCI_INIT_W4_CUSTOM_INIT:
139774b323a9SMatthias Ringwald             // repeat custom init
139874b323a9SMatthias Ringwald             hci_stack->substate = HCI_INIT_CUSTOM_INIT;
139974b323a9SMatthias Ringwald             return;
140006b9e820SMatthias Ringwald #else
140106b9e820SMatthias Ringwald         case HCI_INIT_W4_SEND_RESET:
140206b9e820SMatthias Ringwald             hci_stack->substate = HCI_INIT_READ_LOCAL_SUPPORTED_COMMANDS;
140306b9e820SMatthias Ringwald             return ;
140406b9e820SMatthias Ringwald #endif
140506b9e820SMatthias Ringwald 
1406a828a756SMatthias Ringwald         case HCI_INIT_W4_READ_LOCAL_SUPPORTED_COMMANDS:
1407*61f37892SMatthias Ringwald             if (need_baud_change && hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION){
1408eb3a5314SMatthias Ringwald                 hci_stack->substate = HCI_INIT_SEND_BAUD_CHANGE_BCM;
1409eb3a5314SMatthias Ringwald                 return;
1410eb3a5314SMatthias Ringwald             }
141153860077SMatthias Ringwald             if (need_addr_change){
141253860077SMatthias Ringwald                 hci_stack->substate = HCI_INIT_SET_BD_ADDR;
141353860077SMatthias Ringwald                 return;
141453860077SMatthias Ringwald             }
141553860077SMatthias Ringwald             hci_stack->substate = HCI_INIT_READ_BD_ADDR;
141653860077SMatthias Ringwald             return;
141706b9e820SMatthias Ringwald #if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
14187224be7eSMatthias Ringwald         case HCI_INIT_W4_SEND_BAUD_CHANGE_BCM:
14197224be7eSMatthias Ringwald             if (need_baud_change){
142096b53536SMatthias Ringwald                 uint32_t baud_rate = hci_transport_uart_get_main_baud_rate();
1421cd724cb7SMatthias Ringwald                 log_info("Local baud rate change to %"PRIu32"(w4_send_baud_change_bcm))", baud_rate);
1422fab26ab3SMatthias Ringwald                 hci_stack->hci_transport->set_baudrate(baud_rate);
14237224be7eSMatthias Ringwald             }
1424eb3a5314SMatthias Ringwald             if (need_addr_change){
1425eb3a5314SMatthias Ringwald                 hci_stack->substate = HCI_INIT_SET_BD_ADDR;
1426eb3a5314SMatthias Ringwald                 return;
1427eb3a5314SMatthias Ringwald             }
1428eb3a5314SMatthias Ringwald             hci_stack->substate = HCI_INIT_READ_BD_ADDR;
1429eb3a5314SMatthias Ringwald             return;
143053860077SMatthias Ringwald         case HCI_INIT_W4_SET_BD_ADDR:
143153860077SMatthias Ringwald             // for STLC2500D, bd addr change only gets active after sending reset command
1432*61f37892SMatthias Ringwald             if (hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS){
143353860077SMatthias Ringwald                 hci_stack->substate = HCI_INIT_SEND_RESET_ST_WARM_BOOT;
143453860077SMatthias Ringwald                 return;
143553860077SMatthias Ringwald             }
143653860077SMatthias Ringwald             // skipping st warm boot
143753860077SMatthias Ringwald             hci_stack->substate = HCI_INIT_READ_BD_ADDR;
143853860077SMatthias Ringwald             return;
143953860077SMatthias Ringwald         case HCI_INIT_W4_SEND_RESET_ST_WARM_BOOT:
144053860077SMatthias Ringwald             hci_stack->substate = HCI_INIT_READ_BD_ADDR;
144153860077SMatthias Ringwald             return;
144206b9e820SMatthias Ringwald #endif
144353860077SMatthias Ringwald         case HCI_INIT_W4_READ_BD_ADDR:
144453860077SMatthias Ringwald             // only read buffer size if supported
144553860077SMatthias Ringwald             if (hci_stack->local_supported_commands[0] & 0x01) {
144653860077SMatthias Ringwald                 hci_stack->substate = HCI_INIT_READ_BUFFER_SIZE;
144753860077SMatthias Ringwald                 return;
144853860077SMatthias Ringwald             }
144953860077SMatthias Ringwald             // skipping read buffer size
145053860077SMatthias Ringwald             hci_stack->substate = HCI_INIT_READ_LOCAL_SUPPORTED_FEATURES;
1451a828a756SMatthias Ringwald             return;
145274b323a9SMatthias Ringwald         case HCI_INIT_W4_SET_EVENT_MASK:
14536155b3d3S[email protected]             // skip Classic init commands for LE only chipsets
14546155b3d3S[email protected]             if (!hci_classic_supported()){
14552c68f164SMatthias Ringwald #ifdef ENABLE_BLE
14566155b3d3S[email protected]                 if (hci_le_supported()){
145774b323a9SMatthias Ringwald                     hci_stack->substate = HCI_INIT_LE_READ_BUFFER_SIZE; // skip all classic command
145874b323a9SMatthias Ringwald                     return;
14592c68f164SMatthias Ringwald                 }
14602c68f164SMatthias Ringwald #endif
14616155b3d3S[email protected]                 log_error("Neither BR/EDR nor LE supported");
1462a650ba4dSMatthias Ringwald                 hci_init_done();
146374b323a9SMatthias Ringwald                 return;
14646155b3d3S[email protected]             }
146515a95bd5SMatthias Ringwald             if (!gap_ssp_supported()){
14665c363727SMatthias Ringwald                 hci_stack->substate = HCI_INIT_WRITE_PAGE_TIMEOUT;
146774b323a9SMatthias Ringwald                 return;
14686155b3d3S[email protected]             }
14696155b3d3S[email protected]             break;
1470903ea03aSMatthias Ringwald #ifdef ENABLE_BLE
1471a828a756SMatthias Ringwald         case HCI_INIT_W4_LE_READ_BUFFER_SIZE:
1472a828a756SMatthias Ringwald             // skip write le host if not supported (e.g. on LE only EM9301)
1473a828a756SMatthias Ringwald             if (hci_stack->local_supported_commands[0] & 0x02) break;
1474903ea03aSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
1475903ea03aSMatthias Ringwald             hci_stack->substate = HCI_INIT_READ_WHITE_LIST_SIZE;
1476903ea03aSMatthias Ringwald #else
1477903ea03aSMatthias Ringwald             hci_init_done();
1478903ea03aSMatthias Ringwald #endif
1479a828a756SMatthias Ringwald             return;
1480903ea03aSMatthias Ringwald #endif
1481ff00ed1cSMatthias Ringwald         case HCI_INIT_W4_WRITE_LOCAL_NAME:
1482ff00ed1cSMatthias Ringwald             // skip write eir data if no eir data set
1483ff00ed1cSMatthias Ringwald             if (hci_stack->eir_data) break;
1484ff00ed1cSMatthias Ringwald             hci_stack->substate = HCI_INIT_WRITE_INQUIRY_MODE;
1485ff00ed1cSMatthias Ringwald             return;
1486729ed62eSMatthias Ringwald 
148771c4de7aSMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
1488729ed62eSMatthias Ringwald         case HCI_INIT_W4_WRITE_SCAN_ENABLE:
14893905afbfSMatthias Ringwald             // skip write synchronous flow control if not supported
14903905afbfSMatthias Ringwald             if (hci_stack->local_supported_commands[0] & 0x04) break;
14913905afbfSMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE;
14923905afbfSMatthias Ringwald             // explicit fall through to reduce repetitions
14933905afbfSMatthias Ringwald 
1494729ed62eSMatthias Ringwald         case HCI_INIT_W4_WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE:
14953905afbfSMatthias Ringwald             // skip write default erroneous data reporting if not supported
14963905afbfSMatthias Ringwald             if (hci_stack->local_supported_commands[0] & 0x08) break;
14973905afbfSMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING;
14983905afbfSMatthias Ringwald             // explicit fall through to reduce repetitions
14993905afbfSMatthias Ringwald 
1500f064e0bbSMatthias Ringwald         case HCI_INIT_W4_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING:
1501a42798c3SMatthias Ringwald             // skip bcm set sco pcm config on non-Broadcom chipsets
1502*61f37892SMatthias Ringwald             if (hci_stack->manufacturer == BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION) break;
1503a42798c3SMatthias Ringwald             hci_stack->substate = HCI_INIT_W4_BCM_WRITE_SCO_PCM_INT;
1504a42798c3SMatthias Ringwald             // explicit fall through to reduce repetitions
1505a42798c3SMatthias Ringwald 
1506a42798c3SMatthias Ringwald         case HCI_INIT_W4_BCM_WRITE_SCO_PCM_INT:
1507729ed62eSMatthias Ringwald             if (!hci_le_supported()){
1508729ed62eSMatthias Ringwald                 // SKIP LE init for Classic only configuration
1509a650ba4dSMatthias Ringwald                 hci_init_done();
1510729ed62eSMatthias Ringwald                 return;
1511729ed62eSMatthias Ringwald             }
1512729ed62eSMatthias Ringwald             break;
1513f3b012f9SMatthias Ringwald 
1514f3b012f9SMatthias Ringwald #else /* !ENABLE_SCO_OVER_HCI */
1515f3b012f9SMatthias Ringwald 
151674b323a9SMatthias Ringwald         case HCI_INIT_W4_WRITE_SCAN_ENABLE:
1517f3b012f9SMatthias Ringwald #ifdef ENABLE_BLE
1518f3b012f9SMatthias Ringwald             if (hci_le_supported()){
1519f3b012f9SMatthias Ringwald                 hci_stack->substate = HCI_INIT_LE_READ_BUFFER_SIZE;
152074b323a9SMatthias Ringwald                 return;
15216155b3d3S[email protected]             }
1522729ed62eSMatthias Ringwald #endif
1523f3b012f9SMatthias Ringwald             // SKIP LE init for Classic only configuration
1524f3b012f9SMatthias Ringwald             hci_init_done();
1525f3b012f9SMatthias Ringwald             return;
1526f3b012f9SMatthias Ringwald #endif /* ENABLE_SCO_OVER_HCI */
1527f3b012f9SMatthias Ringwald 
1528a650ba4dSMatthias Ringwald         // Response to command before init done state -> init done
1529a650ba4dSMatthias Ringwald         case (HCI_INIT_DONE-1):
1530a650ba4dSMatthias Ringwald             hci_init_done();
1531a650ba4dSMatthias Ringwald             return;
1532a650ba4dSMatthias Ringwald 
15336155b3d3S[email protected]         default:
153474b323a9SMatthias Ringwald             break;
15356155b3d3S[email protected]     }
153655975f88SMatthias Ringwald     hci_initializing_next_state();
15376155b3d3S[email protected] }
15386155b3d3S[email protected] 
153916833f0aSmatthias.ringwald static void event_handler(uint8_t *packet, int size){
1540e76a89eeS[email protected] 
1541e76a89eeS[email protected]     uint16_t event_length = packet[1];
1542e76a89eeS[email protected] 
1543e76a89eeS[email protected]     // assert packet is complete
1544e76a89eeS[email protected]     if (size != event_length + 2){
1545f04a0c31SMatthias Ringwald         log_error("hci.c: event_handler called with event packet of wrong size %d, expected %u => dropping packet", size, event_length + 2);
1546e76a89eeS[email protected]         return;
1547e76a89eeS[email protected]     }
1548e76a89eeS[email protected] 
15491281a47eSmatthias.ringwald     bd_addr_t addr;
155096a45072S[email protected]     bd_addr_type_t addr_type;
15512d00edd4Smatthias.ringwald     uint8_t link_type;
1552fe1ed1b8Smatthias.ringwald     hci_con_handle_t handle;
15531f7b95a1Smatthias.ringwald     hci_connection_t * conn;
155456cf178bSmatthias.ringwald     int i;
155522909952Smatthias.ringwald 
155635454696SMatthias Ringwald     // warnings
155735454696SMatthias Ringwald     (void) link_type;
155835454696SMatthias Ringwald 
15590e2df43fSMatthias Ringwald     // log_info("HCI:EVENT:%02x", hci_event_packet_get_type(packet));
15605909f7f2Smatthias.ringwald 
15610e2df43fSMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
156222909952Smatthias.ringwald 
15636772a24cSmatthias.ringwald         case HCI_EVENT_COMMAND_COMPLETE:
15646bef4003SMatthias Ringwald             // get num cmd packets - limit to 1 to reduce complexity
15656bef4003SMatthias Ringwald             hci_stack->num_cmd_packets = packet[2] ? 1 : 0;
15667ec5eeaaSmatthias.ringwald 
15679e263bd7SMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_name)){
156806b9e820SMatthias Ringwald                 if (packet[5]) break;
15699e263bd7SMatthias Ringwald                 // terminate, name 248 chars
15709e263bd7SMatthias Ringwald                 packet[6+248] = 0;
15719e263bd7SMatthias Ringwald                 log_info("local name: %s", &packet[6]);
15729e263bd7SMatthias Ringwald             }
1573073bd0faSMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_buffer_size)){
15741d279b20Smatthias.ringwald                 // "The HC_ACL_Data_Packet_Length return parameter will be used to determine the size of the L2CAP segments contained in ACL Data Packets"
1575429122ccSMatthias Ringwald                 if (hci_stack->state == HCI_STATE_INITIALIZING){
1576429122ccSMatthias Ringwald                     uint16_t acl_len = little_endian_read_16(packet, 6);
1577429122ccSMatthias Ringwald                     uint16_t sco_len = packet[8];
1578429122ccSMatthias Ringwald 
1579429122ccSMatthias Ringwald                     // determine usable ACL/SCO payload size
1580429122ccSMatthias Ringwald                     hci_stack->acl_data_packet_length = btstack_min(acl_len, HCI_ACL_PAYLOAD_SIZE);
1581429122ccSMatthias Ringwald                     hci_stack->sco_data_packet_length = btstack_min(sco_len, HCI_ACL_PAYLOAD_SIZE);
1582429122ccSMatthias Ringwald 
1583f8fbdce0SMatthias Ringwald                     hci_stack->acl_packets_total_num  = little_endian_read_16(packet, 9);
1584f8fbdce0SMatthias Ringwald                     hci_stack->sco_packets_total_num  = little_endian_read_16(packet, 11);
1585a8b12447S[email protected] 
1586429122ccSMatthias Ringwald                     log_info("hci_read_buffer_size: ACL size module %u -> used %u, count %u / SCO size %u, count %u",
1587429122ccSMatthias Ringwald                              acl_len, hci_stack->acl_data_packet_length, hci_stack->acl_packets_total_num,
15881a06f663S[email protected]                              hci_stack->sco_data_packet_length, hci_stack->sco_packets_total_num);
1589e2edc0c3Smatthias.ringwald                 }
159056cf178bSmatthias.ringwald             }
1591a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
1592073bd0faSMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_read_buffer_size)){
1593f8fbdce0SMatthias Ringwald                 hci_stack->le_data_packets_length = little_endian_read_16(packet, 6);
1594ee303eddS[email protected]                 hci_stack->le_acl_packets_total_num  = packet[8];
15956c26b087S[email protected]                     // determine usable ACL payload size
15966c26b087S[email protected]                     if (HCI_ACL_PAYLOAD_SIZE < hci_stack->le_data_packets_length){
15976c26b087S[email protected]                         hci_stack->le_data_packets_length = HCI_ACL_PAYLOAD_SIZE;
15986c26b087S[email protected]                     }
15999da54300S[email protected]                 log_info("hci_le_read_buffer_size: size %u, count %u", hci_stack->le_data_packets_length, hci_stack->le_acl_packets_total_num);
160065a46ef3S[email protected]             }
1601d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
1602073bd0faSMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_le_read_white_list_size)){
1603e691bb38SMatthias Ringwald                 hci_stack->le_whitelist_capacity = packet[6];
160415d0a15bSMatthias Ringwald                 log_info("hci_le_read_white_list_size: size %u", hci_stack->le_whitelist_capacity);
16053b6d4121SMatthias Ringwald             }
160665a46ef3S[email protected] #endif
1607d70217a2SMatthias Ringwald #endif
1608073bd0faSMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_bd_addr)) {
1609724d70a2SMatthias Ringwald                 reverse_bd_addr(&packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1],
1610724d70a2SMatthias Ringwald 				hci_stack->local_bd_addr);
16119da54300S[email protected]                 log_info("Local Address, Status: 0x%02x: Addr: %s",
16123a9fb326S[email protected]                     packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE], bd_addr_to_str(hci_stack->local_bd_addr));
161333373e40SMatthias Ringwald #ifdef ENABLE_CLASSIC
16141624665aSMatthias Ringwald                 if (hci_stack->link_key_db){
16151624665aSMatthias Ringwald                     hci_stack->link_key_db->set_local_bd_addr(hci_stack->local_bd_addr);
16161624665aSMatthias Ringwald                 }
161733373e40SMatthias Ringwald #endif
1618188981d2Smatthias.ringwald             }
161935454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
1620073bd0faSMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_scan_enable)){
16213a9fb326S[email protected]                 hci_emit_discoverable_enabled(hci_stack->discoverable);
1622381fbed8Smatthias.ringwald             }
162335454696SMatthias Ringwald #endif
162435454696SMatthias Ringwald 
162565389bfcS[email protected]             // Note: HCI init checks
1626073bd0faSMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_supported_features)){
16273a9fb326S[email protected]                 memcpy(hci_stack->local_supported_features, &packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1], 8);
162865389bfcS[email protected] 
162935454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
1630a5a23fc2S[email protected]                 // determine usable ACL packet types based on host buffer size and supported features
1631a5a23fc2S[email protected]                 hci_stack->packet_types = hci_acl_packet_types_for_buffer_size_and_local_features(HCI_ACL_PAYLOAD_SIZE, &hci_stack->local_supported_features[0]);
16328b96126aSMatthias Ringwald                 log_info("Packet types %04x, eSCO %u", hci_stack->packet_types, hci_extended_sco_link_supported());
163335454696SMatthias Ringwald #endif
1634f5d8d141S[email protected]                 // Classic/LE
1635f5d8d141S[email protected]                 log_info("BR/EDR support %u, LE support %u", hci_classic_supported(), hci_le_supported());
1636559e517eS[email protected]             }
1637073bd0faSMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_version_information)){
1638f8fbdce0SMatthias Ringwald                 // hci_stack->hci_version    = little_endian_read_16(packet, 4);
1639f8fbdce0SMatthias Ringwald                 // hci_stack->hci_revision   = little_endian_read_16(packet, 6);
1640f8fbdce0SMatthias Ringwald                 // hci_stack->lmp_version    = little_endian_read_16(packet, 8);
1641f8fbdce0SMatthias Ringwald                 hci_stack->manufacturer   = little_endian_read_16(packet, 10);
1642f8fbdce0SMatthias Ringwald                 // hci_stack->lmp_subversion = little_endian_read_16(packet, 12);
16434696bddbSMatthias Ringwald                 log_info("Manufacturer: 0x%04x", hci_stack->manufacturer);
16444696bddbSMatthias Ringwald             }
1645073bd0faSMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_read_local_supported_commands)){
1646a828a756SMatthias Ringwald                 hci_stack->local_supported_commands[0] =
16473905afbfSMatthias Ringwald                     (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+14] & 0x80) >> 7 |  // bit 0 = Octet 14, bit 7
16483905afbfSMatthias Ringwald                     (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+24] & 0x40) >> 5 |  // bit 1 = Octet 24, bit 6
16493905afbfSMatthias Ringwald                     (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+10] & 0x10) >> 2 |  // bit 2 = Octet 10, bit 4
16503905afbfSMatthias Ringwald                     (packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE+1+18] & 0x08);        // bit 3 = Octet 18, bit 3
16513905afbfSMatthias Ringwald                     log_info("Local supported commands summary 0x%02x", hci_stack->local_supported_commands[0]);
1652a828a756SMatthias Ringwald             }
1653e8c8828eSMatthias Ringwald #ifdef ENABLE_CLASSIC
1654073bd0faSMatthias Ringwald             if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_synchronous_flow_control_enable)){
16555b9b590fSMatthias Ringwald                 if (packet[5] == 0){
16565b9b590fSMatthias Ringwald                     hci_stack->synchronous_flow_control_enabled = 1;
16575b9b590fSMatthias Ringwald                 }
16585b9b590fSMatthias Ringwald             }
1659e8c8828eSMatthias Ringwald #endif
166056cf178bSmatthias.ringwald             break;
166156cf178bSmatthias.ringwald 
16627ec5eeaaSmatthias.ringwald         case HCI_EVENT_COMMAND_STATUS:
16636bef4003SMatthias Ringwald             // get num cmd packets - limit to 1 to reduce complexity
16646bef4003SMatthias Ringwald             hci_stack->num_cmd_packets = packet[3] ? 1 : 0;
16657ec5eeaaSmatthias.ringwald             break;
16667ec5eeaaSmatthias.ringwald 
16672e440c8aS[email protected]         case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:{
16682e440c8aS[email protected]             int offset = 3;
166956cf178bSmatthias.ringwald             for (i=0; i<packet[2];i++){
1670f8fbdce0SMatthias Ringwald                 handle = little_endian_read_16(packet, offset);
16712e440c8aS[email protected]                 offset += 2;
1672f8fbdce0SMatthias Ringwald                 uint16_t num_packets = little_endian_read_16(packet, offset);
16732e440c8aS[email protected]                 offset += 2;
16742e440c8aS[email protected] 
16755061f3afS[email protected]                 conn = hci_connection_for_handle(handle);
167656cf178bSmatthias.ringwald                 if (!conn){
16779da54300S[email protected]                     log_error("hci_number_completed_packet lists unused con handle %u", handle);
167856cf178bSmatthias.ringwald                     continue;
167956cf178bSmatthias.ringwald                 }
168023bed257S[email protected] 
1681e35edcc1S[email protected]                 if (conn->address_type == BD_ADDR_TYPE_SCO){
168235454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
1683e35edcc1S[email protected]                     if (conn->num_sco_packets_sent >= num_packets){
1684e35edcc1S[email protected]                         conn->num_sco_packets_sent -= num_packets;
1685e35edcc1S[email protected]                     } else {
1686e35edcc1S[email protected]                         log_error("hci_number_completed_packets, more sco slots freed then sent.");
1687e35edcc1S[email protected]                         conn->num_sco_packets_sent = 0;
1688e35edcc1S[email protected]                     }
1689701e3307SMatthias Ringwald                     hci_notify_if_sco_can_send_now();
169035454696SMatthias Ringwald #endif
1691e35edcc1S[email protected]                 } else {
169223bed257S[email protected]                     if (conn->num_acl_packets_sent >= num_packets){
169356cf178bSmatthias.ringwald                         conn->num_acl_packets_sent -= num_packets;
169423bed257S[email protected]                     } else {
1695e35edcc1S[email protected]                         log_error("hci_number_completed_packets, more acl slots freed then sent.");
169623bed257S[email protected]                         conn->num_acl_packets_sent = 0;
169723bed257S[email protected]                     }
1698e35edcc1S[email protected]                 }
16999da54300S[email protected]                 // log_info("hci_number_completed_packet %u processed for handle %u, outstanding %u", num_packets, handle, conn->num_acl_packets_sent);
170056cf178bSmatthias.ringwald             }
17016772a24cSmatthias.ringwald             break;
17022e440c8aS[email protected]         }
170335454696SMatthias Ringwald 
170435454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
17051f7b95a1Smatthias.ringwald         case HCI_EVENT_CONNECTION_REQUEST:
1706724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[2], addr);
170737eaa4cfSmatthias.ringwald             // TODO: eval COD 8-10
17082d00edd4Smatthias.ringwald             link_type = packet[11];
17099da54300S[email protected]             log_info("Connection_incoming: %s, type %u", bd_addr_to_str(addr), link_type);
1710e35edcc1S[email protected]             addr_type = link_type == 1 ? BD_ADDR_TYPE_CLASSIC : BD_ADDR_TYPE_SCO;
17112e77e513S[email protected]             conn = hci_connection_for_bd_addr_and_type(addr, addr_type);
17121f7b95a1Smatthias.ringwald             if (!conn) {
17135293c072S[email protected]                 conn = create_connection_for_bd_addr_and_type(addr, addr_type);
17141f7b95a1Smatthias.ringwald             }
1715ce4c8fabSmatthias.ringwald             if (!conn) {
1716ce4c8fabSmatthias.ringwald                 // CONNECTION REJECTED DUE TO LIMITED RESOURCES (0X0D)
17173a9fb326S[email protected]                 hci_stack->decline_reason = 0x0d;
1718058e3d6bSMatthias Ringwald                 bd_addr_copy(hci_stack->decline_addr, addr);
1719ce4c8fabSmatthias.ringwald                 break;
1720ce4c8fabSmatthias.ringwald             }
17215cf766e8SMatthias Ringwald             conn->role  = HCI_ROLE_SLAVE;
172232ab9390Smatthias.ringwald             conn->state = RECEIVED_CONNECTION_REQUEST;
1723f3a16b9aSMatthias Ringwald             // store info about eSCO
1724f3a16b9aSMatthias Ringwald             if (link_type == 0x02){
1725f3a16b9aSMatthias Ringwald                 conn->remote_supported_feature_eSCO = 1;
1726f3a16b9aSMatthias Ringwald             }
172732ab9390Smatthias.ringwald             hci_run();
17281f7b95a1Smatthias.ringwald             break;
17291f7b95a1Smatthias.ringwald 
17306772a24cSmatthias.ringwald         case HCI_EVENT_CONNECTION_COMPLETE:
1731fe1ed1b8Smatthias.ringwald             // Connection management
1732724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[5], addr);
17339da54300S[email protected]             log_info("Connection_complete (status=%u) %s", packet[2], bd_addr_to_str(addr));
173496a45072S[email protected]             addr_type = BD_ADDR_TYPE_CLASSIC;
17352e77e513S[email protected]             conn = hci_connection_for_bd_addr_and_type(addr, addr_type);
1736fe1ed1b8Smatthias.ringwald             if (conn) {
1737b448a0e7Smatthias.ringwald                 if (!packet[2]){
1738c8e4258aSmatthias.ringwald                     conn->state = OPEN;
1739f8fbdce0SMatthias Ringwald                     conn->con_handle = little_endian_read_16(packet, 3);
1740ad83dc6aS[email protected]                     conn->bonding_flags |= BONDING_REQUEST_REMOTE_FEATURES;
1741ee091cf1Smatthias.ringwald 
1742c785ef68Smatthias.ringwald                     // restart timer
1743528a4a3bSMatthias Ringwald                     btstack_run_loop_set_timer(&conn->timeout, HCI_CONNECTION_TIMEOUT_MS);
1744528a4a3bSMatthias Ringwald                     btstack_run_loop_add_timer(&conn->timeout);
1745c785ef68Smatthias.ringwald 
17469da54300S[email protected]                     log_info("New connection: handle %u, %s", conn->con_handle, bd_addr_to_str(conn->address));
174743bfb1bdSmatthias.ringwald 
174843bfb1bdSmatthias.ringwald                     hci_emit_nr_connections_changed();
1749b448a0e7Smatthias.ringwald                 } else {
17501bd5283dS[email protected]                     int notify_dedicated_bonding_failed = conn->bonding_flags & BONDING_DEDICATED;
17511bd5283dS[email protected]                     uint8_t status = packet[2];
17521bd5283dS[email protected]                     bd_addr_t bd_address;
17531bd5283dS[email protected]                     memcpy(&bd_address, conn->address, 6);
1754ad83dc6aS[email protected] 
1755b448a0e7Smatthias.ringwald                     // connection failed, remove entry
1756665d90f2SMatthias Ringwald                     btstack_linked_list_remove(&hci_stack->connections, (btstack_linked_item_t *) conn);
1757a3b02b71Smatthias.ringwald                     btstack_memory_hci_connection_free( conn );
1758c12e46e7Smatthias.ringwald 
17591bd5283dS[email protected]                     // notify client if dedicated bonding
17601bd5283dS[email protected]                     if (notify_dedicated_bonding_failed){
17611bd5283dS[email protected]                         log_info("hci notify_dedicated_bonding_failed");
17621bd5283dS[email protected]                         hci_emit_dedicated_bonding_result(bd_address, status);
17631bd5283dS[email protected]                     }
17641bd5283dS[email protected] 
1765c12e46e7Smatthias.ringwald                     // if authentication error, also delete link key
1766c12e46e7Smatthias.ringwald                     if (packet[2] == 0x05) {
176715a95bd5SMatthias Ringwald                         gap_drop_link_key_for_bd_addr(addr);
1768c12e46e7Smatthias.ringwald                     }
1769fe1ed1b8Smatthias.ringwald                 }
1770fe1ed1b8Smatthias.ringwald             }
17716772a24cSmatthias.ringwald             break;
1772fe1ed1b8Smatthias.ringwald 
177344d0e3d5S[email protected]         case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:
1774724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[5], addr);
177544d0e3d5S[email protected]             log_info("Synchronous Connection Complete (status=%u) %s", packet[2], bd_addr_to_str(addr));
17761a06f663S[email protected]             if (packet[2]){
177744d0e3d5S[email protected]                 // connection failed
177844d0e3d5S[email protected]                 break;
177944d0e3d5S[email protected]             }
17802e77e513S[email protected]             conn = hci_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_SCO);
1781e35edcc1S[email protected]             if (!conn) {
1782e35edcc1S[email protected]                 conn = create_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_SCO);
1783e35edcc1S[email protected]             }
1784e35edcc1S[email protected]             if (!conn) {
1785e35edcc1S[email protected]                 break;
1786e35edcc1S[email protected]             }
17871a06f663S[email protected]             conn->state = OPEN;
1788f8fbdce0SMatthias Ringwald             conn->con_handle = little_endian_read_16(packet, 3);
1789ee752bb8SMatthias Ringwald 
1790ee752bb8SMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
1791ee752bb8SMatthias Ringwald             // update SCO
1792ee752bb8SMatthias Ringwald             if (conn->address_type == BD_ADDR_TYPE_SCO && hci_stack->hci_transport && hci_stack->hci_transport->set_sco_config){
1793ee752bb8SMatthias Ringwald                 hci_stack->hci_transport->set_sco_config(hci_stack->sco_voice_setting_active, hci_number_sco_connections());
1794ee752bb8SMatthias Ringwald             }
1795ee752bb8SMatthias Ringwald #endif
179644d0e3d5S[email protected]             break;
179744d0e3d5S[email protected] 
1798afd4e962S[email protected]         case HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE:
1799f8fbdce0SMatthias Ringwald             handle = little_endian_read_16(packet, 3);
1800afd4e962S[email protected]             conn = hci_connection_for_handle(handle);
1801afd4e962S[email protected]             if (!conn) break;
1802afd4e962S[email protected]             if (!packet[2]){
1803afd4e962S[email protected]                 uint8_t * features = &packet[5];
1804afd4e962S[email protected]                 if (features[6] & (1 << 3)){
1805afd4e962S[email protected]                     conn->bonding_flags |= BONDING_REMOTE_SUPPORTS_SSP;
1806afd4e962S[email protected]                 }
180798a2fd1cSMatthias Ringwald                 if (features[3] & (1<<7)){
180898a2fd1cSMatthias Ringwald                     conn->remote_supported_feature_eSCO = 1;
180998a2fd1cSMatthias Ringwald                 }
1810afd4e962S[email protected]             }
1811afd4e962S[email protected]             conn->bonding_flags |= BONDING_RECEIVED_REMOTE_FEATURES;
181298a2fd1cSMatthias Ringwald             log_info("HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE, bonding flags %x, eSCO %u", conn->bonding_flags, conn->remote_supported_feature_eSCO);
1813ad83dc6aS[email protected]             if (conn->bonding_flags & BONDING_DEDICATED){
1814ad83dc6aS[email protected]                 conn->bonding_flags |= BONDING_SEND_AUTHENTICATE_REQUEST;
1815ad83dc6aS[email protected]             }
1816afd4e962S[email protected]             break;
1817afd4e962S[email protected] 
18187fde4af9Smatthias.ringwald         case HCI_EVENT_LINK_KEY_REQUEST:
18199da54300S[email protected]             log_info("HCI_EVENT_LINK_KEY_REQUEST");
18207fde4af9Smatthias.ringwald             hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_LINK_KEY_REQUEST);
182174d716b5S[email protected]             // non-bondable mode: link key negative reply will be sent by HANDLE_LINK_KEY_REQUEST
1822a98592bcSMatthias Ringwald             if (hci_stack->bondable && !hci_stack->link_key_db) break;
182332ab9390Smatthias.ringwald             hci_add_connection_flags_for_flipped_bd_addr(&packet[2], HANDLE_LINK_KEY_REQUEST);
182464472d52Smatthias.ringwald             hci_run();
1825d9a327f9Smatthias.ringwald             // request handled by hci_run() as HANDLE_LINK_KEY_REQUEST gets set
182629d53098Smatthias.ringwald             return;
18277fde4af9Smatthias.ringwald 
18289ab95c90S[email protected]         case HCI_EVENT_LINK_KEY_NOTIFICATION: {
1829724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[2], addr);
18302e77e513S[email protected]             conn = hci_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_CLASSIC);
18319ab95c90S[email protected]             if (!conn) break;
18329ab95c90S[email protected]             conn->authentication_flags |= RECV_LINK_KEY_NOTIFICATION;
18337bdc6798S[email protected]             link_key_type_t link_key_type = (link_key_type_t)packet[24];
18349ab95c90S[email protected]             // Change Connection Encryption keeps link key type
18359ab95c90S[email protected]             if (link_key_type != CHANGED_COMBINATION_KEY){
18369ab95c90S[email protected]                 conn->link_key_type = link_key_type;
18379ab95c90S[email protected]             }
183855597469SMatthias Ringwald             gap_store_link_key_for_bd_addr(addr, &packet[8], conn->link_key_type);
183929d53098Smatthias.ringwald             // still forward event to allow dismiss of pairing dialog
18407fde4af9Smatthias.ringwald             break;
18419ab95c90S[email protected]         }
18427fde4af9Smatthias.ringwald 
18437fde4af9Smatthias.ringwald         case HCI_EVENT_PIN_CODE_REQUEST:
18446724cd9eS[email protected]             hci_add_connection_flags_for_flipped_bd_addr(&packet[2], LEGACY_PAIRING_ACTIVE);
18454c57c146S[email protected]             // non-bondable mode: pin code negative reply will be sent
18463a9fb326S[email protected]             if (!hci_stack->bondable){
1847899283eaS[email protected]                 hci_add_connection_flags_for_flipped_bd_addr(&packet[2], DENY_PIN_CODE_REQUEST);
1848f8fb5f6eS[email protected]                 hci_run();
1849f8fb5f6eS[email protected]                 return;
18504c57c146S[email protected]             }
1851d9a327f9Smatthias.ringwald             // PIN CODE REQUEST means the link key request didn't succee -> delete stored link key
1852a98592bcSMatthias Ringwald             if (!hci_stack->link_key_db) break;
1853a6ef64baSMilanka Ringwald             hci_event_pin_code_request_get_bd_addr(packet, addr);
1854a98592bcSMatthias Ringwald             hci_stack->link_key_db->delete_link_key(addr);
18557fde4af9Smatthias.ringwald             break;
18567fde4af9Smatthias.ringwald 
18571d6b20aeS[email protected]         case HCI_EVENT_IO_CAPABILITY_REQUEST:
18581d6b20aeS[email protected]             hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_IO_CAPABILITIES_REQUEST);
1859dbe1a790S[email protected]             hci_add_connection_flags_for_flipped_bd_addr(&packet[2], SEND_IO_CAPABILITIES_REPLY);
1860dbe1a790S[email protected]             break;
1861dbe1a790S[email protected] 
1862dbe1a790S[email protected]         case HCI_EVENT_USER_CONFIRMATION_REQUEST:
18636724cd9eS[email protected]             hci_add_connection_flags_for_flipped_bd_addr(&packet[2], SSP_PAIRING_ACTIVE);
18643a9fb326S[email protected]             if (!hci_stack->ssp_auto_accept) break;
1865dbe1a790S[email protected]             hci_add_connection_flags_for_flipped_bd_addr(&packet[2], SEND_USER_CONFIRM_REPLY);
1866dbe1a790S[email protected]             break;
1867dbe1a790S[email protected] 
1868dbe1a790S[email protected]         case HCI_EVENT_USER_PASSKEY_REQUEST:
18696724cd9eS[email protected]             hci_add_connection_flags_for_flipped_bd_addr(&packet[2], SSP_PAIRING_ACTIVE);
18703a9fb326S[email protected]             if (!hci_stack->ssp_auto_accept) break;
1871dbe1a790S[email protected]             hci_add_connection_flags_for_flipped_bd_addr(&packet[2], SEND_USER_PASSKEY_REPLY);
18721d6b20aeS[email protected]             break;
187335454696SMatthias Ringwald #endif
18741d6b20aeS[email protected] 
1875f0944df2S[email protected]         case HCI_EVENT_ENCRYPTION_CHANGE:
1876f8fbdce0SMatthias Ringwald             handle = little_endian_read_16(packet, 3);
1877f0944df2S[email protected]             conn = hci_connection_for_handle(handle);
1878f0944df2S[email protected]             if (!conn) break;
1879ad83dc6aS[email protected]             if (packet[2] == 0) {
1880f0944df2S[email protected]                 if (packet[5]){
1881f0944df2S[email protected]                     conn->authentication_flags |= CONNECTION_ENCRYPTED;
1882f0944df2S[email protected]                 } else {
1883536f9994S[email protected]                     conn->authentication_flags &= ~CONNECTION_ENCRYPTED;
1884f0944df2S[email protected]                 }
1885ad83dc6aS[email protected]             }
188635454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
1887a00031e2S[email protected]             hci_emit_security_level(handle, gap_security_level_for_connection(conn));
188835454696SMatthias Ringwald #endif
1889f0944df2S[email protected]             break;
1890f0944df2S[email protected] 
189135454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
18921eb2563eS[email protected]         case HCI_EVENT_AUTHENTICATION_COMPLETE_EVENT:
1893f8fbdce0SMatthias Ringwald             handle = little_endian_read_16(packet, 3);
18941eb2563eS[email protected]             conn = hci_connection_for_handle(handle);
18951eb2563eS[email protected]             if (!conn) break;
1896ad83dc6aS[email protected] 
1897ad83dc6aS[email protected]             // dedicated bonding: send result and disconnect
1898ad83dc6aS[email protected]             if (conn->bonding_flags & BONDING_DEDICATED){
1899ad83dc6aS[email protected]                 conn->bonding_flags &= ~BONDING_DEDICATED;
1900ad83dc6aS[email protected]                 conn->bonding_flags |= BONDING_DISCONNECT_DEDICATED_DONE;
19011bd5283dS[email protected]                 conn->bonding_status = packet[2];
1902ad83dc6aS[email protected]                 break;
1903ad83dc6aS[email protected]             }
1904ad83dc6aS[email protected] 
1905b5cb6874S[email protected]             if (packet[2] == 0 && gap_security_level_for_link_key_type(conn->link_key_type) >= conn->requested_security_level){
19061eb2563eS[email protected]                 // link key sufficient for requested security
19071eb2563eS[email protected]                 conn->bonding_flags |= BONDING_SEND_ENCRYPTION_REQUEST;
1908ad83dc6aS[email protected]                 break;
1909ad83dc6aS[email protected]             }
19101eb2563eS[email protected]             // not enough
19111eb2563eS[email protected]             hci_emit_security_level(handle, gap_security_level_for_connection(conn));
19121eb2563eS[email protected]             break;
191335454696SMatthias Ringwald #endif
191434d2123cS[email protected] 
191586805605S[email protected]         // HCI_EVENT_DISCONNECTION_COMPLETE
1916ccda6e14S[email protected]         // has been split, to first notify stack before shutting connection down
1917ccda6e14S[email protected]         // see end of function, too.
1918a4f30ec0S[email protected]         case HCI_EVENT_DISCONNECTION_COMPLETE:
1919a4f30ec0S[email protected]             if (packet[2]) break;   // status != 0
1920f8fbdce0SMatthias Ringwald             handle = little_endian_read_16(packet, 3);
1921c6a37cfdSMatthias Ringwald             // drop outgoing ACL fragments if it is for closed connection
1922c6a37cfdSMatthias Ringwald             if (hci_stack->acl_fragmentation_total_size > 0) {
1923c6a37cfdSMatthias Ringwald                 if (handle == READ_ACL_CONNECTION_HANDLE(hci_stack->hci_packet_buffer)){
1924c6a37cfdSMatthias Ringwald                     log_info("hci: drop fragmented ACL data for closed connection");
1925c6a37cfdSMatthias Ringwald                      hci_stack->acl_fragmentation_total_size = 0;
1926c6a37cfdSMatthias Ringwald                      hci_stack->acl_fragmentation_pos = 0;
1927c6a37cfdSMatthias Ringwald                 }
1928c6a37cfdSMatthias Ringwald             }
192935454696SMatthias Ringwald 
19309a2e4658SMatthias Ringwald             // re-enable advertisements for le connections if active
1931c6a37cfdSMatthias Ringwald             conn = hci_connection_for_handle(handle);
1932c6a37cfdSMatthias Ringwald             if (!conn) break;
193335454696SMatthias Ringwald #ifdef ENABLE_BLE
1934d70217a2SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
19359a2e4658SMatthias Ringwald             if (hci_is_le_connection(conn) && hci_stack->le_advertisements_enabled){
19369a2e4658SMatthias Ringwald                 hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_ENABLE;
19379a2e4658SMatthias Ringwald             }
193835454696SMatthias Ringwald #endif
1939d70217a2SMatthias Ringwald #endif
1940ccda6e14S[email protected]             conn->state = RECEIVED_DISCONNECTION_COMPLETE;
1941ccda6e14S[email protected]             break;
19426772a24cSmatthias.ringwald 
1943c68bdf90Smatthias.ringwald         case HCI_EVENT_HARDWARE_ERROR:
1944313e5f9cSMatthias Ringwald             log_error("Hardware Error: 0x%02x", packet[2]);
1945d23838ecSMatthias Ringwald             if (hci_stack->hardware_error_callback){
1946c2e1fa60SMatthias Ringwald                 (*hci_stack->hardware_error_callback)(packet[2]);
19477586ee35S[email protected]             } else {
19487586ee35S[email protected]                 // if no special requests, just reboot stack
19497586ee35S[email protected]                 hci_power_control_off();
19507586ee35S[email protected]                 hci_power_control_on();
1951c68bdf90Smatthias.ringwald             }
1952c68bdf90Smatthias.ringwald             break;
1953c68bdf90Smatthias.ringwald 
19540e6f3837SMatthias Ringwald #ifdef ENABLE_CLASSIC
19555cf766e8SMatthias Ringwald         case HCI_EVENT_ROLE_CHANGE:
19565cf766e8SMatthias Ringwald             if (packet[2]) break;   // status != 0
1957f8fbdce0SMatthias Ringwald             handle = little_endian_read_16(packet, 3);
19585cf766e8SMatthias Ringwald             conn = hci_connection_for_handle(handle);
19595cf766e8SMatthias Ringwald             if (!conn) break;       // no conn
19605cf766e8SMatthias Ringwald             conn->role = packet[9];
19615cf766e8SMatthias Ringwald             break;
19620e6f3837SMatthias Ringwald #endif
19635cf766e8SMatthias Ringwald 
196463fa3374SMatthias Ringwald         case HCI_EVENT_TRANSPORT_PACKET_SENT:
1965d051460cS[email protected]             // release packet buffer only for asynchronous transport and if there are not further fragements
19664fa24b5fS[email protected]             if (hci_transport_synchronous()) {
196763fa3374SMatthias Ringwald                 log_error("Synchronous HCI Transport shouldn't send HCI_EVENT_TRANSPORT_PACKET_SENT");
19684fa24b5fS[email protected]                 return; // instead of break: to avoid re-entering hci_run()
19694fa24b5fS[email protected]             }
1970d051460cS[email protected]             if (hci_stack->acl_fragmentation_total_size) break;
1971d051460cS[email protected]             hci_release_packet_buffer();
1972701e3307SMatthias Ringwald 
197363fa3374SMatthias Ringwald             // L2CAP receives this event via the hci_emit_event below
197463fa3374SMatthias Ringwald 
197535454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
197663fa3374SMatthias Ringwald             // For SCO, we do the can_send_now_check here
1977701e3307SMatthias Ringwald             hci_notify_if_sco_can_send_now();
197835454696SMatthias Ringwald #endif
19796b4af23dS[email protected]             break;
19806b4af23dS[email protected] 
198135454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
198263fa3374SMatthias Ringwald         case HCI_EVENT_SCO_CAN_SEND_NOW:
198363fa3374SMatthias Ringwald             // For SCO, we do the can_send_now_check here
198463fa3374SMatthias Ringwald             hci_notify_if_sco_can_send_now();
198563fa3374SMatthias Ringwald             return;
198635454696SMatthias Ringwald #endif
198763fa3374SMatthias Ringwald 
1988a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
19895909f7f2Smatthias.ringwald         case HCI_EVENT_LE_META:
19905909f7f2Smatthias.ringwald             switch (packet[2]){
1991d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
199257c9da5bS[email protected]                 case HCI_SUBEVENT_LE_ADVERTISING_REPORT:
19934f4e0224SMatthias Ringwald                     // log_info("advertising report received");
19947bdc6798S[email protected]                     if (hci_stack->le_scanning_state != LE_SCANNING) break;
199557c9da5bS[email protected]                     le_handle_advertisement_report(packet, size);
19967bdc6798S[email protected]                     break;
1997d70217a2SMatthias Ringwald #endif
19985909f7f2Smatthias.ringwald                 case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
19995909f7f2Smatthias.ringwald                     // Connection management
2000724d70a2SMatthias Ringwald                     reverse_bd_addr(&packet[8], addr);
20017bdc6798S[email protected]                     addr_type = (bd_addr_type_t)packet[7];
20029da54300S[email protected]                     log_info("LE Connection_complete (status=%u) type %u, %s", packet[3], addr_type, bd_addr_to_str(addr));
20032e77e513S[email protected]                     conn = hci_connection_for_bd_addr_and_type(addr, addr_type);
2004d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
200542ff5ba1SMatthias Ringwald                     // if auto-connect, remove from whitelist in both roles
200642ff5ba1SMatthias Ringwald                     if (hci_stack->le_connecting_state == LE_CONNECTING_WHITELIST){
200742ff5ba1SMatthias Ringwald                         hci_remove_from_whitelist(addr_type, addr);
200842ff5ba1SMatthias Ringwald                     }
200942ff5ba1SMatthias Ringwald                     // handle error: error is reported only to the initiator -> outgoing connection
20105909f7f2Smatthias.ringwald                     if (packet[3]){
201142ff5ba1SMatthias Ringwald                         // outgoing connection establishment is done
201242ff5ba1SMatthias Ringwald                         hci_stack->le_connecting_state = LE_CONNECTING_IDLE;
201342ff5ba1SMatthias Ringwald                         // remove entry
20145909f7f2Smatthias.ringwald                         if (conn){
2015665d90f2SMatthias Ringwald                             btstack_linked_list_remove(&hci_stack->connections, (btstack_linked_item_t *) conn);
20165909f7f2Smatthias.ringwald                             btstack_memory_hci_connection_free( conn );
20175909f7f2Smatthias.ringwald                         }
20185909f7f2Smatthias.ringwald                         break;
20195909f7f2Smatthias.ringwald                     }
2020d70217a2SMatthias Ringwald #endif
202142ff5ba1SMatthias Ringwald                     // on success, both hosts receive connection complete event
20225cf766e8SMatthias Ringwald                     if (packet[6] == HCI_ROLE_MASTER){
2023d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
202442ff5ba1SMatthias Ringwald                         // if we're master, it was an outgoing connection and we're done with it
202542ff5ba1SMatthias Ringwald                         hci_stack->le_connecting_state = LE_CONNECTING_IDLE;
2026d70217a2SMatthias Ringwald #endif
202742ff5ba1SMatthias Ringwald                     } else {
2028d70217a2SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
202942ff5ba1SMatthias Ringwald                         // if we're slave, it was an incoming connection, advertisements have stopped
2030171293d3SMatthias Ringwald                         hci_stack->le_advertisements_active = 0;
20315106e6dcSMatthias Ringwald                         // try to re-enable them
20325106e6dcSMatthias Ringwald                         hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_ENABLE;
2033d70217a2SMatthias Ringwald #endif
203442ff5ba1SMatthias Ringwald                     }
2035171293d3SMatthias Ringwald                     // LE connections are auto-accepted, so just create a connection if there isn't one already
203642ff5ba1SMatthias Ringwald                     if (!conn){
203796a45072S[email protected]                         conn = create_connection_for_bd_addr_and_type(addr, addr_type);
20385909f7f2Smatthias.ringwald                     }
203942ff5ba1SMatthias Ringwald                     // no memory, sorry.
20405909f7f2Smatthias.ringwald                     if (!conn){
20415909f7f2Smatthias.ringwald                         break;
20425909f7f2Smatthias.ringwald                     }
20435909f7f2Smatthias.ringwald 
20445909f7f2Smatthias.ringwald                     conn->state = OPEN;
20455cf766e8SMatthias Ringwald                     conn->role  = packet[6];
2046f8fbdce0SMatthias Ringwald                     conn->con_handle = little_endian_read_16(packet, 4);
20475909f7f2Smatthias.ringwald 
20485909f7f2Smatthias.ringwald                     // TODO: store - role, peer address type, conn_interval, conn_latency, supervision timeout, master clock
20495909f7f2Smatthias.ringwald 
20505909f7f2Smatthias.ringwald                     // restart timer
2051528a4a3bSMatthias Ringwald                     // btstack_run_loop_set_timer(&conn->timeout, HCI_CONNECTION_TIMEOUT_MS);
2052528a4a3bSMatthias Ringwald                     // btstack_run_loop_add_timer(&conn->timeout);
20535909f7f2Smatthias.ringwald 
20549da54300S[email protected]                     log_info("New connection: handle %u, %s", conn->con_handle, bd_addr_to_str(conn->address));
20555909f7f2Smatthias.ringwald 
20565909f7f2Smatthias.ringwald                     hci_emit_nr_connections_changed();
20575909f7f2Smatthias.ringwald                     break;
20585909f7f2Smatthias.ringwald 
2059f8fbdce0SMatthias Ringwald             // log_info("LE buffer size: %u, count %u", little_endian_read_16(packet,6), packet[8]);
206065a46ef3S[email protected] 
20615909f7f2Smatthias.ringwald                 default:
20625909f7f2Smatthias.ringwald                     break;
20635909f7f2Smatthias.ringwald             }
20645909f7f2Smatthias.ringwald             break;
20655909f7f2Smatthias.ringwald #endif
20666772a24cSmatthias.ringwald         default:
20676772a24cSmatthias.ringwald             break;
2068fe1ed1b8Smatthias.ringwald     }
2069fe1ed1b8Smatthias.ringwald 
20703429f56bSmatthias.ringwald     // handle BT initialization
20713a9fb326S[email protected]     if (hci_stack->state == HCI_STATE_INITIALIZING){
20726155b3d3S[email protected]         hci_initializing_event_handler(packet, size);
2073c9af4d3fS[email protected]     }
207422909952Smatthias.ringwald 
207589db417bSmatthias.ringwald     // help with BT sleep
20763a9fb326S[email protected]     if (hci_stack->state == HCI_STATE_FALLING_ASLEEP
207774b323a9SMatthias Ringwald         && hci_stack->substate == HCI_FALLING_ASLEEP_W4_WRITE_SCAN_ENABLE
2078073bd0faSMatthias Ringwald         && HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_write_scan_enable)){
207955975f88SMatthias Ringwald         hci_initializing_next_state();
208089db417bSmatthias.ringwald     }
208189db417bSmatthias.ringwald 
208286805605S[email protected]     // notify upper stack
2083d6b06661SMatthias Ringwald 	hci_emit_event(packet, size, 0);   // don't dump, already happened in packet handler
208494ab26f8Smatthias.ringwald 
208586805605S[email protected]     // moved here to give upper stack a chance to close down everything with hci_connection_t intact
20860e2df43fSMatthias Ringwald     if (hci_event_packet_get_type(packet) == HCI_EVENT_DISCONNECTION_COMPLETE){
208786805605S[email protected]         if (!packet[2]){
2088f8fbdce0SMatthias Ringwald             handle = little_endian_read_16(packet, 3);
208905ae8de3SMatthias Ringwald             hci_connection_t * aConn = hci_connection_for_handle(handle);
209005ae8de3SMatthias Ringwald             if (aConn) {
209105ae8de3SMatthias Ringwald                 uint8_t status = aConn->bonding_status;
209205ae8de3SMatthias Ringwald                 uint16_t flags = aConn->bonding_flags;
209386805605S[email protected]                 bd_addr_t bd_address;
209405ae8de3SMatthias Ringwald                 memcpy(&bd_address, aConn->address, 6);
209505ae8de3SMatthias Ringwald                 hci_shutdown_connection(aConn);
2096bb820044S[email protected]                 // connection struct is gone, don't access anymore
2097bb820044S[email protected]                 if (flags & BONDING_EMIT_COMPLETE_ON_DISCONNECT){
209886805605S[email protected]                     hci_emit_dedicated_bonding_result(bd_address, status);
209986805605S[email protected]                 }
210086805605S[email protected]             }
210186805605S[email protected]         }
210286805605S[email protected]     }
210386805605S[email protected] 
210494ab26f8Smatthias.ringwald 	// execute main loop
210594ab26f8Smatthias.ringwald 	hci_run();
210616833f0aSmatthias.ringwald }
210716833f0aSmatthias.ringwald 
210835454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
2109c91d150bS[email protected] static void sco_handler(uint8_t * packet, uint16_t size){
21108abbe8b5SMatthias Ringwald     if (!hci_stack->sco_packet_handler) return;
21113d50b4baSMatthias Ringwald     hci_stack->sco_packet_handler(HCI_SCO_DATA_PACKET, 0, packet, size);
2112c91d150bS[email protected] }
211335454696SMatthias Ringwald #endif
2114c91d150bS[email protected] 
21150a57e69fSmatthias.ringwald static void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
21165bb5bc3eS[email protected]     hci_dump_packet(packet_type, 1, packet, size);
211710e830c9Smatthias.ringwald     switch (packet_type) {
211810e830c9Smatthias.ringwald         case HCI_EVENT_PACKET:
211910e830c9Smatthias.ringwald             event_handler(packet, size);
212010e830c9Smatthias.ringwald             break;
212110e830c9Smatthias.ringwald         case HCI_ACL_DATA_PACKET:
212210e830c9Smatthias.ringwald             acl_handler(packet, size);
212310e830c9Smatthias.ringwald             break;
212435454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
2125c91d150bS[email protected]         case HCI_SCO_DATA_PACKET:
2126c91d150bS[email protected]             sco_handler(packet, size);
2127202c8a4cSMatthias Ringwald             break;
212835454696SMatthias Ringwald #endif
212910e830c9Smatthias.ringwald         default:
213010e830c9Smatthias.ringwald             break;
213110e830c9Smatthias.ringwald     }
213210e830c9Smatthias.ringwald }
213310e830c9Smatthias.ringwald 
2134d6b06661SMatthias Ringwald /**
2135d6b06661SMatthias Ringwald  * @brief Add event packet handler.
2136d6b06661SMatthias Ringwald  */
2137d6b06661SMatthias Ringwald void hci_add_event_handler(btstack_packet_callback_registration_t * callback_handler){
2138d6b06661SMatthias Ringwald     btstack_linked_list_add_tail(&hci_stack->event_handlers, (btstack_linked_item_t*) callback_handler);
2139d6b06661SMatthias Ringwald }
2140d6b06661SMatthias Ringwald 
2141d6b06661SMatthias Ringwald 
2142fcadd0caSmatthias.ringwald /** Register HCI packet handlers */
21433d50b4baSMatthias Ringwald void hci_register_acl_packet_handler(btstack_packet_handler_t handler){
2144fb37a842SMatthias Ringwald     hci_stack->acl_packet_handler = handler;
214516833f0aSmatthias.ringwald }
214616833f0aSmatthias.ringwald 
214735454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
21488abbe8b5SMatthias Ringwald /**
21498abbe8b5SMatthias Ringwald  * @brief Registers a packet handler for SCO data. Used for HSP and HFP profiles.
21508abbe8b5SMatthias Ringwald  */
21513d50b4baSMatthias Ringwald void hci_register_sco_packet_handler(btstack_packet_handler_t handler){
21528abbe8b5SMatthias Ringwald     hci_stack->sco_packet_handler = handler;
21538abbe8b5SMatthias Ringwald }
215435454696SMatthias Ringwald #endif
21558abbe8b5SMatthias Ringwald 
215671de195eSMatthias Ringwald static void hci_state_reset(void){
2157595bdbfbS[email protected]     // no connections yet
2158595bdbfbS[email protected]     hci_stack->connections = NULL;
215974308b23Smatthias.ringwald 
216074308b23Smatthias.ringwald     // keep discoverable/connectable as this has been requested by the client(s)
216174308b23Smatthias.ringwald     // hci_stack->discoverable = 0;
216274308b23Smatthias.ringwald     // hci_stack->connectable = 0;
216374308b23Smatthias.ringwald     // hci_stack->bondable = 1;
2164b95a5a35SMatthias Ringwald     // hci_stack->own_addr_type = 0;
2165595bdbfbS[email protected] 
216644935e40S[email protected]     // buffer is free
216744935e40S[email protected]     hci_stack->hci_packet_buffer_reserved = 0;
216844935e40S[email protected] 
2169595bdbfbS[email protected]     // no pending cmds
2170595bdbfbS[email protected]     hci_stack->decline_reason = 0;
2171595bdbfbS[email protected]     hci_stack->new_scan_enable_value = 0xff;
2172595bdbfbS[email protected] 
2173595bdbfbS[email protected]     // LE
2174b95a5a35SMatthias Ringwald #ifdef ENABLE_BLE
2175b95a5a35SMatthias Ringwald     memset(hci_stack->le_random_address, 0, 6);
2176b95a5a35SMatthias Ringwald     hci_stack->le_random_address_set = 0;
2177d70217a2SMatthias Ringwald #endif
2178d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
2179595bdbfbS[email protected]     hci_stack->le_scanning_state = LE_SCAN_IDLE;
2180e2602ea2Smatthias.ringwald     hci_stack->le_scan_type = 0xff;
2181b04dfa37SMatthias Ringwald     hci_stack->le_connecting_state = LE_CONNECTING_IDLE;
2182e83201bcSMatthias Ringwald     hci_stack->le_whitelist = 0;
2183e83201bcSMatthias Ringwald     hci_stack->le_whitelist_capacity = 0;
2184d70217a2SMatthias Ringwald #endif
2185d70217a2SMatthias Ringwald 
2186e21192abSMatthias Ringwald     hci_stack->le_connection_parameter_range.le_conn_interval_min =          6;
2187e21192abSMatthias Ringwald     hci_stack->le_connection_parameter_range.le_conn_interval_max =       3200;
2188e21192abSMatthias Ringwald     hci_stack->le_connection_parameter_range.le_conn_latency_min =           0;
2189e21192abSMatthias Ringwald     hci_stack->le_connection_parameter_range.le_conn_latency_max =         500;
2190e21192abSMatthias Ringwald     hci_stack->le_connection_parameter_range.le_supervision_timeout_min =   10;
2191e21192abSMatthias Ringwald     hci_stack->le_connection_parameter_range.le_supervision_timeout_max = 3200;
2192595bdbfbS[email protected] }
2193595bdbfbS[email protected] 
219435454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
21952d5e09d6SMatthias Ringwald /**
21962d5e09d6SMatthias Ringwald  * @brief Configure Bluetooth hardware control. Has to be called before power on.
21972d5e09d6SMatthias Ringwald  */
21982d5e09d6SMatthias Ringwald void hci_set_link_key_db(btstack_link_key_db_t const * link_key_db){
21992d5e09d6SMatthias Ringwald     // store and open remote device db
22002d5e09d6SMatthias Ringwald     hci_stack->link_key_db = link_key_db;
22012d5e09d6SMatthias Ringwald     if (hci_stack->link_key_db) {
22022d5e09d6SMatthias Ringwald         hci_stack->link_key_db->open();
22032d5e09d6SMatthias Ringwald     }
22042d5e09d6SMatthias Ringwald }
220535454696SMatthias Ringwald #endif
22062d5e09d6SMatthias Ringwald 
22072d5e09d6SMatthias Ringwald void hci_init(const hci_transport_t *transport, const void *config){
2208475c8125Smatthias.ringwald 
22093a9fb326S[email protected] #ifdef HAVE_MALLOC
22103a9fb326S[email protected]     if (!hci_stack) {
22113a9fb326S[email protected]         hci_stack = (hci_stack_t*) malloc(sizeof(hci_stack_t));
22123a9fb326S[email protected]     }
22133a9fb326S[email protected] #else
22143a9fb326S[email protected]     hci_stack = &hci_stack_static;
22153a9fb326S[email protected] #endif
221666fb9560S[email protected]     memset(hci_stack, 0, sizeof(hci_stack_t));
22173a9fb326S[email protected] 
2218475c8125Smatthias.ringwald     // reference to use transport layer implementation
22193a9fb326S[email protected]     hci_stack->hci_transport = transport;
2220475c8125Smatthias.ringwald 
222111e23e5fSmatthias.ringwald     // reference to used config
22223a9fb326S[email protected]     hci_stack->config = config;
222311e23e5fSmatthias.ringwald 
222426a9b6daSMatthias Ringwald     // setup pointer for outgoing packet buffer
222526a9b6daSMatthias Ringwald     hci_stack->hci_packet_buffer = &hci_stack->hci_packet_buffer_data[HCI_OUTGOING_PRE_BUFFER_SIZE];
222626a9b6daSMatthias Ringwald 
22278fcba05dSmatthias.ringwald     // max acl payload size defined in config.h
22283a9fb326S[email protected]     hci_stack->acl_data_packet_length = HCI_ACL_PAYLOAD_SIZE;
22298fcba05dSmatthias.ringwald 
223016833f0aSmatthias.ringwald     // register packet handlers with transport
223110e830c9Smatthias.ringwald     transport->register_packet_handler(&packet_handler);
2232f5454fc6Smatthias.ringwald 
22333a9fb326S[email protected]     hci_stack->state = HCI_STATE_OFF;
2234e2386ba1S[email protected] 
2235e2386ba1S[email protected]     // class of device
22363a9fb326S[email protected]     hci_stack->class_of_device = 0x007a020c; // Smartphone
2237a45d6b9fS[email protected] 
2238f20168b8Smatthias.ringwald     // bondable by default
2239f20168b8Smatthias.ringwald     hci_stack->bondable = 1;
2240f20168b8Smatthias.ringwald 
224163048403S[email protected]     // Secure Simple Pairing default: enable, no I/O capabilities, general bonding, mitm not required, auto accept
22423a9fb326S[email protected]     hci_stack->ssp_enable = 1;
22433a9fb326S[email protected]     hci_stack->ssp_io_capability = SSP_IO_CAPABILITY_NO_INPUT_NO_OUTPUT;
22443a9fb326S[email protected]     hci_stack->ssp_authentication_requirement = SSP_IO_AUTHREQ_MITM_PROTECTION_NOT_REQUIRED_GENERAL_BONDING;
22453a9fb326S[email protected]     hci_stack->ssp_auto_accept = 1;
224669a97523S[email protected] 
2247fac2e2feSMatthias Ringwald     // voice setting - signed 16 bit pcm data with CVSD over the air
2248fac2e2feSMatthias Ringwald     hci_stack->sco_voice_setting = 0x60;
2249d950d659SMatthias Ringwald 
2250595bdbfbS[email protected]     hci_state_reset();
2251475c8125Smatthias.ringwald }
2252475c8125Smatthias.ringwald 
22533fb36a29SMatthias Ringwald /**
22543fb36a29SMatthias Ringwald  * @brief Configure Bluetooth chipset driver. Has to be called before power on, or right after receiving the local version information
22553fb36a29SMatthias Ringwald  */
22563fb36a29SMatthias Ringwald void hci_set_chipset(const btstack_chipset_t *chipset_driver){
22573fb36a29SMatthias Ringwald     hci_stack->chipset = chipset_driver;
22583fb36a29SMatthias Ringwald 
22593fb36a29SMatthias Ringwald     // reset chipset driver - init is also called on power_up
22603fb36a29SMatthias Ringwald     if (hci_stack->chipset && hci_stack->chipset->init){
22613fb36a29SMatthias Ringwald         hci_stack->chipset->init(hci_stack->config);
22623fb36a29SMatthias Ringwald     }
22633fb36a29SMatthias Ringwald }
22643fb36a29SMatthias Ringwald 
2265fb55bd0aSMatthias Ringwald /**
2266d0b87befSMatthias Ringwald  * @brief Configure Bluetooth hardware control. Has to be called after hci_init() but before power on.
2267fb55bd0aSMatthias Ringwald  */
2268fb55bd0aSMatthias Ringwald void hci_set_control(const btstack_control_t *hardware_control){
2269fb55bd0aSMatthias Ringwald     // references to used control implementation
2270fb55bd0aSMatthias Ringwald     hci_stack->control = hardware_control;
2271d0b87befSMatthias Ringwald     // init with transport config
2272d0b87befSMatthias Ringwald     hardware_control->init(hci_stack->config);
2273fb55bd0aSMatthias Ringwald }
2274fb55bd0aSMatthias Ringwald 
227571de195eSMatthias Ringwald void hci_close(void){
2276404843c1Smatthias.ringwald     // close remote device db
2277a98592bcSMatthias Ringwald     if (hci_stack->link_key_db) {
2278a98592bcSMatthias Ringwald         hci_stack->link_key_db->close();
2279404843c1Smatthias.ringwald     }
22807224be7eSMatthias Ringwald 
22817224be7eSMatthias Ringwald     btstack_linked_list_iterator_t lit;
22827224be7eSMatthias Ringwald     btstack_linked_list_iterator_init(&lit, &hci_stack->connections);
22837224be7eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&lit)){
22847224be7eSMatthias Ringwald         // cancel all l2cap connections by emitting dicsconnection complete before shutdown (free) connection
22857224be7eSMatthias Ringwald         hci_connection_t * connection = (hci_connection_t*) btstack_linked_list_iterator_next(&lit);
22867224be7eSMatthias Ringwald         hci_emit_disconnection_complete(connection->con_handle, 0x16); // terminated by local host
22877224be7eSMatthias Ringwald         hci_shutdown_connection(connection);
2288f5454fc6Smatthias.ringwald     }
22897224be7eSMatthias Ringwald 
2290f5454fc6Smatthias.ringwald     hci_power_control(HCI_POWER_OFF);
22913a9fb326S[email protected] 
22923a9fb326S[email protected] #ifdef HAVE_MALLOC
22933a9fb326S[email protected]     free(hci_stack);
22943a9fb326S[email protected] #endif
22953a9fb326S[email protected]     hci_stack = NULL;
2296404843c1Smatthias.ringwald }
2297404843c1Smatthias.ringwald 
229835454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
229960b9e82fSMatthias Ringwald void gap_set_class_of_device(uint32_t class_of_device){
23009e61646fS[email protected]     hci_stack->class_of_device = class_of_device;
23019e61646fS[email protected] }
230276f27cffSMatthias Ringwald 
230376f27cffSMatthias Ringwald void hci_disable_l2cap_timeout_check(void){
230476f27cffSMatthias Ringwald     disable_l2cap_timeouts = 1;
230576f27cffSMatthias Ringwald }
230635454696SMatthias Ringwald #endif
23079e61646fS[email protected] 
230876f27cffSMatthias Ringwald #if !defined(HAVE_PLATFORM_IPHONE_OS) && !defined (HAVE_HOST_CONTROLLER_API)
2309f456b2d0S[email protected] // Set Public BD ADDR - passed on to Bluetooth chipset if supported in bt_control_h
2310f456b2d0S[email protected] void hci_set_bd_addr(bd_addr_t addr){
2311f456b2d0S[email protected]     memcpy(hci_stack->custom_bd_addr, addr, 6);
2312f456b2d0S[email protected]     hci_stack->custom_bd_addr_set = 1;
2313f456b2d0S[email protected] }
231476f27cffSMatthias Ringwald #endif
2315f456b2d0S[email protected] 
23168d213e1aSmatthias.ringwald // State-Module-Driver overview
23178d213e1aSmatthias.ringwald // state                    module  low-level
23188d213e1aSmatthias.ringwald // HCI_STATE_OFF             off      close
23198d213e1aSmatthias.ringwald // HCI_STATE_INITIALIZING,   on       open
23208d213e1aSmatthias.ringwald // HCI_STATE_WORKING,        on       open
23218d213e1aSmatthias.ringwald // HCI_STATE_HALTING,        on       open
2322d661ed19Smatthias.ringwald // HCI_STATE_SLEEPING,    off/sleep   close
2323d661ed19Smatthias.ringwald // HCI_STATE_FALLING_ASLEEP  on       open
2324c7e0c5f6Smatthias.ringwald 
232540d1c7a4Smatthias.ringwald static int hci_power_control_on(void){
23267301ad89Smatthias.ringwald 
2327038bc64cSmatthias.ringwald     // power on
2328f9a30166Smatthias.ringwald     int err = 0;
23293a9fb326S[email protected]     if (hci_stack->control && hci_stack->control->on){
2330d0b87befSMatthias Ringwald         err = (*hci_stack->control->on)();
2331f9a30166Smatthias.ringwald     }
2332038bc64cSmatthias.ringwald     if (err){
23339da54300S[email protected]         log_error( "POWER_ON failed");
2334038bc64cSmatthias.ringwald         hci_emit_hci_open_failed();
2335038bc64cSmatthias.ringwald         return err;
2336038bc64cSmatthias.ringwald     }
2337038bc64cSmatthias.ringwald 
233824b3c629SMatthias Ringwald     // int chipset driver
23393fb36a29SMatthias Ringwald     if (hci_stack->chipset && hci_stack->chipset->init){
23403fb36a29SMatthias Ringwald         hci_stack->chipset->init(hci_stack->config);
23413fb36a29SMatthias Ringwald     }
23423fb36a29SMatthias Ringwald 
234324b3c629SMatthias Ringwald     // init transport
234424b3c629SMatthias Ringwald     if (hci_stack->hci_transport->init){
234524b3c629SMatthias Ringwald         hci_stack->hci_transport->init(hci_stack->config);
234624b3c629SMatthias Ringwald     }
234724b3c629SMatthias Ringwald 
234824b3c629SMatthias Ringwald     // open transport
234924b3c629SMatthias Ringwald     err = hci_stack->hci_transport->open();
2350038bc64cSmatthias.ringwald     if (err){
23519da54300S[email protected]         log_error( "HCI_INIT failed, turning Bluetooth off again");
23523a9fb326S[email protected]         if (hci_stack->control && hci_stack->control->off){
2353d0b87befSMatthias Ringwald             (*hci_stack->control->off)();
2354f9a30166Smatthias.ringwald         }
2355038bc64cSmatthias.ringwald         hci_emit_hci_open_failed();
2356038bc64cSmatthias.ringwald         return err;
2357038bc64cSmatthias.ringwald     }
23588d213e1aSmatthias.ringwald     return 0;
23598d213e1aSmatthias.ringwald }
2360038bc64cSmatthias.ringwald 
236140d1c7a4Smatthias.ringwald static void hci_power_control_off(void){
23628d213e1aSmatthias.ringwald 
23639da54300S[email protected]     log_info("hci_power_control_off");
23649418f9c9Smatthias.ringwald 
23658d213e1aSmatthias.ringwald     // close low-level device
236624b3c629SMatthias Ringwald     hci_stack->hci_transport->close();
23678d213e1aSmatthias.ringwald 
23689da54300S[email protected]     log_info("hci_power_control_off - hci_transport closed");
23699418f9c9Smatthias.ringwald 
23708d213e1aSmatthias.ringwald     // power off
23713a9fb326S[email protected]     if (hci_stack->control && hci_stack->control->off){
2372d0b87befSMatthias Ringwald         (*hci_stack->control->off)();
23738d213e1aSmatthias.ringwald     }
23749418f9c9Smatthias.ringwald 
23759da54300S[email protected]     log_info("hci_power_control_off - control closed");
23769418f9c9Smatthias.ringwald 
23773a9fb326S[email protected]     hci_stack->state = HCI_STATE_OFF;
237872ea5239Smatthias.ringwald }
237972ea5239Smatthias.ringwald 
238040d1c7a4Smatthias.ringwald static void hci_power_control_sleep(void){
238172ea5239Smatthias.ringwald 
23829da54300S[email protected]     log_info("hci_power_control_sleep");
23833144bce4Smatthias.ringwald 
2384b429b9b7Smatthias.ringwald #if 0
2385b429b9b7Smatthias.ringwald     // don't close serial port during sleep
2386b429b9b7Smatthias.ringwald 
238772ea5239Smatthias.ringwald     // close low-level device
23883a9fb326S[email protected]     hci_stack->hci_transport->close(hci_stack->config);
2389b429b9b7Smatthias.ringwald #endif
239072ea5239Smatthias.ringwald 
239172ea5239Smatthias.ringwald     // sleep mode
23923a9fb326S[email protected]     if (hci_stack->control && hci_stack->control->sleep){
2393d0b87befSMatthias Ringwald         (*hci_stack->control->sleep)();
239472ea5239Smatthias.ringwald     }
2395b429b9b7Smatthias.ringwald 
23963a9fb326S[email protected]     hci_stack->state = HCI_STATE_SLEEPING;
23978d213e1aSmatthias.ringwald }
23988d213e1aSmatthias.ringwald 
239940d1c7a4Smatthias.ringwald static int hci_power_control_wake(void){
2400b429b9b7Smatthias.ringwald 
24019da54300S[email protected]     log_info("hci_power_control_wake");
2402b429b9b7Smatthias.ringwald 
2403b429b9b7Smatthias.ringwald     // wake on
24043a9fb326S[email protected]     if (hci_stack->control && hci_stack->control->wake){
2405d0b87befSMatthias Ringwald         (*hci_stack->control->wake)();
2406b429b9b7Smatthias.ringwald     }
2407b429b9b7Smatthias.ringwald 
2408b429b9b7Smatthias.ringwald #if 0
2409b429b9b7Smatthias.ringwald     // open low-level device
24103a9fb326S[email protected]     int err = hci_stack->hci_transport->open(hci_stack->config);
2411b429b9b7Smatthias.ringwald     if (err){
24129da54300S[email protected]         log_error( "HCI_INIT failed, turning Bluetooth off again");
24133a9fb326S[email protected]         if (hci_stack->control && hci_stack->control->off){
2414d0b87befSMatthias Ringwald             (*hci_stack->control->off)();
2415b429b9b7Smatthias.ringwald         }
2416b429b9b7Smatthias.ringwald         hci_emit_hci_open_failed();
2417b429b9b7Smatthias.ringwald         return err;
2418b429b9b7Smatthias.ringwald     }
2419b429b9b7Smatthias.ringwald #endif
2420b429b9b7Smatthias.ringwald 
2421b429b9b7Smatthias.ringwald     return 0;
2422b429b9b7Smatthias.ringwald }
2423b429b9b7Smatthias.ringwald 
242444935e40S[email protected] static void hci_power_transition_to_initializing(void){
242544935e40S[email protected]     // set up state machine
242644935e40S[email protected]     hci_stack->num_cmd_packets = 1; // assume that one cmd can be sent
242744935e40S[email protected]     hci_stack->hci_packet_buffer_reserved = 0;
242844935e40S[email protected]     hci_stack->state = HCI_STATE_INITIALIZING;
24295c363727SMatthias Ringwald     hci_stack->substate = HCI_INIT_SEND_RESET;
243044935e40S[email protected] }
2431b429b9b7Smatthias.ringwald 
24328d213e1aSmatthias.ringwald int hci_power_control(HCI_POWER_MODE power_mode){
2433d661ed19Smatthias.ringwald 
2434f04a0c31SMatthias Ringwald     log_info("hci_power_control: %d, current mode %u", power_mode, hci_stack->state);
2435d661ed19Smatthias.ringwald 
24368d213e1aSmatthias.ringwald     int err = 0;
24373a9fb326S[email protected]     switch (hci_stack->state){
24388d213e1aSmatthias.ringwald 
24398d213e1aSmatthias.ringwald         case HCI_STATE_OFF:
24408d213e1aSmatthias.ringwald             switch (power_mode){
24418d213e1aSmatthias.ringwald                 case HCI_POWER_ON:
24428d213e1aSmatthias.ringwald                     err = hci_power_control_on();
244397b61c7bS[email protected]                     if (err) {
2444f04a0c31SMatthias Ringwald                         log_error("hci_power_control_on() error %d", err);
244597b61c7bS[email protected]                         return err;
244697b61c7bS[email protected]                     }
244744935e40S[email protected]                     hci_power_transition_to_initializing();
24488d213e1aSmatthias.ringwald                     break;
24498d213e1aSmatthias.ringwald                 case HCI_POWER_OFF:
24508d213e1aSmatthias.ringwald                     // do nothing
24518d213e1aSmatthias.ringwald                     break;
24528d213e1aSmatthias.ringwald                 case HCI_POWER_SLEEP:
2453b546ac54Smatthias.ringwald                     // do nothing (with SLEEP == OFF)
24548d213e1aSmatthias.ringwald                     break;
24558d213e1aSmatthias.ringwald             }
24568d213e1aSmatthias.ringwald             break;
24577301ad89Smatthias.ringwald 
24588d213e1aSmatthias.ringwald         case HCI_STATE_INITIALIZING:
24598d213e1aSmatthias.ringwald             switch (power_mode){
24608d213e1aSmatthias.ringwald                 case HCI_POWER_ON:
24618d213e1aSmatthias.ringwald                     // do nothing
24628d213e1aSmatthias.ringwald                     break;
24638d213e1aSmatthias.ringwald                 case HCI_POWER_OFF:
24648d213e1aSmatthias.ringwald                     // no connections yet, just turn it off
24658d213e1aSmatthias.ringwald                     hci_power_control_off();
24668d213e1aSmatthias.ringwald                     break;
24678d213e1aSmatthias.ringwald                 case HCI_POWER_SLEEP:
2468b546ac54Smatthias.ringwald                     // no connections yet, just turn it off
246972ea5239Smatthias.ringwald                     hci_power_control_sleep();
24708d213e1aSmatthias.ringwald                     break;
24718d213e1aSmatthias.ringwald             }
24728d213e1aSmatthias.ringwald             break;
24737301ad89Smatthias.ringwald 
24748d213e1aSmatthias.ringwald         case HCI_STATE_WORKING:
24758d213e1aSmatthias.ringwald             switch (power_mode){
24768d213e1aSmatthias.ringwald                 case HCI_POWER_ON:
24778d213e1aSmatthias.ringwald                     // do nothing
24788d213e1aSmatthias.ringwald                     break;
24798d213e1aSmatthias.ringwald                 case HCI_POWER_OFF:
2480c7e0c5f6Smatthias.ringwald                     // see hci_run
24813a9fb326S[email protected]                     hci_stack->state = HCI_STATE_HALTING;
24828d213e1aSmatthias.ringwald                     break;
24838d213e1aSmatthias.ringwald                 case HCI_POWER_SLEEP:
2484b546ac54Smatthias.ringwald                     // see hci_run
24853a9fb326S[email protected]                     hci_stack->state = HCI_STATE_FALLING_ASLEEP;
248674b323a9SMatthias Ringwald                     hci_stack->substate = HCI_FALLING_ASLEEP_DISCONNECT;
24878d213e1aSmatthias.ringwald                     break;
24888d213e1aSmatthias.ringwald             }
24898d213e1aSmatthias.ringwald             break;
24907301ad89Smatthias.ringwald 
24918d213e1aSmatthias.ringwald         case HCI_STATE_HALTING:
24928d213e1aSmatthias.ringwald             switch (power_mode){
24938d213e1aSmatthias.ringwald                 case HCI_POWER_ON:
249444935e40S[email protected]                     hci_power_transition_to_initializing();
24958d213e1aSmatthias.ringwald                     break;
24968d213e1aSmatthias.ringwald                 case HCI_POWER_OFF:
24978d213e1aSmatthias.ringwald                     // do nothing
24988d213e1aSmatthias.ringwald                     break;
24998d213e1aSmatthias.ringwald                 case HCI_POWER_SLEEP:
2500b546ac54Smatthias.ringwald                     // see hci_run
25013a9fb326S[email protected]                     hci_stack->state = HCI_STATE_FALLING_ASLEEP;
250274b323a9SMatthias Ringwald                     hci_stack->substate = HCI_FALLING_ASLEEP_DISCONNECT;
25038d213e1aSmatthias.ringwald                     break;
25048d213e1aSmatthias.ringwald             }
25058d213e1aSmatthias.ringwald             break;
25068d213e1aSmatthias.ringwald 
25078d213e1aSmatthias.ringwald         case HCI_STATE_FALLING_ASLEEP:
25088d213e1aSmatthias.ringwald             switch (power_mode){
25098d213e1aSmatthias.ringwald                 case HCI_POWER_ON:
251028171530Smatthias.ringwald 
2511423a3e49SMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
251228171530Smatthias.ringwald                     // nothing to do, if H4 supports power management
2513d0b87befSMatthias Ringwald                     if (btstack_control_iphone_power_management_enabled()){
25143a9fb326S[email protected]                         hci_stack->state = HCI_STATE_INITIALIZING;
251574b323a9SMatthias Ringwald                         hci_stack->substate = HCI_INIT_WRITE_SCAN_ENABLE;   // init after sleep
251628171530Smatthias.ringwald                         break;
251728171530Smatthias.ringwald                     }
251828171530Smatthias.ringwald #endif
251944935e40S[email protected]                     hci_power_transition_to_initializing();
25208d213e1aSmatthias.ringwald                     break;
25218d213e1aSmatthias.ringwald                 case HCI_POWER_OFF:
2522b546ac54Smatthias.ringwald                     // see hci_run
25233a9fb326S[email protected]                     hci_stack->state = HCI_STATE_HALTING;
25248d213e1aSmatthias.ringwald                     break;
25258d213e1aSmatthias.ringwald                 case HCI_POWER_SLEEP:
2526b546ac54Smatthias.ringwald                     // do nothing
25278d213e1aSmatthias.ringwald                     break;
25288d213e1aSmatthias.ringwald             }
25298d213e1aSmatthias.ringwald             break;
25308d213e1aSmatthias.ringwald 
25318d213e1aSmatthias.ringwald         case HCI_STATE_SLEEPING:
25328d213e1aSmatthias.ringwald             switch (power_mode){
25338d213e1aSmatthias.ringwald                 case HCI_POWER_ON:
253428171530Smatthias.ringwald 
2535423a3e49SMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
253628171530Smatthias.ringwald                     // nothing to do, if H4 supports power management
2537d0b87befSMatthias Ringwald                     if (btstack_control_iphone_power_management_enabled()){
25383a9fb326S[email protected]                         hci_stack->state = HCI_STATE_INITIALIZING;
25395c363727SMatthias Ringwald                         hci_stack->substate = HCI_INIT_AFTER_SLEEP;
2540758b46ceSmatthias.ringwald                         hci_update_scan_enable();
254128171530Smatthias.ringwald                         break;
254228171530Smatthias.ringwald                     }
254328171530Smatthias.ringwald #endif
25443144bce4Smatthias.ringwald                     err = hci_power_control_wake();
25453144bce4Smatthias.ringwald                     if (err) return err;
254644935e40S[email protected]                     hci_power_transition_to_initializing();
25478d213e1aSmatthias.ringwald                     break;
25488d213e1aSmatthias.ringwald                 case HCI_POWER_OFF:
25493a9fb326S[email protected]                     hci_stack->state = HCI_STATE_HALTING;
25508d213e1aSmatthias.ringwald                     break;
25518d213e1aSmatthias.ringwald                 case HCI_POWER_SLEEP:
2552b546ac54Smatthias.ringwald                     // do nothing
25538d213e1aSmatthias.ringwald                     break;
25548d213e1aSmatthias.ringwald             }
25558d213e1aSmatthias.ringwald             break;
255611e23e5fSmatthias.ringwald     }
255768d92d03Smatthias.ringwald 
2558038bc64cSmatthias.ringwald     // create internal event
2559ee8bf225Smatthias.ringwald 	hci_emit_state();
2560ee8bf225Smatthias.ringwald 
256168d92d03Smatthias.ringwald 	// trigger next/first action
256268d92d03Smatthias.ringwald 	hci_run();
256368d92d03Smatthias.ringwald 
2564475c8125Smatthias.ringwald     return 0;
2565475c8125Smatthias.ringwald }
2566475c8125Smatthias.ringwald 
256735454696SMatthias Ringwald 
256835454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
256935454696SMatthias Ringwald 
2570758b46ceSmatthias.ringwald static void hci_update_scan_enable(void){
2571758b46ceSmatthias.ringwald     // 2 = page scan, 1 = inq scan
25723a9fb326S[email protected]     hci_stack->new_scan_enable_value  = hci_stack->connectable << 1 | hci_stack->discoverable;
2573758b46ceSmatthias.ringwald     hci_run();
2574758b46ceSmatthias.ringwald }
2575758b46ceSmatthias.ringwald 
257615a95bd5SMatthias Ringwald void gap_discoverable_control(uint8_t enable){
2577381fbed8Smatthias.ringwald     if (enable) enable = 1; // normalize argument
2578381fbed8Smatthias.ringwald 
25793a9fb326S[email protected]     if (hci_stack->discoverable == enable){
25803a9fb326S[email protected]         hci_emit_discoverable_enabled(hci_stack->discoverable);
2581381fbed8Smatthias.ringwald         return;
2582381fbed8Smatthias.ringwald     }
2583381fbed8Smatthias.ringwald 
25843a9fb326S[email protected]     hci_stack->discoverable = enable;
2585758b46ceSmatthias.ringwald     hci_update_scan_enable();
2586758b46ceSmatthias.ringwald }
2587b031bebbSmatthias.ringwald 
258815a95bd5SMatthias Ringwald void gap_connectable_control(uint8_t enable){
2589758b46ceSmatthias.ringwald     if (enable) enable = 1; // normalize argument
2590758b46ceSmatthias.ringwald 
2591758b46ceSmatthias.ringwald     // don't emit event
25923a9fb326S[email protected]     if (hci_stack->connectable == enable) return;
2593758b46ceSmatthias.ringwald 
25943a9fb326S[email protected]     hci_stack->connectable = enable;
2595758b46ceSmatthias.ringwald     hci_update_scan_enable();
2596381fbed8Smatthias.ringwald }
259735454696SMatthias Ringwald #endif
2598381fbed8Smatthias.ringwald 
259915a95bd5SMatthias Ringwald void gap_local_bd_addr(bd_addr_t address_buffer){
2600690bd0baS[email protected]     memcpy(address_buffer, hci_stack->local_bd_addr, 6);
26015061f3afS[email protected] }
26025061f3afS[email protected] 
260395d71764SMatthias Ringwald static void hci_run(void){
26048a485f27Smatthias.ringwald 
2605db8bc6ffSMatthias Ringwald     // log_info("hci_run: entered");
2606665d90f2SMatthias Ringwald     btstack_linked_item_t * it;
260732ab9390Smatthias.ringwald 
2608b5d8b22bS[email protected]     // send continuation fragments first, as they block the prepared packet buffer
2609b5d8b22bS[email protected]     if (hci_stack->acl_fragmentation_total_size > 0) {
2610b5d8b22bS[email protected]         hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(hci_stack->hci_packet_buffer);
2611b5d8b22bS[email protected]         hci_connection_t *connection = hci_connection_for_handle(con_handle);
2612b5d8b22bS[email protected]         if (connection) {
261328a0332dSMatthias Ringwald             if (hci_can_send_prepared_acl_packet_now(con_handle)){
2614b5d8b22bS[email protected]                 hci_send_acl_packet_fragments(connection);
2615b5d8b22bS[email protected]                 return;
2616b5d8b22bS[email protected]             }
261728a0332dSMatthias Ringwald         } else {
2618b5d8b22bS[email protected]             // connection gone -> discard further fragments
261928a0332dSMatthias Ringwald             log_info("hci_run: fragmented ACL packet no connection -> discard fragment");
2620b5d8b22bS[email protected]             hci_stack->acl_fragmentation_total_size = 0;
2621b5d8b22bS[email protected]             hci_stack->acl_fragmentation_pos = 0;
2622b5d8b22bS[email protected]         }
2623b5d8b22bS[email protected]     }
2624b5d8b22bS[email protected] 
2625d94d3cafS[email protected]     if (!hci_can_send_command_packet_now()) return;
2626ce4c8fabSmatthias.ringwald 
2627b031bebbSmatthias.ringwald     // global/non-connection oriented commands
2628b031bebbSmatthias.ringwald 
262935454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
2630b031bebbSmatthias.ringwald     // decline incoming connections
26313a9fb326S[email protected]     if (hci_stack->decline_reason){
26323a9fb326S[email protected]         uint8_t reason = hci_stack->decline_reason;
26333a9fb326S[email protected]         hci_stack->decline_reason = 0;
26343a9fb326S[email protected]         hci_send_cmd(&hci_reject_connection_request, hci_stack->decline_addr, reason);
2635dbe1a790S[email protected]         return;
2636ce4c8fabSmatthias.ringwald     }
2637ce4c8fabSmatthias.ringwald 
2638b031bebbSmatthias.ringwald     // send scan enable
26393a9fb326S[email protected]     if (hci_stack->state == HCI_STATE_WORKING && hci_stack->new_scan_enable_value != 0xff && hci_classic_supported()){
26403a9fb326S[email protected]         hci_send_cmd(&hci_write_scan_enable, hci_stack->new_scan_enable_value);
26413a9fb326S[email protected]         hci_stack->new_scan_enable_value = 0xff;
2642dbe1a790S[email protected]         return;
2643b031bebbSmatthias.ringwald     }
264435454696SMatthias Ringwald #endif
2645b031bebbSmatthias.ringwald 
2646a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
2647b95a5a35SMatthias Ringwald     // advertisements, active scanning, and creating connections requires randaom address to be set if using private address
2648b95a5a35SMatthias Ringwald     if ((hci_stack->state == HCI_STATE_WORKING)
2649b95a5a35SMatthias Ringwald     && (hci_stack->le_own_addr_type == BD_ADDR_TYPE_LE_PUBLIC || hci_stack->le_random_address_set)){
2650d70217a2SMatthias Ringwald 
2651d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
265245c102fdSMatthias Ringwald         // handle le scan
26537bdc6798S[email protected]         switch(hci_stack->le_scanning_state){
26547bdc6798S[email protected]             case LE_START_SCAN:
26557bdc6798S[email protected]                 hci_stack->le_scanning_state = LE_SCANNING;
26567bdc6798S[email protected]                 hci_send_cmd(&hci_le_set_scan_enable, 1, 0);
26577bdc6798S[email protected]                 return;
26587bdc6798S[email protected] 
26597bdc6798S[email protected]             case LE_STOP_SCAN:
26607bdc6798S[email protected]                 hci_stack->le_scanning_state = LE_SCAN_IDLE;
26617bdc6798S[email protected]                 hci_send_cmd(&hci_le_set_scan_enable, 0, 0);
26627bdc6798S[email protected]                 return;
26637bdc6798S[email protected]             default:
26647bdc6798S[email protected]                 break;
26657bdc6798S[email protected]         }
2666e2602ea2Smatthias.ringwald         if (hci_stack->le_scan_type != 0xff){
2667e2602ea2Smatthias.ringwald             // defaults: active scanning, accept all advertisement packets
2668e2602ea2Smatthias.ringwald             int scan_type = hci_stack->le_scan_type;
2669e2602ea2Smatthias.ringwald             hci_stack->le_scan_type = 0xff;
2670b95a5a35SMatthias Ringwald             hci_send_cmd(&hci_le_set_scan_parameters, scan_type, hci_stack->le_scan_interval, hci_stack->le_scan_window, hci_stack->le_own_addr_type, 0);
2671e2602ea2Smatthias.ringwald             return;
2672e2602ea2Smatthias.ringwald         }
2673d70217a2SMatthias Ringwald #endif
2674d70217a2SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
267545c102fdSMatthias Ringwald         // le advertisement control
26769a2e4658SMatthias Ringwald         if (hci_stack->le_advertisements_todo){
26779a2e4658SMatthias Ringwald             log_info("hci_run: gap_le: adv todo: %x", hci_stack->le_advertisements_todo );
26789a2e4658SMatthias Ringwald         }
267945c102fdSMatthias Ringwald         if (hci_stack->le_advertisements_todo & LE_ADVERTISEMENT_TASKS_DISABLE){
268045c102fdSMatthias Ringwald             hci_stack->le_advertisements_todo &= ~LE_ADVERTISEMENT_TASKS_DISABLE;
268145c102fdSMatthias Ringwald             hci_send_cmd(&hci_le_set_advertise_enable, 0);
268245c102fdSMatthias Ringwald             return;
268345c102fdSMatthias Ringwald         }
268445c102fdSMatthias Ringwald         if (hci_stack->le_advertisements_todo & LE_ADVERTISEMENT_TASKS_SET_PARAMS){
268545c102fdSMatthias Ringwald             hci_stack->le_advertisements_todo &= ~LE_ADVERTISEMENT_TASKS_SET_PARAMS;
268645c102fdSMatthias Ringwald             hci_send_cmd(&hci_le_set_advertising_parameters,
268745c102fdSMatthias Ringwald                  hci_stack->le_advertisements_interval_min,
268845c102fdSMatthias Ringwald                  hci_stack->le_advertisements_interval_max,
268945c102fdSMatthias Ringwald                  hci_stack->le_advertisements_type,
2690b95a5a35SMatthias Ringwald                  hci_stack->le_own_addr_type,
269145c102fdSMatthias Ringwald                  hci_stack->le_advertisements_direct_address_type,
269245c102fdSMatthias Ringwald                  hci_stack->le_advertisements_direct_address,
269345c102fdSMatthias Ringwald                  hci_stack->le_advertisements_channel_map,
269445c102fdSMatthias Ringwald                  hci_stack->le_advertisements_filter_policy);
269545c102fdSMatthias Ringwald             return;
269645c102fdSMatthias Ringwald         }
2697501f56b3SMatthias Ringwald         if (hci_stack->le_advertisements_todo & LE_ADVERTISEMENT_TASKS_SET_ADV_DATA){
2698501f56b3SMatthias Ringwald             hci_stack->le_advertisements_todo &= ~LE_ADVERTISEMENT_TASKS_SET_ADV_DATA;
2699b95a5a35SMatthias Ringwald             hci_send_cmd(&hci_le_set_advertising_data, hci_stack->le_advertisements_data_len, hci_stack->le_advertisements_data);
270045c102fdSMatthias Ringwald             return;
270145c102fdSMatthias Ringwald         }
2702501f56b3SMatthias Ringwald         if (hci_stack->le_advertisements_todo & LE_ADVERTISEMENT_TASKS_SET_SCAN_DATA){
2703501f56b3SMatthias Ringwald             hci_stack->le_advertisements_todo &= ~LE_ADVERTISEMENT_TASKS_SET_SCAN_DATA;
2704501f56b3SMatthias Ringwald             hci_send_cmd(&hci_le_set_scan_response_data, hci_stack->le_scan_response_data_len,
2705501f56b3SMatthias Ringwald                 hci_stack->le_scan_response_data);
2706501f56b3SMatthias Ringwald             return;
2707501f56b3SMatthias Ringwald         }
2708b95a5a35SMatthias Ringwald         if (hci_stack->le_advertisements_todo & LE_ADVERTISEMENT_TASKS_ENABLE){
270945c102fdSMatthias Ringwald             hci_stack->le_advertisements_todo &= ~LE_ADVERTISEMENT_TASKS_ENABLE;
271045c102fdSMatthias Ringwald             hci_send_cmd(&hci_le_set_advertise_enable, 1);
271145c102fdSMatthias Ringwald             return;
271245c102fdSMatthias Ringwald         }
2713d70217a2SMatthias Ringwald #endif
27149956955bSMatthias Ringwald 
2715d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
27169956955bSMatthias Ringwald         //
27179956955bSMatthias Ringwald         // LE Whitelist Management
27189956955bSMatthias Ringwald         //
27199956955bSMatthias Ringwald 
27209956955bSMatthias Ringwald         // check if whitelist needs modification
2721665d90f2SMatthias Ringwald         btstack_linked_list_iterator_t lit;
27229956955bSMatthias Ringwald         int modification_pending = 0;
2723665d90f2SMatthias Ringwald         btstack_linked_list_iterator_init(&lit, &hci_stack->le_whitelist);
2724665d90f2SMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&lit)){
2725665d90f2SMatthias Ringwald             whitelist_entry_t * entry = (whitelist_entry_t*) btstack_linked_list_iterator_next(&lit);
27269956955bSMatthias Ringwald             if (entry->state & (LE_WHITELIST_REMOVE_FROM_CONTROLLER | LE_WHITELIST_ADD_TO_CONTROLLER)){
27279956955bSMatthias Ringwald                 modification_pending = 1;
27289956955bSMatthias Ringwald                 break;
27299956955bSMatthias Ringwald             }
27309956955bSMatthias Ringwald         }
273191915b0bSMatthias Ringwald 
27329956955bSMatthias Ringwald         if (modification_pending){
273391915b0bSMatthias Ringwald             // stop connnecting if modification pending
27349956955bSMatthias Ringwald             if (hci_stack->le_connecting_state != LE_CONNECTING_IDLE){
27359956955bSMatthias Ringwald                 hci_send_cmd(&hci_le_create_connection_cancel);
27369956955bSMatthias Ringwald                 return;
27379956955bSMatthias Ringwald             }
27389956955bSMatthias Ringwald 
27399956955bSMatthias Ringwald             // add/remove entries
2740665d90f2SMatthias Ringwald             btstack_linked_list_iterator_init(&lit, &hci_stack->le_whitelist);
2741665d90f2SMatthias Ringwald             while (btstack_linked_list_iterator_has_next(&lit)){
2742665d90f2SMatthias Ringwald                 whitelist_entry_t * entry = (whitelist_entry_t*) btstack_linked_list_iterator_next(&lit);
27439956955bSMatthias Ringwald                 if (entry->state & LE_WHITELIST_ADD_TO_CONTROLLER){
27449956955bSMatthias Ringwald                     entry->state = LE_WHITELIST_ON_CONTROLLER;
27459956955bSMatthias Ringwald                     hci_send_cmd(&hci_le_add_device_to_white_list, entry->address_type, entry->address);
27469956955bSMatthias Ringwald                     return;
27479956955bSMatthias Ringwald 
27489956955bSMatthias Ringwald                 }
27499956955bSMatthias Ringwald                 if (entry->state & LE_WHITELIST_REMOVE_FROM_CONTROLLER){
27509ecbe201SMatthias Ringwald                     bd_addr_t address;
27519ecbe201SMatthias Ringwald                     bd_addr_type_t address_type = entry->address_type;
27529ecbe201SMatthias Ringwald                     memcpy(address, entry->address, 6);
2753665d90f2SMatthias Ringwald                     btstack_linked_list_remove(&hci_stack->le_whitelist, (btstack_linked_item_t *) entry);
27549956955bSMatthias Ringwald                     btstack_memory_whitelist_entry_free(entry);
27559ecbe201SMatthias Ringwald                     hci_send_cmd(&hci_le_remove_device_from_white_list, address_type, address);
27569956955bSMatthias Ringwald                     return;
27579956955bSMatthias Ringwald                 }
27589956955bSMatthias Ringwald             }
275991915b0bSMatthias Ringwald         }
27609956955bSMatthias Ringwald 
27619956955bSMatthias Ringwald         // start connecting
276291915b0bSMatthias Ringwald         if ( hci_stack->le_connecting_state == LE_CONNECTING_IDLE &&
2763665d90f2SMatthias Ringwald             !btstack_linked_list_empty(&hci_stack->le_whitelist)){
27649956955bSMatthias Ringwald             bd_addr_t null_addr;
27659956955bSMatthias Ringwald             memset(null_addr, 0, 6);
27669956955bSMatthias Ringwald             hci_send_cmd(&hci_le_create_connection,
27679956955bSMatthias Ringwald                  0x0060,    // scan interval: 60 ms
27689956955bSMatthias Ringwald                  0x0030,    // scan interval: 30 ms
27699956955bSMatthias Ringwald                  1,         // use whitelist
27709956955bSMatthias Ringwald                  0,         // peer address type
27719956955bSMatthias Ringwald                  null_addr, // peer bd addr
2772b95a5a35SMatthias Ringwald                  hci_stack->le_own_addr_type, // our addr type:
27739956955bSMatthias Ringwald                  0x0008,    // conn interval min
27749956955bSMatthias Ringwald                  0x0018,    // conn interval max
27759956955bSMatthias Ringwald                  0,         // conn latency
27769956955bSMatthias Ringwald                  0x0048,    // supervision timeout
27779956955bSMatthias Ringwald                  0x0001,    // min ce length
27789956955bSMatthias Ringwald                  0x0001     // max ce length
27799956955bSMatthias Ringwald                  );
27809956955bSMatthias Ringwald             return;
27819956955bSMatthias Ringwald         }
2782d70217a2SMatthias Ringwald #endif
27837bdc6798S[email protected]     }
2784b2f949feS[email protected] #endif
27857bdc6798S[email protected] 
278632ab9390Smatthias.ringwald     // send pending HCI commands
2787665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) hci_stack->connections; it ; it = it->next){
278805ae8de3SMatthias Ringwald         hci_connection_t * connection = (hci_connection_t *) it;
278932ab9390Smatthias.ringwald 
27900bf6344aS[email protected]         switch(connection->state){
27910bf6344aS[email protected]             case SEND_CREATE_CONNECTION:
27924f3229d8S[email protected]                 switch(connection->address_type){
279335454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
27944f3229d8S[email protected]                     case BD_ADDR_TYPE_CLASSIC:
27959da54300S[email protected]                         log_info("sending hci_create_connection");
2796ad83dc6aS[email protected]                         hci_send_cmd(&hci_create_connection, connection->address, hci_usable_acl_packet_types(), 0, 0, 0, 1);
27974f3229d8S[email protected]                         break;
279835454696SMatthias Ringwald #endif
27994f3229d8S[email protected]                     default:
2800a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
2801d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
28029da54300S[email protected]                         log_info("sending hci_le_create_connection");
28034f3229d8S[email protected]                         hci_send_cmd(&hci_le_create_connection,
2804b2571179Smatthias.ringwald                                      0x0060,    // scan interval: 60 ms
2805b2571179Smatthias.ringwald                                      0x0030,    // scan interval: 30 ms
28064f3229d8S[email protected]                                      0,         // don't use whitelist
28074f3229d8S[email protected]                                      connection->address_type, // peer address type
28084f3229d8S[email protected]                                      connection->address,      // peer bd addr
2809b95a5a35SMatthias Ringwald                                      hci_stack->le_own_addr_type,  // our addr type:
2810b2571179Smatthias.ringwald                                      0x0008,    // conn interval min
2811b2571179Smatthias.ringwald                                      0x0018,    // conn interval max
28124f3229d8S[email protected]                                      0,         // conn latency
2813b2571179Smatthias.ringwald                                      0x0048,    // supervision timeout
2814b2571179Smatthias.ringwald                                      0x0001,    // min ce length
2815b2571179Smatthias.ringwald                                      0x0001     // max ce length
28164f3229d8S[email protected]                                      );
28174f3229d8S[email protected] 
28184f3229d8S[email protected]                         connection->state = SENT_CREATE_CONNECTION;
2819b2f949feS[email protected] #endif
2820d70217a2SMatthias Ringwald #endif
28214f3229d8S[email protected]                         break;
28224f3229d8S[email protected]                 }
2823ad83dc6aS[email protected]                 return;
2824ad83dc6aS[email protected] 
282535454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
28260bf6344aS[email protected]             case RECEIVED_CONNECTION_REQUEST:
282794e4aaa2SMatthias Ringwald                 log_info("sending hci_accept_connection_request, remote eSCO %u", connection->remote_supported_feature_eSCO);
282832ab9390Smatthias.ringwald                 connection->state = ACCEPTED_CONNECTION_REQUEST;
28295cf766e8SMatthias Ringwald                 connection->role  = HCI_ROLE_SLAVE;
2830e35edcc1S[email protected]                 if (connection->address_type == BD_ADDR_TYPE_CLASSIC){
283134d2123cS[email protected]                     hci_send_cmd(&hci_accept_connection_request, connection->address, 1);
2832e35edcc1S[email protected]                 }
2833dbe1a790S[email protected]                 return;
283435454696SMatthias Ringwald #endif
28350bf6344aS[email protected] 
2836a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
2837d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
28380bf6344aS[email protected]             case SEND_CANCEL_CONNECTION:
28390bf6344aS[email protected]                 connection->state = SENT_CANCEL_CONNECTION;
28400bf6344aS[email protected]                 hci_send_cmd(&hci_le_create_connection_cancel);
28410bf6344aS[email protected]                 return;
2842a6725849S[email protected] #endif
2843d70217a2SMatthias Ringwald #endif
28440bf6344aS[email protected]             case SEND_DISCONNECT:
28450bf6344aS[email protected]                 connection->state = SENT_DISCONNECT;
28467851196eSmatthias.ringwald                 hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13); // remote closed connection
28470bf6344aS[email protected]                 return;
28480bf6344aS[email protected] 
28490bf6344aS[email protected]             default:
28500bf6344aS[email protected]                 break;
2851c7e0c5f6Smatthias.ringwald         }
2852c7e0c5f6Smatthias.ringwald 
285335454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
285432ab9390Smatthias.ringwald         if (connection->authentication_flags & HANDLE_LINK_KEY_REQUEST){
28559da54300S[email protected]             log_info("responding to link key request");
285634d2123cS[email protected]             connectionClearAuthenticationFlags(connection, HANDLE_LINK_KEY_REQUEST);
285732ab9390Smatthias.ringwald             link_key_t link_key;
2858c77e8838S[email protected]             link_key_type_t link_key_type;
2859a98592bcSMatthias Ringwald             if ( hci_stack->link_key_db
2860a98592bcSMatthias Ringwald               && hci_stack->link_key_db->get_link_key(connection->address, link_key, &link_key_type)
286134d2123cS[email protected]               && gap_security_level_for_link_key_type(link_key_type) >= connection->requested_security_level){
28629ab95c90S[email protected]                connection->link_key_type = link_key_type;
286332ab9390Smatthias.ringwald                hci_send_cmd(&hci_link_key_request_reply, connection->address, &link_key);
286432ab9390Smatthias.ringwald             } else {
286532ab9390Smatthias.ringwald                hci_send_cmd(&hci_link_key_request_negative_reply, connection->address);
286632ab9390Smatthias.ringwald             }
2867dbe1a790S[email protected]             return;
286832ab9390Smatthias.ringwald         }
28691d6b20aeS[email protected] 
2870899283eaS[email protected]         if (connection->authentication_flags & DENY_PIN_CODE_REQUEST){
28719da54300S[email protected]             log_info("denying to pin request");
2872899283eaS[email protected]             connectionClearAuthenticationFlags(connection, DENY_PIN_CODE_REQUEST);
287334d2123cS[email protected]             hci_send_cmd(&hci_pin_code_request_negative_reply, connection->address);
28744c57c146S[email protected]             return;
28754c57c146S[email protected]         }
28764c57c146S[email protected] 
2877dbe1a790S[email protected]         if (connection->authentication_flags & SEND_IO_CAPABILITIES_REPLY){
287834d2123cS[email protected]             connectionClearAuthenticationFlags(connection, SEND_IO_CAPABILITIES_REPLY);
287982d8f825S[email protected]             log_info("IO Capability Request received, stack bondable %u, io cap %u", hci_stack->bondable, hci_stack->ssp_io_capability);
288082d8f825S[email protected]             if (hci_stack->bondable && (hci_stack->ssp_io_capability != SSP_IO_CAPABILITY_UNKNOWN)){
2881106d6d11S[email protected]                 // tweak authentication requirements
28823a9fb326S[email protected]                 uint8_t authreq = hci_stack->ssp_authentication_requirement;
2883106d6d11S[email protected]                 if (connection->bonding_flags & BONDING_DEDICATED){
28849faad3abS[email protected]                     authreq = SSP_IO_AUTHREQ_MITM_PROTECTION_NOT_REQUIRED_DEDICATED_BONDING;
28859faad3abS[email protected]                 }
28869faad3abS[email protected]                 if (gap_mitm_protection_required_for_security_level(connection->requested_security_level)){
28879faad3abS[email protected]                     authreq |= 1;
2888106d6d11S[email protected]                 }
28893a9fb326S[email protected]                 hci_send_cmd(&hci_io_capability_request_reply, &connection->address, hci_stack->ssp_io_capability, NULL, authreq);
2890f8fb5f6eS[email protected]             } else {
2891f8fb5f6eS[email protected]                 hci_send_cmd(&hci_io_capability_request_negative_reply, &connection->address, ERROR_CODE_PAIRING_NOT_ALLOWED);
2892f8fb5f6eS[email protected]             }
2893dbe1a790S[email protected]             return;
289432ab9390Smatthias.ringwald         }
289532ab9390Smatthias.ringwald 
2896dbe1a790S[email protected]         if (connection->authentication_flags & SEND_USER_CONFIRM_REPLY){
2897dbe1a790S[email protected]             connectionClearAuthenticationFlags(connection, SEND_USER_CONFIRM_REPLY);
289834d2123cS[email protected]             hci_send_cmd(&hci_user_confirmation_request_reply, &connection->address);
2899dbe1a790S[email protected]             return;
2900dbe1a790S[email protected]         }
2901dbe1a790S[email protected] 
2902dbe1a790S[email protected]         if (connection->authentication_flags & SEND_USER_PASSKEY_REPLY){
2903dbe1a790S[email protected]             connectionClearAuthenticationFlags(connection, SEND_USER_PASSKEY_REPLY);
290434d2123cS[email protected]             hci_send_cmd(&hci_user_passkey_request_reply, &connection->address, 000000);
2905dbe1a790S[email protected]             return;
2906dbe1a790S[email protected]         }
2907afd4e962S[email protected] 
2908afd4e962S[email protected]         if (connection->bonding_flags & BONDING_REQUEST_REMOTE_FEATURES){
2909afd4e962S[email protected]             connection->bonding_flags &= ~BONDING_REQUEST_REMOTE_FEATURES;
291034d2123cS[email protected]             hci_send_cmd(&hci_read_remote_supported_features_command, connection->con_handle);
29112bd8b7e7S[email protected]             return;
29122bd8b7e7S[email protected]         }
29132bd8b7e7S[email protected] 
2914ad83dc6aS[email protected]         if (connection->bonding_flags & BONDING_DISCONNECT_DEDICATED_DONE){
2915ad83dc6aS[email protected]             connection->bonding_flags &= ~BONDING_DISCONNECT_DEDICATED_DONE;
29161bd5283dS[email protected]             connection->bonding_flags |= BONDING_EMIT_COMPLETE_ON_DISCONNECT;
291752d34f98S[email protected]             hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13);  // authentication done
2918ad83dc6aS[email protected]             return;
2919ad83dc6aS[email protected]         }
292076f27cffSMatthias Ringwald 
292134d2123cS[email protected]         if (connection->bonding_flags & BONDING_SEND_AUTHENTICATE_REQUEST){
292234d2123cS[email protected]             connection->bonding_flags &= ~BONDING_SEND_AUTHENTICATE_REQUEST;
292334d2123cS[email protected]             hci_send_cmd(&hci_authentication_requested, connection->con_handle);
29242bd8b7e7S[email protected]             return;
2925afd4e962S[email protected]         }
292676f27cffSMatthias Ringwald 
2927dce78009S[email protected]         if (connection->bonding_flags & BONDING_SEND_ENCRYPTION_REQUEST){
2928dce78009S[email protected]             connection->bonding_flags &= ~BONDING_SEND_ENCRYPTION_REQUEST;
2929dce78009S[email protected]             hci_send_cmd(&hci_set_connection_encryption, connection->con_handle, 1);
2930dce78009S[email protected]             return;
2931dce78009S[email protected]         }
293276f27cffSMatthias Ringwald #endif
293376f27cffSMatthias Ringwald 
293476f27cffSMatthias Ringwald         if (connection->bonding_flags & BONDING_DISCONNECT_SECURITY_BLOCK){
293576f27cffSMatthias Ringwald             connection->bonding_flags &= ~BONDING_DISCONNECT_SECURITY_BLOCK;
293676f27cffSMatthias Ringwald             hci_send_cmd(&hci_disconnect, connection->con_handle, 0x0005);  // authentication failure
293776f27cffSMatthias Ringwald             return;
293876f27cffSMatthias Ringwald         }
2939da886c03S[email protected] 
2940a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
2941da886c03S[email protected]         if (connection->le_con_parameter_update_state == CON_PARAMETER_UPDATE_CHANGE_HCI_CON_PARAMETERS){
2942da886c03S[email protected]             connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_NONE;
2943da886c03S[email protected] 
2944c37a3166S[email protected]             uint16_t connection_interval_min = connection->le_conn_interval_min;
2945c37a3166S[email protected]             connection->le_conn_interval_min = 0;
2946c37a3166S[email protected]             hci_send_cmd(&hci_le_connection_update, connection->con_handle, connection_interval_min,
2947c37a3166S[email protected]                 connection->le_conn_interval_max, connection->le_conn_latency, connection->le_supervision_timeout,
2948c37a3166S[email protected]                 0x0000, 0xffff);
2949c37a3166S[email protected]         }
2950c37a3166S[email protected] #endif
2951dbe1a790S[email protected]     }
2952c7e0c5f6Smatthias.ringwald 
295305ae8de3SMatthias Ringwald     hci_connection_t * connection;
29543a9fb326S[email protected]     switch (hci_stack->state){
29553429f56bSmatthias.ringwald         case HCI_STATE_INITIALIZING:
295674b323a9SMatthias Ringwald             hci_initializing_run();
29573429f56bSmatthias.ringwald             break;
2958c7e0c5f6Smatthias.ringwald 
2959c7e0c5f6Smatthias.ringwald         case HCI_STATE_HALTING:
2960c7e0c5f6Smatthias.ringwald 
29619da54300S[email protected]             log_info("HCI_STATE_HALTING");
29629956955bSMatthias Ringwald 
29639956955bSMatthias Ringwald             // free whitelist entries
2964a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
2965d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
29669956955bSMatthias Ringwald             {
2967665d90f2SMatthias Ringwald                 btstack_linked_list_iterator_t lit;
2968665d90f2SMatthias Ringwald                 btstack_linked_list_iterator_init(&lit, &hci_stack->le_whitelist);
2969665d90f2SMatthias Ringwald                 while (btstack_linked_list_iterator_has_next(&lit)){
2970665d90f2SMatthias Ringwald                     whitelist_entry_t * entry = (whitelist_entry_t*) btstack_linked_list_iterator_next(&lit);
2971665d90f2SMatthias Ringwald                     btstack_linked_list_remove(&hci_stack->le_whitelist, (btstack_linked_item_t *) entry);
29729956955bSMatthias Ringwald                     btstack_memory_whitelist_entry_free(entry);
29739956955bSMatthias Ringwald                 }
29749956955bSMatthias Ringwald             }
29759956955bSMatthias Ringwald #endif
2976d70217a2SMatthias Ringwald #endif
2977c7e0c5f6Smatthias.ringwald             // close all open connections
29783a9fb326S[email protected]             connection =  (hci_connection_t *) hci_stack->connections;
2979c7e0c5f6Smatthias.ringwald             if (connection){
2980711e6c80SMatthias Ringwald                 hci_con_handle_t con_handle = (uint16_t) connection->con_handle;
2981d94d3cafS[email protected]                 if (!hci_can_send_command_packet_now()) return;
298232ab9390Smatthias.ringwald 
29838837e9efSMatthias Ringwald                 log_info("HCI_STATE_HALTING, connection %p, handle %u", connection, con_handle);
2984c7e0c5f6Smatthias.ringwald 
29858837e9efSMatthias Ringwald                 // cancel all l2cap connections right away instead of waiting for disconnection complete event ...
29868837e9efSMatthias Ringwald                 hci_emit_disconnection_complete(con_handle, 0x16); // terminated by local host
29878837e9efSMatthias Ringwald 
29888837e9efSMatthias Ringwald                 // ... which would be ignored anyway as we shutdown (free) the connection now
2989c7e0c5f6Smatthias.ringwald                 hci_shutdown_connection(connection);
29908837e9efSMatthias Ringwald 
29918837e9efSMatthias Ringwald                 // finally, send the disconnect command
29928837e9efSMatthias Ringwald                 hci_send_cmd(&hci_disconnect, con_handle, 0x13);  // remote closed connection
2993c7e0c5f6Smatthias.ringwald                 return;
2994c7e0c5f6Smatthias.ringwald             }
29959da54300S[email protected]             log_info("HCI_STATE_HALTING, calling off");
2996c7e0c5f6Smatthias.ringwald 
299772ea5239Smatthias.ringwald             // switch mode
2998c7e0c5f6Smatthias.ringwald             hci_power_control_off();
29999418f9c9Smatthias.ringwald 
30009da54300S[email protected]             log_info("HCI_STATE_HALTING, emitting state");
300172ea5239Smatthias.ringwald             hci_emit_state();
30029da54300S[email protected]             log_info("HCI_STATE_HALTING, done");
300372ea5239Smatthias.ringwald             break;
3004c7e0c5f6Smatthias.ringwald 
300572ea5239Smatthias.ringwald         case HCI_STATE_FALLING_ASLEEP:
30063a9fb326S[email protected]             switch(hci_stack->substate) {
300774b323a9SMatthias Ringwald                 case HCI_FALLING_ASLEEP_DISCONNECT:
30089da54300S[email protected]                     log_info("HCI_STATE_FALLING_ASLEEP");
300972ea5239Smatthias.ringwald                     // close all open connections
30103a9fb326S[email protected]                     connection =  (hci_connection_t *) hci_stack->connections;
301166da7044Smatthias.ringwald 
3012423a3e49SMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
301366da7044Smatthias.ringwald                     // don't close connections, if H4 supports power management
3014d0b87befSMatthias Ringwald                     if (btstack_control_iphone_power_management_enabled()){
301566da7044Smatthias.ringwald                         connection = NULL;
301666da7044Smatthias.ringwald                     }
301766da7044Smatthias.ringwald #endif
301872ea5239Smatthias.ringwald                     if (connection){
301932ab9390Smatthias.ringwald 
302072ea5239Smatthias.ringwald                         // send disconnect
3021d94d3cafS[email protected]                         if (!hci_can_send_command_packet_now()) return;
302232ab9390Smatthias.ringwald 
30239da54300S[email protected]                         log_info("HCI_STATE_FALLING_ASLEEP, connection %p, handle %u", connection, (uint16_t)connection->con_handle);
30246ad890d3Smatthias.ringwald                         hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13);  // remote closed connection
302572ea5239Smatthias.ringwald 
302672ea5239Smatthias.ringwald                         // send disconnected event right away - causes higher layer connections to get closed, too.
302772ea5239Smatthias.ringwald                         hci_shutdown_connection(connection);
302872ea5239Smatthias.ringwald                         return;
302972ea5239Smatthias.ringwald                     }
303072ea5239Smatthias.ringwald 
303192368cd3S[email protected]                     if (hci_classic_supported()){
303289db417bSmatthias.ringwald                         // disable page and inquiry scan
3033d94d3cafS[email protected]                         if (!hci_can_send_command_packet_now()) return;
303432ab9390Smatthias.ringwald 
30359da54300S[email protected]                         log_info("HCI_STATE_HALTING, disabling inq scans");
30363a9fb326S[email protected]                         hci_send_cmd(&hci_write_scan_enable, hci_stack->connectable << 1); // drop inquiry scan but keep page scan
303789db417bSmatthias.ringwald 
303889db417bSmatthias.ringwald                         // continue in next sub state
303974b323a9SMatthias Ringwald                         hci_stack->substate = HCI_FALLING_ASLEEP_W4_WRITE_SCAN_ENABLE;
304089db417bSmatthias.ringwald                         break;
304192368cd3S[email protected]                     }
3042202c8a4cSMatthias Ringwald                     // no break - fall through for ble-only chips
304392368cd3S[email protected] 
304474b323a9SMatthias Ringwald                 case HCI_FALLING_ASLEEP_COMPLETE:
30459da54300S[email protected]                     log_info("HCI_STATE_HALTING, calling sleep");
3046423a3e49SMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
304728171530Smatthias.ringwald                     // don't actually go to sleep, if H4 supports power management
3048d0b87befSMatthias Ringwald                     if (btstack_control_iphone_power_management_enabled()){
304928171530Smatthias.ringwald                         // SLEEP MODE reached
30503a9fb326S[email protected]                         hci_stack->state = HCI_STATE_SLEEPING;
305128171530Smatthias.ringwald                         hci_emit_state();
305228171530Smatthias.ringwald                         break;
305328171530Smatthias.ringwald                     }
305428171530Smatthias.ringwald #endif
305572ea5239Smatthias.ringwald                     // switch mode
30563a9fb326S[email protected]                     hci_power_control_sleep();  // changes hci_stack->state to SLEEP
3057c7e0c5f6Smatthias.ringwald                     hci_emit_state();
305828171530Smatthias.ringwald                     break;
305928171530Smatthias.ringwald 
306089db417bSmatthias.ringwald                 default:
306189db417bSmatthias.ringwald                     break;
306289db417bSmatthias.ringwald             }
3063c7e0c5f6Smatthias.ringwald             break;
3064c7e0c5f6Smatthias.ringwald 
30653429f56bSmatthias.ringwald         default:
30663429f56bSmatthias.ringwald             break;
30671f504dbdSmatthias.ringwald     }
30683429f56bSmatthias.ringwald }
306916833f0aSmatthias.ringwald 
307031452debSmatthias.ringwald int hci_send_cmd_packet(uint8_t *packet, int size){
307135454696SMatthias Ringwald     // house-keeping
307235454696SMatthias Ringwald 
307335454696SMatthias Ringwald     if (IS_COMMAND(packet, hci_write_loopback_mode)){
307435454696SMatthias Ringwald         hci_stack->loopback_mode = packet[3];
307535454696SMatthias Ringwald     }
307635454696SMatthias Ringwald 
307735454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
3078c8e4258aSmatthias.ringwald     bd_addr_t addr;
3079c8e4258aSmatthias.ringwald     hci_connection_t * conn;
3080c8e4258aSmatthias.ringwald 
3081c8e4258aSmatthias.ringwald     // create_connection?
3082c8e4258aSmatthias.ringwald     if (IS_COMMAND(packet, hci_create_connection)){
3083724d70a2SMatthias Ringwald         reverse_bd_addr(&packet[3], addr);
30849da54300S[email protected]         log_info("Create_connection to %s", bd_addr_to_str(addr));
3085c8e4258aSmatthias.ringwald 
30862e77e513S[email protected]         conn = hci_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_CLASSIC);
3087ad83dc6aS[email protected]         if (!conn){
308896a45072S[email protected]             conn = create_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_CLASSIC);
308917f1ba2aSmatthias.ringwald             if (!conn){
309017f1ba2aSmatthias.ringwald                 // notify client that alloc failed
30912deddeceSMatthias Ringwald                 hci_emit_connection_complete(addr, 0, BTSTACK_MEMORY_ALLOC_FAILED);
309217f1ba2aSmatthias.ringwald                 return 0; // don't sent packet to controller
309317f1ba2aSmatthias.ringwald             }
3094ad83dc6aS[email protected]             conn->state = SEND_CREATE_CONNECTION;
3095ad83dc6aS[email protected]         }
3096ad83dc6aS[email protected]         log_info("conn state %u", conn->state);
3097ad83dc6aS[email protected]         switch (conn->state){
3098ad83dc6aS[email protected]             // if connection active exists
3099ad83dc6aS[email protected]             case OPEN:
310062bda3fbS[email protected]                 // and OPEN, emit connection complete command, don't send to controller
3101274dad91SMatthias Ringwald                 hci_emit_connection_complete(addr, conn->con_handle, 0);
310262bda3fbS[email protected]                 return 0;
3103ad83dc6aS[email protected]             case SEND_CREATE_CONNECTION:
3104ad83dc6aS[email protected]                 // connection created by hci, e.g. dedicated bonding
3105ad83dc6aS[email protected]                 break;
3106ad83dc6aS[email protected]             default:
3107ad83dc6aS[email protected]                 // otherwise, just ignore as it is already in the open process
3108ad83dc6aS[email protected]                 return 0;
3109ad83dc6aS[email protected]         }
3110c8e4258aSmatthias.ringwald         conn->state = SENT_CREATE_CONNECTION;
3111c8e4258aSmatthias.ringwald     }
311235454696SMatthias Ringwald 
31137fde4af9Smatthias.ringwald     if (IS_COMMAND(packet, hci_link_key_request_reply)){
31147fde4af9Smatthias.ringwald         hci_add_connection_flags_for_flipped_bd_addr(&packet[3], SENT_LINK_KEY_REPLY);
31157fde4af9Smatthias.ringwald     }
31167fde4af9Smatthias.ringwald     if (IS_COMMAND(packet, hci_link_key_request_negative_reply)){
31177fde4af9Smatthias.ringwald         hci_add_connection_flags_for_flipped_bd_addr(&packet[3], SENT_LINK_KEY_NEGATIVE_REQUEST);
31187fde4af9Smatthias.ringwald     }
31197fde4af9Smatthias.ringwald 
31208ef73945Smatthias.ringwald     if (IS_COMMAND(packet, hci_delete_stored_link_key)){
3121a98592bcSMatthias Ringwald         if (hci_stack->link_key_db){
3122724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[3], addr);
3123a98592bcSMatthias Ringwald             hci_stack->link_key_db->delete_link_key(addr);
31248ef73945Smatthias.ringwald         }
31258ef73945Smatthias.ringwald     }
3126c8e4258aSmatthias.ringwald 
31276724cd9eS[email protected]     if (IS_COMMAND(packet, hci_pin_code_request_negative_reply)
31286724cd9eS[email protected]     ||  IS_COMMAND(packet, hci_pin_code_request_reply)){
3129724d70a2SMatthias Ringwald         reverse_bd_addr(&packet[3], addr);
31302e77e513S[email protected]         conn = hci_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_CLASSIC);
31316724cd9eS[email protected]         if (conn){
31326724cd9eS[email protected]             connectionClearAuthenticationFlags(conn, LEGACY_PAIRING_ACTIVE);
31336724cd9eS[email protected]         }
31346724cd9eS[email protected]     }
31356724cd9eS[email protected] 
31366724cd9eS[email protected]     if (IS_COMMAND(packet, hci_user_confirmation_request_negative_reply)
31376724cd9eS[email protected]     ||  IS_COMMAND(packet, hci_user_confirmation_request_reply)
31386724cd9eS[email protected]     ||  IS_COMMAND(packet, hci_user_passkey_request_negative_reply)
31396724cd9eS[email protected]     ||  IS_COMMAND(packet, hci_user_passkey_request_reply)) {
3140724d70a2SMatthias Ringwald         reverse_bd_addr(&packet[3], addr);
31412e77e513S[email protected]         conn = hci_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_CLASSIC);
31426724cd9eS[email protected]         if (conn){
31436724cd9eS[email protected]             connectionClearAuthenticationFlags(conn, SSP_PAIRING_ACTIVE);
31446724cd9eS[email protected]         }
31456724cd9eS[email protected]     }
3146ee752bb8SMatthias Ringwald 
3147ee752bb8SMatthias Ringwald #ifdef ENABLE_SCO_OVER_HCI
3148ee752bb8SMatthias Ringwald     // setup_synchronous_connection? Voice setting at offset 22
3149ee752bb8SMatthias Ringwald     if (IS_COMMAND(packet, hci_setup_synchronous_connection)){
3150ee752bb8SMatthias Ringwald         // TODO: compare to current setting if sco connection already active
3151ee752bb8SMatthias Ringwald         hci_stack->sco_voice_setting_active = little_endian_read_16(packet, 15);
3152ee752bb8SMatthias Ringwald     }
3153ee752bb8SMatthias Ringwald     // accept_synchronus_connection? Voice setting at offset 18
3154ee752bb8SMatthias Ringwald     if (IS_COMMAND(packet, hci_accept_synchronous_connection)){
3155ee752bb8SMatthias Ringwald         // TODO: compare to current setting if sco connection already active
3156ee752bb8SMatthias Ringwald         hci_stack->sco_voice_setting_active = little_endian_read_16(packet, 19);
3157ee752bb8SMatthias Ringwald     }
3158ee752bb8SMatthias Ringwald #endif
315935454696SMatthias Ringwald #endif
31604b3e1e19SMatthias Ringwald 
3161a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
3162d70217a2SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
316369a97523S[email protected]     if (IS_COMMAND(packet, hci_le_set_random_address)){
3164b95a5a35SMatthias Ringwald         hci_stack->le_random_address_set = 1;
3165b95a5a35SMatthias Ringwald         reverse_bd_addr(&packet[3], hci_stack->le_random_address);
3166d70217a2SMatthias Ringwald     }
3167171293d3SMatthias Ringwald     if (IS_COMMAND(packet, hci_le_set_advertise_enable)){
3168171293d3SMatthias Ringwald         hci_stack->le_advertisements_active = packet[3];
3169171293d3SMatthias Ringwald     }
3170d70217a2SMatthias Ringwald #endif
3171d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
3172b04dfa37SMatthias Ringwald     if (IS_COMMAND(packet, hci_le_create_connection)){
3173b04dfa37SMatthias Ringwald         // white list used?
3174b04dfa37SMatthias Ringwald         uint8_t initiator_filter_policy = packet[7];
3175b04dfa37SMatthias Ringwald         switch (initiator_filter_policy){
3176b04dfa37SMatthias Ringwald             case 0:
3177b04dfa37SMatthias Ringwald                 // whitelist not used
3178b04dfa37SMatthias Ringwald                 hci_stack->le_connecting_state = LE_CONNECTING_DIRECT;
3179b04dfa37SMatthias Ringwald                 break;
3180b04dfa37SMatthias Ringwald             case 1:
3181b04dfa37SMatthias Ringwald                 hci_stack->le_connecting_state = LE_CONNECTING_WHITELIST;
3182b04dfa37SMatthias Ringwald                 break;
3183b04dfa37SMatthias Ringwald             default:
3184b04dfa37SMatthias Ringwald                 log_error("Invalid initiator_filter_policy in LE Create Connection %u", initiator_filter_policy);
3185b04dfa37SMatthias Ringwald                 break;
3186b04dfa37SMatthias Ringwald         }
3187b04dfa37SMatthias Ringwald     }
3188b04dfa37SMatthias Ringwald     if (IS_COMMAND(packet, hci_le_create_connection_cancel)){
3189b04dfa37SMatthias Ringwald         hci_stack->le_connecting_state = LE_CONNECTING_IDLE;
3190b04dfa37SMatthias Ringwald     }
319169a97523S[email protected] #endif
3192d70217a2SMatthias Ringwald #endif
319369a97523S[email protected] 
31943a9fb326S[email protected]     hci_stack->num_cmd_packets--;
31955bb5bc3eS[email protected] 
31965bb5bc3eS[email protected]     hci_dump_packet(HCI_COMMAND_DATA_PACKET, 0, packet, size);
31976b4af23dS[email protected]     int err = hci_stack->hci_transport->send_packet(HCI_COMMAND_DATA_PACKET, packet, size);
31986b4af23dS[email protected] 
3199d051460cS[email protected]     // release packet buffer for synchronous transport implementations
3200c8b9416aS[email protected]     if (hci_transport_synchronous() && (packet == hci_stack->hci_packet_buffer)){
32016b4af23dS[email protected]         hci_stack->hci_packet_buffer_reserved = 0;
32026b4af23dS[email protected]     }
32036b4af23dS[email protected] 
32046b4af23dS[email protected]     return err;
320531452debSmatthias.ringwald }
32068adf0ddaSmatthias.ringwald 
32072bd8b7e7S[email protected] // disconnect because of security block
32082bd8b7e7S[email protected] void hci_disconnect_security_block(hci_con_handle_t con_handle){
32092bd8b7e7S[email protected]     hci_connection_t * connection = hci_connection_for_handle(con_handle);
32102bd8b7e7S[email protected]     if (!connection) return;
32112bd8b7e7S[email protected]     connection->bonding_flags |= BONDING_DISCONNECT_SECURITY_BLOCK;
32122bd8b7e7S[email protected] }
32132bd8b7e7S[email protected] 
32142bd8b7e7S[email protected] 
3215dbe1a790S[email protected] // Configure Secure Simple Pairing
3216dbe1a790S[email protected] 
321735454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
321835454696SMatthias Ringwald 
3219dbe1a790S[email protected] // enable will enable SSP during init
322015a95bd5SMatthias Ringwald void gap_ssp_set_enable(int enable){
32213a9fb326S[email protected]     hci_stack->ssp_enable = enable;
3222dbe1a790S[email protected] }
3223dbe1a790S[email protected] 
322495d71764SMatthias Ringwald static int hci_local_ssp_activated(void){
322515a95bd5SMatthias Ringwald     return gap_ssp_supported() && hci_stack->ssp_enable;
32262bd8b7e7S[email protected] }
32272bd8b7e7S[email protected] 
3228dbe1a790S[email protected] // if set, BTstack will respond to io capability request using authentication requirement
322915a95bd5SMatthias Ringwald void gap_ssp_set_io_capability(int io_capability){
32303a9fb326S[email protected]     hci_stack->ssp_io_capability = io_capability;
3231dbe1a790S[email protected] }
323215a95bd5SMatthias Ringwald void gap_ssp_set_authentication_requirement(int authentication_requirement){
32333a9fb326S[email protected]     hci_stack->ssp_authentication_requirement = authentication_requirement;
3234dbe1a790S[email protected] }
3235dbe1a790S[email protected] 
3236dbe1a790S[email protected] // if set, BTstack will confirm a numberic comparion and enter '000000' if requested
323715a95bd5SMatthias Ringwald void gap_ssp_set_auto_accept(int auto_accept){
32383a9fb326S[email protected]     hci_stack->ssp_auto_accept = auto_accept;
3239dbe1a790S[email protected] }
324035454696SMatthias Ringwald #endif
3241dbe1a790S[email protected] 
324294be1a66SMatthias Ringwald // va_list part of hci_send_cmd
324394be1a66SMatthias Ringwald int hci_send_cmd_va_arg(const hci_cmd_t *cmd, va_list argptr){
3244d94d3cafS[email protected]     if (!hci_can_send_command_packet_now()){
32459d14b626S[email protected]         log_error("hci_send_cmd called but cannot send packet now");
32469d14b626S[email protected]         return 0;
32479d14b626S[email protected]     }
32489d14b626S[email protected] 
32495127cc62S[email protected]     // for HCI INITIALIZATION
32509da54300S[email protected]     // log_info("hci_send_cmd: opcode %04x", cmd->opcode);
32515127cc62S[email protected]     hci_stack->last_cmd_opcode = cmd->opcode;
32525127cc62S[email protected] 
32539d14b626S[email protected]     hci_reserve_packet_buffer();
32549d14b626S[email protected]     uint8_t * packet = hci_stack->hci_packet_buffer;
325594be1a66SMatthias Ringwald     uint16_t size = hci_cmd_create_from_template(packet, cmd, argptr);
325694be1a66SMatthias Ringwald     return hci_send_cmd_packet(packet, size);
325794be1a66SMatthias Ringwald }
32589d14b626S[email protected] 
325994be1a66SMatthias Ringwald /**
326094be1a66SMatthias Ringwald  * pre: numcmds >= 0 - it's allowed to send a command to the controller
326194be1a66SMatthias Ringwald  */
326294be1a66SMatthias Ringwald int hci_send_cmd(const hci_cmd_t *cmd, ...){
32631cd208adSmatthias.ringwald     va_list argptr;
32641cd208adSmatthias.ringwald     va_start(argptr, cmd);
326594be1a66SMatthias Ringwald     int res = hci_send_cmd_va_arg(cmd, argptr);
32661cd208adSmatthias.ringwald     va_end(argptr);
326794be1a66SMatthias Ringwald     return res;
326893b8dc03Smatthias.ringwald }
3269c8e4258aSmatthias.ringwald 
3270ee091cf1Smatthias.ringwald // Create various non-HCI events.
3271ee091cf1Smatthias.ringwald // TODO: generalize, use table similar to hci_create_command
3272ee091cf1Smatthias.ringwald 
3273d6b06661SMatthias Ringwald static void hci_emit_event(uint8_t * event, uint16_t size, int dump){
3274fb37a842SMatthias Ringwald     // dump packet
3275d6b06661SMatthias Ringwald     if (dump) {
3276300c1ba4SMatthias Ringwald         hci_dump_packet( HCI_EVENT_PACKET, 0, event, size);
3277d6b06661SMatthias Ringwald     }
32781ef6bb52SMatthias Ringwald 
3279fb37a842SMatthias Ringwald     // dispatch to all event handlers
32801ef6bb52SMatthias Ringwald     btstack_linked_list_iterator_t it;
32811ef6bb52SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &hci_stack->event_handlers);
32821ef6bb52SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
32831ef6bb52SMatthias Ringwald         btstack_packet_callback_registration_t * entry = (btstack_packet_callback_registration_t*) btstack_linked_list_iterator_next(&it);
3284d9a7306aSMatthias Ringwald         entry->callback(HCI_EVENT_PACKET, 0, event, size);
32851ef6bb52SMatthias Ringwald     }
3286d6b06661SMatthias Ringwald }
3287d6b06661SMatthias Ringwald 
3288d6b06661SMatthias Ringwald static void hci_emit_acl_packet(uint8_t * packet, uint16_t size){
3289fb37a842SMatthias Ringwald     if (!hci_stack->acl_packet_handler) return;
32903d50b4baSMatthias Ringwald     hci_stack->acl_packet_handler(HCI_ACL_DATA_PACKET, 0, packet, size);
3291d6b06661SMatthias Ringwald }
3292d6b06661SMatthias Ringwald 
329335454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
3294701e3307SMatthias Ringwald static void hci_notify_if_sco_can_send_now(void){
32953bc639ceSMatthias Ringwald     // notify SCO sender if waiting
3296701e3307SMatthias Ringwald     if (!hci_stack->sco_waiting_for_can_send_now) return;
3297701e3307SMatthias Ringwald     if (hci_can_send_sco_packet_now()){
32983bc639ceSMatthias Ringwald         hci_stack->sco_waiting_for_can_send_now = 0;
3299701e3307SMatthias Ringwald         uint8_t event[2] = { HCI_EVENT_SCO_CAN_SEND_NOW, 0 };
3300701e3307SMatthias Ringwald         hci_dump_packet(HCI_EVENT_PACKET, 1, event, sizeof(event));
33013d50b4baSMatthias Ringwald         hci_stack->sco_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
33023bc639ceSMatthias Ringwald     }
33033bc639ceSMatthias Ringwald }
330435454696SMatthias Ringwald #endif
33053bc639ceSMatthias Ringwald 
330671de195eSMatthias Ringwald void hci_emit_state(void){
33073a9fb326S[email protected]     log_info("BTSTACK_EVENT_STATE %u", hci_stack->state);
3308425d1371Smatthias.ringwald     uint8_t event[3];
330980d52d6bSmatthias.ringwald     event[0] = BTSTACK_EVENT_STATE;
3310425d1371Smatthias.ringwald     event[1] = sizeof(event) - 2;
33113a9fb326S[email protected]     event[2] = hci_stack->state;
3312d6b06661SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
3313c8e4258aSmatthias.ringwald }
3314c8e4258aSmatthias.ringwald 
331535454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
33162deddeceSMatthias Ringwald static void hci_emit_connection_complete(bd_addr_t address, hci_con_handle_t con_handle, uint8_t status){
3317425d1371Smatthias.ringwald     uint8_t event[13];
3318c8e4258aSmatthias.ringwald     event[0] = HCI_EVENT_CONNECTION_COMPLETE;
3319425d1371Smatthias.ringwald     event[1] = sizeof(event) - 2;
332017f1ba2aSmatthias.ringwald     event[2] = status;
33212deddeceSMatthias Ringwald     little_endian_store_16(event, 3, con_handle);
33222deddeceSMatthias Ringwald     reverse_bd_addr(address, &event[5]);
3323c8e4258aSmatthias.ringwald     event[11] = 1; // ACL connection
3324c8e4258aSmatthias.ringwald     event[12] = 0; // encryption disabled
3325d6b06661SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
3326c8e4258aSmatthias.ringwald }
332752db98b2SMatthias Ringwald static void hci_emit_l2cap_check_timeout(hci_connection_t *conn){
332852db98b2SMatthias Ringwald     if (disable_l2cap_timeouts) return;
332952db98b2SMatthias Ringwald     log_info("L2CAP_EVENT_TIMEOUT_CHECK");
333052db98b2SMatthias Ringwald     uint8_t event[4];
333152db98b2SMatthias Ringwald     event[0] = L2CAP_EVENT_TIMEOUT_CHECK;
333252db98b2SMatthias Ringwald     event[1] = sizeof(event) - 2;
333352db98b2SMatthias Ringwald     little_endian_store_16(event, 2, conn->con_handle);
333452db98b2SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
333552db98b2SMatthias Ringwald }
333635454696SMatthias Ringwald #endif
3337c8e4258aSmatthias.ringwald 
333835454696SMatthias Ringwald #ifdef ENABLE_BLE
3339d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
3340fc64f94aSMatthias Ringwald static void hci_emit_le_connection_complete(uint8_t address_type, bd_addr_t address, hci_con_handle_t con_handle, uint8_t status){
33414f3229d8S[email protected]     uint8_t event[21];
33424f3229d8S[email protected]     event[0] = HCI_EVENT_LE_META;
33434f3229d8S[email protected]     event[1] = sizeof(event) - 2;
33444f3229d8S[email protected]     event[2] = HCI_SUBEVENT_LE_CONNECTION_COMPLETE;
33454f3229d8S[email protected]     event[3] = status;
3346fc64f94aSMatthias Ringwald     little_endian_store_16(event, 4, con_handle);
33474f3229d8S[email protected]     event[6] = 0; // TODO: role
33486e2e9a6bS[email protected]     event[7] = address_type;
3349724d70a2SMatthias Ringwald     reverse_bd_addr(address, &event[8]);
3350f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 14, 0); // interval
3351f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 16, 0); // latency
3352f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 18, 0); // supervision timeout
33534f3229d8S[email protected]     event[20] = 0; // master clock accuracy
3354d6b06661SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
33554f3229d8S[email protected] }
335635454696SMatthias Ringwald #endif
3357d70217a2SMatthias Ringwald #endif
33584f3229d8S[email protected] 
3359fc64f94aSMatthias Ringwald static void hci_emit_disconnection_complete(hci_con_handle_t con_handle, uint8_t reason){
3360425d1371Smatthias.ringwald     uint8_t event[6];
33613c4d4b90Smatthias.ringwald     event[0] = HCI_EVENT_DISCONNECTION_COMPLETE;
3362e518c4b8Smatthias.ringwald     event[1] = sizeof(event) - 2;
33633c4d4b90Smatthias.ringwald     event[2] = 0; // status = OK
3364fc64f94aSMatthias Ringwald     little_endian_store_16(event, 3, con_handle);
33653c4d4b90Smatthias.ringwald     event[5] = reason;
3366d6b06661SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
33673c4d4b90Smatthias.ringwald }
33683c4d4b90Smatthias.ringwald 
3369b83d5eabSMatthias Ringwald static void hci_emit_nr_connections_changed(void){
3370e0abb8e7S[email protected]     log_info("BTSTACK_EVENT_NR_CONNECTIONS_CHANGED %u", nr_hci_connections());
3371425d1371Smatthias.ringwald     uint8_t event[3];
337280d52d6bSmatthias.ringwald     event[0] = BTSTACK_EVENT_NR_CONNECTIONS_CHANGED;
3373425d1371Smatthias.ringwald     event[1] = sizeof(event) - 2;
337443bfb1bdSmatthias.ringwald     event[2] = nr_hci_connections();
3375d6b06661SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
337643bfb1bdSmatthias.ringwald }
3377038bc64cSmatthias.ringwald 
3378b83d5eabSMatthias Ringwald static void hci_emit_hci_open_failed(void){
3379e0abb8e7S[email protected]     log_info("BTSTACK_EVENT_POWERON_FAILED");
3380425d1371Smatthias.ringwald     uint8_t event[2];
338180d52d6bSmatthias.ringwald     event[0] = BTSTACK_EVENT_POWERON_FAILED;
3382425d1371Smatthias.ringwald     event[1] = sizeof(event) - 2;
3383d6b06661SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
3384038bc64cSmatthias.ringwald }
33851b0e3922Smatthias.ringwald 
338635454696SMatthias Ringwald static void hci_emit_dedicated_bonding_result(bd_addr_t address, uint8_t status){
338735454696SMatthias Ringwald     log_info("hci_emit_dedicated_bonding_result %u ", status);
338835454696SMatthias Ringwald     uint8_t event[9];
338935454696SMatthias Ringwald     int pos = 0;
339035454696SMatthias Ringwald     event[pos++] = GAP_EVENT_DEDICATED_BONDING_COMPLETED;
339135454696SMatthias Ringwald     event[pos++] = sizeof(event) - 2;
339235454696SMatthias Ringwald     event[pos++] = status;
339335454696SMatthias Ringwald     reverse_bd_addr(address, &event[pos]);
3394d6b06661SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
3395381fbed8Smatthias.ringwald }
3396458bf4e8S[email protected] 
339735454696SMatthias Ringwald 
339835454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
339935454696SMatthias Ringwald 
3400b83d5eabSMatthias Ringwald static void hci_emit_security_level(hci_con_handle_t con_handle, gap_security_level_t level){
3401df3354fcS[email protected]     log_info("hci_emit_security_level %u for handle %x", level, con_handle);
3402a00031e2S[email protected]     uint8_t event[5];
3403e00caf9cS[email protected]     int pos = 0;
34045611a760SMatthias Ringwald     event[pos++] = GAP_EVENT_SECURITY_LEVEL;
3405e00caf9cS[email protected]     event[pos++] = sizeof(event) - 2;
3406f8fbdce0SMatthias Ringwald     little_endian_store_16(event, 2, con_handle);
3407e00caf9cS[email protected]     pos += 2;
3408e00caf9cS[email protected]     event[pos++] = level;
3409d6b06661SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
3410e00caf9cS[email protected] }
3411e00caf9cS[email protected] 
341235454696SMatthias Ringwald static gap_security_level_t gap_security_level_for_connection(hci_connection_t * connection){
341335454696SMatthias Ringwald     if (!connection) return LEVEL_0;
341435454696SMatthias Ringwald     if ((connection->authentication_flags & CONNECTION_ENCRYPTED) == 0) return LEVEL_0;
341535454696SMatthias Ringwald     return gap_security_level_for_link_key_type(connection->link_key_type);
341635454696SMatthias Ringwald }
341735454696SMatthias Ringwald 
341835454696SMatthias Ringwald static void hci_emit_discoverable_enabled(uint8_t enabled){
341935454696SMatthias Ringwald     log_info("BTSTACK_EVENT_DISCOVERABLE_ENABLED %u", enabled);
342035454696SMatthias Ringwald     uint8_t event[3];
342135454696SMatthias Ringwald     event[0] = BTSTACK_EVENT_DISCOVERABLE_ENABLED;
342235454696SMatthias Ringwald     event[1] = sizeof(event) - 2;
342335454696SMatthias Ringwald     event[2] = enabled;
3424d6b06661SMatthias Ringwald     hci_emit_event(event, sizeof(event), 1);
3425ad83dc6aS[email protected] }
3426ad83dc6aS[email protected] 
342706b9e820SMatthias Ringwald #ifdef ENABLE_CLASSIC
342898a2fd1cSMatthias Ringwald // query if remote side supports eSCO
3429073bd0faSMatthias Ringwald int hci_remote_esco_supported(hci_con_handle_t con_handle){
343098a2fd1cSMatthias Ringwald     hci_connection_t * connection = hci_connection_for_handle(con_handle);
343198a2fd1cSMatthias Ringwald     if (!connection) return 0;
343298a2fd1cSMatthias Ringwald     return connection->remote_supported_feature_eSCO;
343398a2fd1cSMatthias Ringwald }
343498a2fd1cSMatthias Ringwald 
34352bd8b7e7S[email protected] // query if remote side supports SSP
34362bd8b7e7S[email protected] int hci_remote_ssp_supported(hci_con_handle_t con_handle){
34372bd8b7e7S[email protected]     hci_connection_t * connection = hci_connection_for_handle(con_handle);
34382bd8b7e7S[email protected]     if (!connection) return 0;
34392bd8b7e7S[email protected]     return (connection->bonding_flags & BONDING_REMOTE_SUPPORTS_SSP) ? 1 : 0;
34402bd8b7e7S[email protected] }
34412bd8b7e7S[email protected] 
344215a95bd5SMatthias Ringwald int gap_ssp_supported_on_both_sides(hci_con_handle_t handle){
3443df3354fcS[email protected]     return hci_local_ssp_activated() && hci_remote_ssp_supported(handle);
3444df3354fcS[email protected] }
344506b9e820SMatthias Ringwald #endif
3446df3354fcS[email protected] 
3447458bf4e8S[email protected] // GAP API
3448458bf4e8S[email protected] /**
3449458bf4e8S[email protected]  * @bbrief enable/disable bonding. default is enabled
3450458bf4e8S[email protected]  * @praram enabled
3451458bf4e8S[email protected]  */
34524c57c146S[email protected] void gap_set_bondable_mode(int enable){
34533a9fb326S[email protected]     hci_stack->bondable = enable ? 1 : 0;
3454458bf4e8S[email protected] }
34554ef6443cSMatthias Ringwald /**
34564ef6443cSMatthias Ringwald  * @brief Get bondable mode.
34574ef6443cSMatthias Ringwald  * @return 1 if bondable
34584ef6443cSMatthias Ringwald  */
34594ef6443cSMatthias Ringwald int gap_get_bondable_mode(void){
34604ef6443cSMatthias Ringwald     return hci_stack->bondable;
34614ef6443cSMatthias Ringwald }
3462cb230b9dS[email protected] 
3463cb230b9dS[email protected] /**
346434d2123cS[email protected]  * @brief map link keys to security levels
3465cb230b9dS[email protected]  */
346634d2123cS[email protected] gap_security_level_t gap_security_level_for_link_key_type(link_key_type_t link_key_type){
346734d2123cS[email protected]     switch (link_key_type){
34683c68dfa9S[email protected]         case AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256:
34693c68dfa9S[email protected]             return LEVEL_4;
34703c68dfa9S[email protected]         case COMBINATION_KEY:
34713c68dfa9S[email protected]         case AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P192:
34723c68dfa9S[email protected]             return LEVEL_3;
34733c68dfa9S[email protected]         default:
34743c68dfa9S[email protected]             return LEVEL_2;
34753c68dfa9S[email protected]     }
3476cb230b9dS[email protected] }
3477cb230b9dS[email protected] 
3478106d6d11S[email protected] int gap_mitm_protection_required_for_security_level(gap_security_level_t level){
34795127cc62S[email protected]     log_info("gap_mitm_protection_required_for_security_level %u", level);
3480106d6d11S[email protected]     return level > LEVEL_2;
3481106d6d11S[email protected] }
3482106d6d11S[email protected] 
348334d2123cS[email protected] /**
348434d2123cS[email protected]  * @brief get current security level
348534d2123cS[email protected]  */
348634d2123cS[email protected] gap_security_level_t gap_security_level(hci_con_handle_t con_handle){
348734d2123cS[email protected]     hci_connection_t * connection = hci_connection_for_handle(con_handle);
348834d2123cS[email protected]     if (!connection) return LEVEL_0;
348934d2123cS[email protected]     return gap_security_level_for_connection(connection);
349034d2123cS[email protected] }
349134d2123cS[email protected] 
3492cb230b9dS[email protected] /**
3493cb230b9dS[email protected]  * @brief request connection to device to
3494cb230b9dS[email protected]  * @result GAP_AUTHENTICATION_RESULT
3495cb230b9dS[email protected]  */
349634d2123cS[email protected] void gap_request_security_level(hci_con_handle_t con_handle, gap_security_level_t requested_level){
349734d2123cS[email protected]     hci_connection_t * connection = hci_connection_for_handle(con_handle);
349834d2123cS[email protected]     if (!connection){
3499a00031e2S[email protected]         hci_emit_security_level(con_handle, LEVEL_0);
350034d2123cS[email protected]         return;
350134d2123cS[email protected]     }
350234d2123cS[email protected]     gap_security_level_t current_level = gap_security_level(con_handle);
350334d2123cS[email protected]     log_info("gap_request_security_level %u, current level %u", requested_level, current_level);
350434d2123cS[email protected]     if (current_level >= requested_level){
3505a00031e2S[email protected]         hci_emit_security_level(con_handle, current_level);
350634d2123cS[email protected]         return;
350734d2123cS[email protected]     }
3508a00031e2S[email protected] 
350934d2123cS[email protected]     connection->requested_security_level = requested_level;
3510a00031e2S[email protected] 
351125bf5872S[email protected] #if 0
351225bf5872S[email protected]     // sending encryption request without a link key results in an error.
351325bf5872S[email protected]     // TODO: figure out how to use it properly
351425bf5872S[email protected] 
3515fb8ba0dbS[email protected]     // would enabling ecnryption suffice (>= LEVEL_2)?
3516a98592bcSMatthias Ringwald     if (hci_stack->link_key_db){
3517a00031e2S[email protected]         link_key_type_t link_key_type;
3518a00031e2S[email protected]         link_key_t      link_key;
3519a98592bcSMatthias Ringwald         if (hci_stack->link_key_db->get_link_key( &connection->address, &link_key, &link_key_type)){
3520a00031e2S[email protected]             if (gap_security_level_for_link_key_type(link_key_type) >= requested_level){
3521a00031e2S[email protected]                 connection->bonding_flags |= BONDING_SEND_ENCRYPTION_REQUEST;
3522a00031e2S[email protected]                 return;
3523a00031e2S[email protected]             }
3524a00031e2S[email protected]         }
3525a00031e2S[email protected]     }
352625bf5872S[email protected] #endif
3527a00031e2S[email protected] 
35281eb2563eS[email protected]     // try to authenticate connection
35291eb2563eS[email protected]     connection->bonding_flags |= BONDING_SEND_AUTHENTICATE_REQUEST;
3530e80b2cf9S[email protected]     hci_run();
3531e00caf9cS[email protected] }
3532ad83dc6aS[email protected] 
3533ad83dc6aS[email protected] /**
3534ad83dc6aS[email protected]  * @brief start dedicated bonding with device. disconnect after bonding
3535ad83dc6aS[email protected]  * @param device
3536ad83dc6aS[email protected]  * @param request MITM protection
3537ad83dc6aS[email protected]  * @result GAP_DEDICATED_BONDING_COMPLETE
3538ad83dc6aS[email protected]  */
3539ad83dc6aS[email protected] int gap_dedicated_bonding(bd_addr_t device, int mitm_protection_required){
3540ad83dc6aS[email protected] 
3541ad83dc6aS[email protected]     // create connection state machine
354296a45072S[email protected]     hci_connection_t * connection = create_connection_for_bd_addr_and_type(device, BD_ADDR_TYPE_CLASSIC);
3543ad83dc6aS[email protected] 
3544ad83dc6aS[email protected]     if (!connection){
3545ad83dc6aS[email protected]         return BTSTACK_MEMORY_ALLOC_FAILED;
3546ad83dc6aS[email protected]     }
3547ad83dc6aS[email protected] 
3548ad83dc6aS[email protected]     // delete linkn key
354915a95bd5SMatthias Ringwald     gap_drop_link_key_for_bd_addr(device);
3550ad83dc6aS[email protected] 
3551ad83dc6aS[email protected]     // configure LEVEL_2/3, dedicated bonding
3552ad83dc6aS[email protected]     connection->state = SEND_CREATE_CONNECTION;
3553ad83dc6aS[email protected]     connection->requested_security_level = mitm_protection_required ? LEVEL_3 : LEVEL_2;
3554f04a0c31SMatthias Ringwald     log_info("gap_dedicated_bonding, mitm %d -> level %u", mitm_protection_required, connection->requested_security_level);
3555ad83dc6aS[email protected]     connection->bonding_flags = BONDING_DEDICATED;
3556ad83dc6aS[email protected] 
3557ad83dc6aS[email protected]     // wait for GAP Security Result and send GAP Dedicated Bonding complete
3558ad83dc6aS[email protected] 
3559ad83dc6aS[email protected]     // handle: connnection failure (connection complete != ok)
3560ad83dc6aS[email protected]     // handle: authentication failure
3561ad83dc6aS[email protected]     // handle: disconnect on done
3562ad83dc6aS[email protected] 
3563ad83dc6aS[email protected]     hci_run();
3564ad83dc6aS[email protected] 
3565ad83dc6aS[email protected]     return 0;
3566ad83dc6aS[email protected] }
356735454696SMatthias Ringwald #endif
35688e618f72S[email protected] 
35698e618f72S[email protected] void gap_set_local_name(const char * local_name){
35708e618f72S[email protected]     hci_stack->local_name = local_name;
35718e618f72S[email protected] }
35728e618f72S[email protected] 
357335454696SMatthias Ringwald 
357435454696SMatthias Ringwald #ifdef ENABLE_BLE
357535454696SMatthias Ringwald 
3576d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
3577d8e8f12aSMatthias Ringwald void gap_start_scan(void){
3578d8e8f12aSMatthias Ringwald     if (hci_stack->le_scanning_state == LE_SCANNING) return;
35797bdc6798S[email protected]     hci_stack->le_scanning_state = LE_START_SCAN;
35807bdc6798S[email protected]     hci_run();
35817bdc6798S[email protected] }
35828e618f72S[email protected] 
3583d8e8f12aSMatthias Ringwald void gap_stop_scan(void){
3584d8e8f12aSMatthias Ringwald     if ( hci_stack->le_scanning_state == LE_SCAN_IDLE) return;
35857bdc6798S[email protected]     hci_stack->le_scanning_state = LE_STOP_SCAN;
35867bdc6798S[email protected]     hci_run();
35877bdc6798S[email protected] }
35884f3229d8S[email protected] 
3589d8e8f12aSMatthias Ringwald void gap_set_scan_parameters(uint8_t scan_type, uint16_t scan_interval, uint16_t scan_window){
3590ef11999fSmatthias.ringwald     hci_stack->le_scan_type     = scan_type;
3591ef11999fSmatthias.ringwald     hci_stack->le_scan_interval = scan_interval;
3592ef11999fSmatthias.ringwald     hci_stack->le_scan_window   = scan_window;
3593ef11999fSmatthias.ringwald     hci_run();
3594ef11999fSmatthias.ringwald }
35954f3229d8S[email protected] 
3596d8e8f12aSMatthias Ringwald uint8_t gap_connect(bd_addr_t addr, bd_addr_type_t addr_type){
35974f3229d8S[email protected]     hci_connection_t * conn = hci_connection_for_bd_addr_and_type(addr, addr_type);
35984f3229d8S[email protected]     if (!conn){
3599d8e8f12aSMatthias Ringwald         log_info("gap_connect: no connection exists yet, creating context");
36002e77e513S[email protected]         conn = create_connection_for_bd_addr_and_type(addr, addr_type);
36014f3229d8S[email protected]         if (!conn){
36024f3229d8S[email protected]             // notify client that alloc failed
36036e2e9a6bS[email protected]             hci_emit_le_connection_complete(addr_type, addr, 0, BTSTACK_MEMORY_ALLOC_FAILED);
3604d8e8f12aSMatthias Ringwald             log_info("gap_connect: failed to alloc hci_connection_t");
3605472a5742SMatthias Ringwald             return GATT_CLIENT_NOT_CONNECTED; // don't sent packet to controller
36064f3229d8S[email protected]         }
36074f3229d8S[email protected]         conn->state = SEND_CREATE_CONNECTION;
3608d8e8f12aSMatthias Ringwald         log_info("gap_connect: send create connection next");
3609564fca32S[email protected]         hci_run();
3610616edd56SMatthias Ringwald         return 0;
36114f3229d8S[email protected]     }
36120bf6344aS[email protected] 
36130bf6344aS[email protected]     if (!hci_is_le_connection(conn) ||
36140bf6344aS[email protected]         conn->state == SEND_CREATE_CONNECTION ||
36150bf6344aS[email protected]         conn->state == SENT_CREATE_CONNECTION) {
36162e77e513S[email protected]         hci_emit_le_connection_complete(conn->address_type, conn->address, 0, ERROR_CODE_COMMAND_DISALLOWED);
3617d8e8f12aSMatthias Ringwald         log_error("gap_connect: classic connection or connect is already being created");
3618616edd56SMatthias Ringwald         return GATT_CLIENT_IN_WRONG_STATE;
36190bf6344aS[email protected]     }
36200bf6344aS[email protected] 
3621d8e8f12aSMatthias Ringwald     log_info("gap_connect: context exists with state %u", conn->state);
36222e77e513S[email protected]     hci_emit_le_connection_complete(conn->address_type, conn->address, conn->con_handle, 0);
36234f3229d8S[email protected]     hci_run();
3624616edd56SMatthias Ringwald     return 0;
36254f3229d8S[email protected] }
36264f3229d8S[email protected] 
36277851196eSmatthias.ringwald // @assumption: only a single outgoing LE Connection exists
3628d8e8f12aSMatthias Ringwald static hci_connection_t * gap_get_outgoing_connection(void){
3629665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
3630665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) hci_stack->connections; it ; it = it->next){
36310bf6344aS[email protected]         hci_connection_t * conn = (hci_connection_t *) it;
36320bf6344aS[email protected]         if (!hci_is_le_connection(conn)) continue;
36330bf6344aS[email protected]         switch (conn->state){
3634a6725849S[email protected]             case SEND_CREATE_CONNECTION:
36357851196eSmatthias.ringwald             case SENT_CREATE_CONNECTION:
36367851196eSmatthias.ringwald                 return conn;
36377851196eSmatthias.ringwald             default:
36387851196eSmatthias.ringwald                 break;
36397851196eSmatthias.ringwald         };
36407851196eSmatthias.ringwald     }
36417851196eSmatthias.ringwald     return NULL;
36427851196eSmatthias.ringwald }
36437851196eSmatthias.ringwald 
3644d8e8f12aSMatthias Ringwald uint8_t gap_connect_cancel(void){
3645d8e8f12aSMatthias Ringwald     hci_connection_t * conn = gap_get_outgoing_connection();
3646616edd56SMatthias Ringwald     if (!conn) return 0;
36477851196eSmatthias.ringwald     switch (conn->state){
36487851196eSmatthias.ringwald         case SEND_CREATE_CONNECTION:
36497851196eSmatthias.ringwald             // skip sending create connection and emit event instead
36502e77e513S[email protected]             hci_emit_le_connection_complete(conn->address_type, conn->address, 0, ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER);
3651665d90f2SMatthias Ringwald             btstack_linked_list_remove(&hci_stack->connections, (btstack_linked_item_t *) conn);
36527851196eSmatthias.ringwald             btstack_memory_hci_connection_free( conn );
36530bf6344aS[email protected]             break;
3654a6725849S[email protected]         case SENT_CREATE_CONNECTION:
36557851196eSmatthias.ringwald             // request to send cancel connection
36560bf6344aS[email protected]             conn->state = SEND_CANCEL_CONNECTION;
36570bf6344aS[email protected]             hci_run();
36580bf6344aS[email protected]             break;
36590bf6344aS[email protected]         default:
36600bf6344aS[email protected]             break;
36610bf6344aS[email protected]     }
3662616edd56SMatthias Ringwald     return 0;
3663e31f89a7S[email protected] }
3664d70217a2SMatthias Ringwald #endif
36654f3229d8S[email protected] 
3666c37a3166S[email protected] /**
3667c37a3166S[email protected]  * @brief Updates the connection parameters for a given LE connection
3668c37a3166S[email protected]  * @param handle
3669c37a3166S[email protected]  * @param conn_interval_min (unit: 1.25ms)
3670c37a3166S[email protected]  * @param conn_interval_max (unit: 1.25ms)
3671c37a3166S[email protected]  * @param conn_latency
3672c37a3166S[email protected]  * @param supervision_timeout (unit: 10ms)
3673c37a3166S[email protected]  * @returns 0 if ok
3674c37a3166S[email protected]  */
3675c37a3166S[email protected] int gap_update_connection_parameters(hci_con_handle_t con_handle, uint16_t conn_interval_min,
3676c37a3166S[email protected]     uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout){
3677c37a3166S[email protected]     hci_connection_t * connection = hci_connection_for_handle(con_handle);
3678c37a3166S[email protected]     if (!connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
3679c37a3166S[email protected]     connection->le_conn_interval_min = conn_interval_min;
3680c37a3166S[email protected]     connection->le_conn_interval_max = conn_interval_max;
3681c37a3166S[email protected]     connection->le_conn_latency = conn_latency;
3682c37a3166S[email protected]     connection->le_supervision_timeout = supervision_timeout;
368384cf6d83SMatthias Ringwald     connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_CHANGE_HCI_CON_PARAMETERS;
3684cfc59f1bSMatthias Ringwald     hci_run();
3685c37a3166S[email protected]     return 0;
3686c37a3166S[email protected] }
3687c37a3166S[email protected] 
368845c102fdSMatthias Ringwald /**
3689b68d7bc3SMatthias Ringwald  * @brief Request an update of the connection parameter for a given LE connection
3690b68d7bc3SMatthias Ringwald  * @param handle
3691b68d7bc3SMatthias Ringwald  * @param conn_interval_min (unit: 1.25ms)
3692b68d7bc3SMatthias Ringwald  * @param conn_interval_max (unit: 1.25ms)
3693b68d7bc3SMatthias Ringwald  * @param conn_latency
3694b68d7bc3SMatthias Ringwald  * @param supervision_timeout (unit: 10ms)
3695b68d7bc3SMatthias Ringwald  * @returns 0 if ok
3696b68d7bc3SMatthias Ringwald  */
3697b68d7bc3SMatthias Ringwald int gap_request_connection_parameter_update(hci_con_handle_t con_handle, uint16_t conn_interval_min,
3698b68d7bc3SMatthias Ringwald     uint16_t conn_interval_max, uint16_t conn_latency, uint16_t supervision_timeout){
3699b68d7bc3SMatthias Ringwald     hci_connection_t * connection = hci_connection_for_handle(con_handle);
3700b68d7bc3SMatthias Ringwald     if (!connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
3701b68d7bc3SMatthias Ringwald     connection->le_conn_interval_min = conn_interval_min;
3702b68d7bc3SMatthias Ringwald     connection->le_conn_interval_max = conn_interval_max;
3703b68d7bc3SMatthias Ringwald     connection->le_conn_latency = conn_latency;
3704b68d7bc3SMatthias Ringwald     connection->le_supervision_timeout = supervision_timeout;
3705b68d7bc3SMatthias Ringwald     connection->le_con_parameter_update_state = CON_PARAMETER_UPDATE_SEND_REQUEST;
3706b68d7bc3SMatthias Ringwald     hci_run();
3707b68d7bc3SMatthias Ringwald     return 0;
3708b68d7bc3SMatthias Ringwald }
3709b68d7bc3SMatthias Ringwald 
3710d70217a2SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
3711d70217a2SMatthias Ringwald 
3712501f56b3SMatthias Ringwald static void gap_advertisments_changed(void){
3713501f56b3SMatthias Ringwald     // disable advertisements before updating adv, scan data, or adv params
3714501f56b3SMatthias Ringwald     if (hci_stack->le_advertisements_active){
3715501f56b3SMatthias Ringwald         hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_DISABLE | LE_ADVERTISEMENT_TASKS_ENABLE;
3716501f56b3SMatthias Ringwald     }
3717501f56b3SMatthias Ringwald     hci_run();
3718501f56b3SMatthias Ringwald }
3719501f56b3SMatthias Ringwald 
3720b68d7bc3SMatthias Ringwald /**
372145c102fdSMatthias Ringwald  * @brief Set Advertisement Data
372245c102fdSMatthias Ringwald  * @param advertising_data_length
372345c102fdSMatthias Ringwald  * @param advertising_data (max 31 octets)
372445c102fdSMatthias Ringwald  * @note data is not copied, pointer has to stay valid
372545c102fdSMatthias Ringwald  */
372645c102fdSMatthias Ringwald void gap_advertisements_set_data(uint8_t advertising_data_length, uint8_t * advertising_data){
372745c102fdSMatthias Ringwald     hci_stack->le_advertisements_data_len = advertising_data_length;
372845c102fdSMatthias Ringwald     hci_stack->le_advertisements_data = advertising_data;
3729501f56b3SMatthias Ringwald     hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_ADV_DATA;
3730501f56b3SMatthias Ringwald     gap_advertisments_changed();
373145c102fdSMatthias Ringwald }
3732501f56b3SMatthias Ringwald 
3733501f56b3SMatthias Ringwald /**
3734501f56b3SMatthias Ringwald  * @brief Set Scan Response Data
3735501f56b3SMatthias Ringwald  * @param advertising_data_length
3736501f56b3SMatthias Ringwald  * @param advertising_data (max 31 octets)
3737501f56b3SMatthias Ringwald  * @note data is not copied, pointer has to stay valid
3738501f56b3SMatthias Ringwald  */
3739501f56b3SMatthias Ringwald void gap_scan_response_set_data(uint8_t scan_response_data_length, uint8_t * scan_response_data){
3740501f56b3SMatthias Ringwald     hci_stack->le_scan_response_data_len = scan_response_data_length;
3741501f56b3SMatthias Ringwald     hci_stack->le_scan_response_data = scan_response_data;
3742501f56b3SMatthias Ringwald     hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_SCAN_DATA;
3743501f56b3SMatthias Ringwald     gap_advertisments_changed();
374445c102fdSMatthias Ringwald }
374545c102fdSMatthias Ringwald 
374645c102fdSMatthias Ringwald /**
374745c102fdSMatthias Ringwald  * @brief Set Advertisement Parameters
374845c102fdSMatthias Ringwald  * @param adv_int_min
374945c102fdSMatthias Ringwald  * @param adv_int_max
375045c102fdSMatthias Ringwald  * @param adv_type
375145c102fdSMatthias Ringwald  * @param direct_address_type
375245c102fdSMatthias Ringwald  * @param direct_address
375345c102fdSMatthias Ringwald  * @param channel_map
375445c102fdSMatthias Ringwald  * @param filter_policy
375545c102fdSMatthias Ringwald  *
375645c102fdSMatthias Ringwald  * @note internal use. use gap_advertisements_set_params from gap_le.h instead.
375745c102fdSMatthias Ringwald  */
375845c102fdSMatthias Ringwald  void hci_le_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type,
3759b95a5a35SMatthias Ringwald     uint8_t direct_address_typ, bd_addr_t direct_address,
376045c102fdSMatthias Ringwald     uint8_t channel_map, uint8_t filter_policy) {
376145c102fdSMatthias Ringwald 
376245c102fdSMatthias Ringwald     hci_stack->le_advertisements_interval_min = adv_int_min;
376345c102fdSMatthias Ringwald     hci_stack->le_advertisements_interval_max = adv_int_max;
376445c102fdSMatthias Ringwald     hci_stack->le_advertisements_type = adv_type;
376545c102fdSMatthias Ringwald     hci_stack->le_advertisements_direct_address_type = direct_address_typ;
376645c102fdSMatthias Ringwald     hci_stack->le_advertisements_channel_map = channel_map;
376745c102fdSMatthias Ringwald     hci_stack->le_advertisements_filter_policy = filter_policy;
376845c102fdSMatthias Ringwald     memcpy(hci_stack->le_advertisements_direct_address, direct_address, 6);
376945c102fdSMatthias Ringwald 
377045c102fdSMatthias Ringwald     hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_PARAMS;
3771501f56b3SMatthias Ringwald     gap_advertisments_changed();
377245c102fdSMatthias Ringwald  }
377345c102fdSMatthias Ringwald 
377445c102fdSMatthias Ringwald /**
377545c102fdSMatthias Ringwald  * @brief Enable/Disable Advertisements
377645c102fdSMatthias Ringwald  * @param enabled
377745c102fdSMatthias Ringwald  */
377845c102fdSMatthias Ringwald void gap_advertisements_enable(int enabled){
377945c102fdSMatthias Ringwald     hci_stack->le_advertisements_enabled = enabled;
378045c102fdSMatthias Ringwald     if (enabled && !hci_stack->le_advertisements_active){
378145c102fdSMatthias Ringwald         hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_ENABLE;
378245c102fdSMatthias Ringwald     }
378345c102fdSMatthias Ringwald     if (!enabled && hci_stack->le_advertisements_active){
378445c102fdSMatthias Ringwald         hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_DISABLE;
378545c102fdSMatthias Ringwald     }
3786cfc59f1bSMatthias Ringwald     hci_run();
378745c102fdSMatthias Ringwald }
378845c102fdSMatthias Ringwald 
378935454696SMatthias Ringwald #endif
379006e5cf96SMatthias Ringwald 
379106e5cf96SMatthias Ringwald void hci_le_set_own_address_type(uint8_t own_address_type){
379206e5cf96SMatthias Ringwald     log_info("hci_le_set_own_address_type: old %u, new %u", hci_stack->le_own_addr_type, own_address_type);
379306e5cf96SMatthias Ringwald     if (own_address_type == hci_stack->le_own_addr_type) return;
379406e5cf96SMatthias Ringwald     hci_stack->le_own_addr_type = own_address_type;
379506e5cf96SMatthias Ringwald 
379664068776SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
379706e5cf96SMatthias Ringwald     // update advertisement parameters, too
379806e5cf96SMatthias Ringwald     hci_stack->le_advertisements_todo |= LE_ADVERTISEMENT_TASKS_SET_PARAMS;
379906e5cf96SMatthias Ringwald     gap_advertisments_changed();
380064068776SMatthias Ringwald #endif
380164068776SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
380206e5cf96SMatthias Ringwald     // note: we don't update scan parameters or modify ongoing connection attempts
380364068776SMatthias Ringwald #endif
380406e5cf96SMatthias Ringwald }
380506e5cf96SMatthias Ringwald 
3806d70217a2SMatthias Ringwald #endif
380745c102fdSMatthias Ringwald 
3808616edd56SMatthias Ringwald uint8_t gap_disconnect(hci_con_handle_t handle){
38095917a5c5S[email protected]     hci_connection_t * conn = hci_connection_for_handle(handle);
38105917a5c5S[email protected]     if (!conn){
38117851196eSmatthias.ringwald         hci_emit_disconnection_complete(handle, 0);
3812616edd56SMatthias Ringwald         return 0;
38135917a5c5S[email protected]     }
38145917a5c5S[email protected]     conn->state = SEND_DISCONNECT;
38155917a5c5S[email protected]     hci_run();
3816616edd56SMatthias Ringwald     return 0;
38174f3229d8S[email protected] }
381804a6ef8cSmatthias.ringwald 
3819a1bf5ae7SMatthias Ringwald /**
3820a1bf5ae7SMatthias Ringwald  * @brief Get connection type
3821a1bf5ae7SMatthias Ringwald  * @param con_handle
3822a1bf5ae7SMatthias Ringwald  * @result connection_type
3823a1bf5ae7SMatthias Ringwald  */
3824a1bf5ae7SMatthias Ringwald gap_connection_type_t gap_get_connection_type(hci_con_handle_t connection_handle){
3825a1bf5ae7SMatthias Ringwald     hci_connection_t * conn = hci_connection_for_handle(connection_handle);
3826a1bf5ae7SMatthias Ringwald     if (!conn) return GAP_CONNECTION_INVALID;
3827a1bf5ae7SMatthias Ringwald     switch (conn->address_type){
3828a1bf5ae7SMatthias Ringwald         case BD_ADDR_TYPE_LE_PUBLIC:
3829a1bf5ae7SMatthias Ringwald         case BD_ADDR_TYPE_LE_RANDOM:
3830a1bf5ae7SMatthias Ringwald             return GAP_CONNECTION_LE;
3831a1bf5ae7SMatthias Ringwald         case BD_ADDR_TYPE_SCO:
3832a1bf5ae7SMatthias Ringwald             return GAP_CONNECTION_SCO;
3833a1bf5ae7SMatthias Ringwald         case BD_ADDR_TYPE_CLASSIC:
3834a1bf5ae7SMatthias Ringwald             return GAP_CONNECTION_ACL;
3835a1bf5ae7SMatthias Ringwald         default:
3836a1bf5ae7SMatthias Ringwald             return GAP_CONNECTION_INVALID;
3837a1bf5ae7SMatthias Ringwald     }
3838a1bf5ae7SMatthias Ringwald }
3839a1bf5ae7SMatthias Ringwald 
3840a9a4c409SMatthias Ringwald #ifdef ENABLE_BLE
38414f551432SMatthias Ringwald 
3842d70217a2SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
3843d23838ecSMatthias Ringwald /**
3844ac9c45e0SMatthias Ringwald  * @brief Auto Connection Establishment - Start Connecting to device
3845ac9c45e0SMatthias Ringwald  * @param address_typ
3846ac9c45e0SMatthias Ringwald  * @param address
3847ac9c45e0SMatthias Ringwald  * @returns 0 if ok
3848ac9c45e0SMatthias Ringwald  */
38494f551432SMatthias Ringwald int gap_auto_connection_start(bd_addr_type_t address_type, bd_addr_t address){
3850e83201bcSMatthias Ringwald     // check capacity
3851665d90f2SMatthias Ringwald     int num_entries = btstack_linked_list_count(&hci_stack->le_whitelist);
385291915b0bSMatthias Ringwald     if (num_entries >= hci_stack->le_whitelist_capacity) return ERROR_CODE_MEMORY_CAPACITY_EXCEEDED;
3853e83201bcSMatthias Ringwald     whitelist_entry_t * entry = btstack_memory_whitelist_entry_get();
3854e83201bcSMatthias Ringwald     if (!entry) return BTSTACK_MEMORY_ALLOC_FAILED;
3855e83201bcSMatthias Ringwald     entry->address_type = address_type;
3856e83201bcSMatthias Ringwald     memcpy(entry->address, address, 6);
3857e83201bcSMatthias Ringwald     entry->state = LE_WHITELIST_ADD_TO_CONTROLLER;
3858665d90f2SMatthias Ringwald     btstack_linked_list_add(&hci_stack->le_whitelist, (btstack_linked_item_t*) entry);
3859e83201bcSMatthias Ringwald     hci_run();
3860e83201bcSMatthias Ringwald     return 0;
3861ac9c45e0SMatthias Ringwald }
3862ac9c45e0SMatthias Ringwald 
386342ff5ba1SMatthias Ringwald static void hci_remove_from_whitelist(bd_addr_type_t address_type, bd_addr_t address){
3864665d90f2SMatthias Ringwald     btstack_linked_list_iterator_t it;
3865665d90f2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &hci_stack->le_whitelist);
3866665d90f2SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
3867665d90f2SMatthias Ringwald         whitelist_entry_t * entry = (whitelist_entry_t*) btstack_linked_list_iterator_next(&it);
3868e83201bcSMatthias Ringwald         if (entry->address_type != address_type) continue;
3869e83201bcSMatthias Ringwald         if (memcmp(entry->address, address, 6) != 0) continue;
3870e83201bcSMatthias Ringwald         if (entry->state & LE_WHITELIST_ON_CONTROLLER){
3871e83201bcSMatthias Ringwald             // remove from controller if already present
3872e83201bcSMatthias Ringwald             entry->state |= LE_WHITELIST_REMOVE_FROM_CONTROLLER;
3873e83201bcSMatthias Ringwald             continue;
3874e83201bcSMatthias Ringwald         }
3875e83201bcSMatthias Ringwald         // direclty remove entry from whitelist
3876665d90f2SMatthias Ringwald         btstack_linked_list_iterator_remove(&it);
3877e83201bcSMatthias Ringwald         btstack_memory_whitelist_entry_free(entry);
3878e83201bcSMatthias Ringwald     }
387942ff5ba1SMatthias Ringwald }
388042ff5ba1SMatthias Ringwald 
388142ff5ba1SMatthias Ringwald /**
388242ff5ba1SMatthias Ringwald  * @brief Auto Connection Establishment - Stop Connecting to device
388342ff5ba1SMatthias Ringwald  * @param address_typ
388442ff5ba1SMatthias Ringwald  * @param address
388542ff5ba1SMatthias Ringwald  * @returns 0 if ok
388642ff5ba1SMatthias Ringwald  */
388742ff5ba1SMatthias Ringwald int gap_auto_connection_stop(bd_addr_type_t address_type, bd_addr_t address){
388842ff5ba1SMatthias Ringwald     hci_remove_from_whitelist(address_type, address);
3889e83201bcSMatthias Ringwald     hci_run();
3890e83201bcSMatthias Ringwald     return 0;
3891ac9c45e0SMatthias Ringwald }
3892ac9c45e0SMatthias Ringwald 
3893ac9c45e0SMatthias Ringwald /**
3894ac9c45e0SMatthias Ringwald  * @brief Auto Connection Establishment - Stop everything
3895ac9c45e0SMatthias Ringwald  * @note  Convenience function to stop all active auto connection attempts
3896ac9c45e0SMatthias Ringwald  */
3897ac9c45e0SMatthias Ringwald void gap_auto_connection_stop_all(void){
3898665d90f2SMatthias Ringwald     btstack_linked_list_iterator_t it;
3899665d90f2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &hci_stack->le_whitelist);
3900665d90f2SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
3901665d90f2SMatthias Ringwald         whitelist_entry_t * entry = (whitelist_entry_t*) btstack_linked_list_iterator_next(&it);
3902e83201bcSMatthias Ringwald         if (entry->state & LE_WHITELIST_ON_CONTROLLER){
3903e83201bcSMatthias Ringwald             // remove from controller if already present
3904e83201bcSMatthias Ringwald             entry->state |= LE_WHITELIST_REMOVE_FROM_CONTROLLER;
3905e83201bcSMatthias Ringwald             continue;
3906e83201bcSMatthias Ringwald         }
390791915b0bSMatthias Ringwald         // directly remove entry from whitelist
3908665d90f2SMatthias Ringwald         btstack_linked_list_iterator_remove(&it);
3909e83201bcSMatthias Ringwald         btstack_memory_whitelist_entry_free(entry);
3910e83201bcSMatthias Ringwald     }
3911e83201bcSMatthias Ringwald     hci_run();
3912ac9c45e0SMatthias Ringwald }
3913d70217a2SMatthias Ringwald #endif
39144f551432SMatthias Ringwald #endif
39154f551432SMatthias Ringwald 
391635454696SMatthias Ringwald #ifdef ENABLE_CLASSIC
3917ac9c45e0SMatthias Ringwald /**
3918ff00ed1cSMatthias Ringwald  * @brief Set Extended Inquiry Response data
3919ff00ed1cSMatthias Ringwald  * @param eir_data size 240 bytes, is not copied make sure memory is accessible during stack startup
3920ff00ed1cSMatthias Ringwald  * @note has to be done before stack starts up
3921ff00ed1cSMatthias Ringwald  */
3922ff00ed1cSMatthias Ringwald void gap_set_extended_inquiry_response(const uint8_t * data){
3923ff00ed1cSMatthias Ringwald     hci_stack->eir_data = data;
3924ff00ed1cSMatthias Ringwald }
3925ff00ed1cSMatthias Ringwald 
3926ff00ed1cSMatthias Ringwald /**
3927f6858d14SMatthias Ringwald  * @brief Set inquiry mode: standard, with RSSI, with RSSI + Extended Inquiry Results. Has to be called before power on.
3928f6858d14SMatthias Ringwald  * @param inquriy_mode see bluetooth_defines.h
3929f6858d14SMatthias Ringwald  */
3930f6858d14SMatthias Ringwald void hci_set_inquiry_mode(inquiry_mode_t mode){
3931f6858d14SMatthias Ringwald     hci_stack->inquiry_mode = mode;
3932f6858d14SMatthias Ringwald }
3933f6858d14SMatthias Ringwald 
3934f6858d14SMatthias Ringwald /**
3935d950d659SMatthias Ringwald  * @brief Configure Voice Setting for use with SCO data in HSP/HFP
3936d950d659SMatthias Ringwald  */
3937d950d659SMatthias Ringwald void hci_set_sco_voice_setting(uint16_t voice_setting){
3938d950d659SMatthias Ringwald     hci_stack->sco_voice_setting = voice_setting;
3939d950d659SMatthias Ringwald }
3940d950d659SMatthias Ringwald 
3941d950d659SMatthias Ringwald /**
3942d950d659SMatthias Ringwald  * @brief Get SCO Voice Setting
3943d950d659SMatthias Ringwald  * @return current voice setting
3944d950d659SMatthias Ringwald  */
39450cb5b971SMatthias Ringwald uint16_t hci_get_sco_voice_setting(void){
3946d950d659SMatthias Ringwald     return hci_stack->sco_voice_setting;
3947d950d659SMatthias Ringwald }
3948d950d659SMatthias Ringwald 
3949b3aad8daSMatthias Ringwald /** @brief Get SCO packet length for current SCO Voice setting
3950b3aad8daSMatthias Ringwald  *  @note  Using SCO packets of the exact length is required for USB transfer
3951b3aad8daSMatthias Ringwald  *  @return Length of SCO packets in bytes (not audio frames)
3952b3aad8daSMatthias Ringwald  */
3953b3aad8daSMatthias Ringwald int hci_get_sco_packet_length(void){
3954b3aad8daSMatthias Ringwald     // see Core Spec for H2 USB Transfer.
3955b3aad8daSMatthias Ringwald     if (hci_stack->sco_voice_setting & 0x0020) return 51;
3956b3aad8daSMatthias Ringwald     return 27;
3957b3aad8daSMatthias Ringwald }
395835454696SMatthias Ringwald #endif
3959b3aad8daSMatthias Ringwald 
3960d950d659SMatthias Ringwald /**
3961d23838ecSMatthias Ringwald  * @brief Set callback for Bluetooth Hardware Error
3962d23838ecSMatthias Ringwald  */
3963c2e1fa60SMatthias Ringwald void hci_set_hardware_error_callback(void (*fn)(uint8_t error)){
3964d23838ecSMatthias Ringwald     hci_stack->hardware_error_callback = fn;
3965d23838ecSMatthias Ringwald }
3966d23838ecSMatthias Ringwald 
396771de195eSMatthias Ringwald void hci_disconnect_all(void){
3968665d90f2SMatthias Ringwald     btstack_linked_list_iterator_t it;
3969665d90f2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &hci_stack->connections);
3970665d90f2SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
3971665d90f2SMatthias Ringwald         hci_connection_t * con = (hci_connection_t*) btstack_linked_list_iterator_next(&it);
397204a6ef8cSmatthias.ringwald         if (con->state == SENT_DISCONNECT) continue;
397304a6ef8cSmatthias.ringwald         con->state = SEND_DISCONNECT;
397404a6ef8cSmatthias.ringwald     }
3975d31fba26S[email protected]     hci_run();
397604a6ef8cSmatthias.ringwald }
397733373e40SMatthias Ringwald 
397833373e40SMatthias Ringwald uint16_t hci_get_manufacturer(void){
397933373e40SMatthias Ringwald     return hci_stack->manufacturer;
398033373e40SMatthias Ringwald }
3981