xref: /btstack/platform/daemon/src/daemon.c (revision 2531c97e167e1cae4616c774a6c07906b45ebb44)
1*2531c97eSMatthias Ringwald /*
2*2531c97eSMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*2531c97eSMatthias Ringwald  *
4*2531c97eSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*2531c97eSMatthias Ringwald  * modification, are permitted provided that the following conditions
6*2531c97eSMatthias Ringwald  * are met:
7*2531c97eSMatthias Ringwald  *
8*2531c97eSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*2531c97eSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*2531c97eSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*2531c97eSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*2531c97eSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*2531c97eSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*2531c97eSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*2531c97eSMatthias Ringwald  *    from this software without specific prior written permission.
16*2531c97eSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*2531c97eSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*2531c97eSMatthias Ringwald  *    monetary gain.
19*2531c97eSMatthias Ringwald  *
20*2531c97eSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*2531c97eSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*2531c97eSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*2531c97eSMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*2531c97eSMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*2531c97eSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*2531c97eSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*2531c97eSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*2531c97eSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*2531c97eSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*2531c97eSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*2531c97eSMatthias Ringwald  * SUCH DAMAGE.
32*2531c97eSMatthias Ringwald  *
33*2531c97eSMatthias Ringwald  * Please inquire about commercial licensing options at
34*2531c97eSMatthias Ringwald  * [email protected]
35*2531c97eSMatthias Ringwald  *
36*2531c97eSMatthias Ringwald  */
37*2531c97eSMatthias Ringwald 
38*2531c97eSMatthias Ringwald /*
39*2531c97eSMatthias Ringwald  *  daemon.c
40*2531c97eSMatthias Ringwald  *
41*2531c97eSMatthias Ringwald  *  Created by Matthias Ringwald on 7/1/09.
42*2531c97eSMatthias Ringwald  *
43*2531c97eSMatthias Ringwald  *  BTstack background daemon
44*2531c97eSMatthias Ringwald  *
45*2531c97eSMatthias Ringwald  */
46*2531c97eSMatthias Ringwald 
47*2531c97eSMatthias Ringwald #include "btstack_config.h"
48*2531c97eSMatthias Ringwald 
49*2531c97eSMatthias Ringwald #include <pthread.h>
50*2531c97eSMatthias Ringwald #include <signal.h>
51*2531c97eSMatthias Ringwald #include <stdio.h>
52*2531c97eSMatthias Ringwald #include <stdlib.h>
53*2531c97eSMatthias Ringwald #include <strings.h>
54*2531c97eSMatthias Ringwald #include <unistd.h>
55*2531c97eSMatthias Ringwald 
56*2531c97eSMatthias Ringwald #include <getopt.h>
57*2531c97eSMatthias Ringwald 
58*2531c97eSMatthias Ringwald #include "btstack.h"
59*2531c97eSMatthias Ringwald #include "btstack_client.h"
60*2531c97eSMatthias Ringwald #include "btstack_debug.h"
61*2531c97eSMatthias Ringwald #include "btstack_device_name_db.h"
62*2531c97eSMatthias Ringwald #include "btstack_event.h"
63*2531c97eSMatthias Ringwald #include "btstack_linked_list.h"
64*2531c97eSMatthias Ringwald #include "btstack_run_loop.h"
65*2531c97eSMatthias Ringwald #include "btstack_run_loop_posix.h"
66*2531c97eSMatthias Ringwald #include "btstack_version.h"
67*2531c97eSMatthias Ringwald #include "classic/btstack_link_key_db.h"
68*2531c97eSMatthias Ringwald #include "classic/rfcomm.h"
69*2531c97eSMatthias Ringwald #include "classic/sdp_server.h"
70*2531c97eSMatthias Ringwald #include "classic/sdp_client.h"
71*2531c97eSMatthias Ringwald #include "classic/sdp_query_rfcomm.h"
72*2531c97eSMatthias Ringwald #include "hci.h"
73*2531c97eSMatthias Ringwald #include "hci_cmd.h"
74*2531c97eSMatthias Ringwald #include "hci_dump.h"
75*2531c97eSMatthias Ringwald #include "hci_transport.h"
76*2531c97eSMatthias Ringwald #include "l2cap.h"
77*2531c97eSMatthias Ringwald #include "rfcomm_service_db.h"
78*2531c97eSMatthias Ringwald #include "socket_connection.h"
79*2531c97eSMatthias Ringwald 
80*2531c97eSMatthias Ringwald #ifdef ENABLE_BLE
81*2531c97eSMatthias Ringwald #include "ble/gatt_client.h"
82*2531c97eSMatthias Ringwald #include "ble/att_server.h"
83*2531c97eSMatthias Ringwald #include "ble/att_db.h"
84*2531c97eSMatthias Ringwald #include "ble/le_device_db.h"
85*2531c97eSMatthias Ringwald #include "ble/sm.h"
86*2531c97eSMatthias Ringwald #endif
87*2531c97eSMatthias Ringwald 
88*2531c97eSMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
89*2531c97eSMatthias Ringwald #include <CoreFoundation/CoreFoundation.h>
90*2531c97eSMatthias Ringwald #include <notify.h>
91*2531c97eSMatthias Ringwald #include "../port/ios/src/btstack_control_iphone.h"
92*2531c97eSMatthias Ringwald #include "../port/ios/src/platform_iphone.h"
93*2531c97eSMatthias Ringwald // support for "enforece wake device" in h4 - used by iOS power management
94*2531c97eSMatthias Ringwald extern void hci_transport_h4_iphone_set_enforce_wake_device(char *path);
95*2531c97eSMatthias Ringwald #endif
96*2531c97eSMatthias Ringwald 
97*2531c97eSMatthias Ringwald // copy of prototypes
98*2531c97eSMatthias Ringwald const btstack_device_name_db_t * btstack_device_name_db_cocoa_instance(void);
99*2531c97eSMatthias Ringwald const btstack_device_name_db_t * btstack_device_name_db_fs_instance(void);
100*2531c97eSMatthias Ringwald const btstack_link_key_db_t * btstack_link_key_db_cocoa_instance(void);
101*2531c97eSMatthias Ringwald const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void);
102*2531c97eSMatthias Ringwald 
103*2531c97eSMatthias Ringwald #ifndef BTSTACK_LOG_FILE
104*2531c97eSMatthias Ringwald #define BTSTACK_LOG_FILE "/tmp/hci_dump.pklg"
105*2531c97eSMatthias Ringwald #endif
106*2531c97eSMatthias Ringwald 
107*2531c97eSMatthias Ringwald // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT
108*2531c97eSMatthias Ringwald #ifndef BTSTACK_LOG_TYPE
109*2531c97eSMatthias Ringwald #define BTSTACK_LOG_TYPE HCI_DUMP_PACKETLOGGER
110*2531c97eSMatthias Ringwald #endif
111*2531c97eSMatthias Ringwald 
112*2531c97eSMatthias Ringwald #define DAEMON_NO_ACTIVE_CLIENT_TIMEOUT 10000
113*2531c97eSMatthias Ringwald 
114*2531c97eSMatthias Ringwald #define ATT_MAX_LONG_ATTRIBUTE_SIZE 512
115*2531c97eSMatthias Ringwald 
116*2531c97eSMatthias Ringwald 
117*2531c97eSMatthias Ringwald #define SERVICE_LENGTH                      20
118*2531c97eSMatthias Ringwald #define CHARACTERISTIC_LENGTH               24
119*2531c97eSMatthias Ringwald #define CHARACTERISTIC_DESCRIPTOR_LENGTH    18
120*2531c97eSMatthias Ringwald 
121*2531c97eSMatthias Ringwald // ATT_MTU - 1
122*2531c97eSMatthias Ringwald #define ATT_MAX_ATTRIBUTE_SIZE 22
123*2531c97eSMatthias Ringwald 
124*2531c97eSMatthias Ringwald // HCI CMD OGF/OCF
125*2531c97eSMatthias Ringwald #define READ_CMD_OGF(buffer) (buffer[1] >> 2)
126*2531c97eSMatthias Ringwald #define READ_CMD_OCF(buffer) ((buffer[1] & 0x03) << 8 | buffer[0])
127*2531c97eSMatthias Ringwald 
128*2531c97eSMatthias Ringwald typedef struct {
129*2531c97eSMatthias Ringwald     // linked list - assert: first field
130*2531c97eSMatthias Ringwald     btstack_linked_item_t    item;
131*2531c97eSMatthias Ringwald 
132*2531c97eSMatthias Ringwald     // connection
133*2531c97eSMatthias Ringwald     connection_t * connection;
134*2531c97eSMatthias Ringwald 
135*2531c97eSMatthias Ringwald     btstack_linked_list_t rfcomm_cids;
136*2531c97eSMatthias Ringwald     btstack_linked_list_t rfcomm_services;
137*2531c97eSMatthias Ringwald     btstack_linked_list_t l2cap_cids;
138*2531c97eSMatthias Ringwald     btstack_linked_list_t l2cap_psms;
139*2531c97eSMatthias Ringwald     btstack_linked_list_t sdp_record_handles;
140*2531c97eSMatthias Ringwald     btstack_linked_list_t gatt_con_handles;
141*2531c97eSMatthias Ringwald     // power mode
142*2531c97eSMatthias Ringwald     HCI_POWER_MODE power_mode;
143*2531c97eSMatthias Ringwald 
144*2531c97eSMatthias Ringwald     // discoverable
145*2531c97eSMatthias Ringwald     uint8_t        discoverable;
146*2531c97eSMatthias Ringwald 
147*2531c97eSMatthias Ringwald } client_state_t;
148*2531c97eSMatthias Ringwald 
149*2531c97eSMatthias Ringwald typedef struct btstack_linked_list_uint32 {
150*2531c97eSMatthias Ringwald     btstack_linked_item_t   item;
151*2531c97eSMatthias Ringwald     uint32_t        value;
152*2531c97eSMatthias Ringwald } btstack_linked_list_uint32_t;
153*2531c97eSMatthias Ringwald 
154*2531c97eSMatthias Ringwald typedef struct btstack_linked_list_connection {
155*2531c97eSMatthias Ringwald     btstack_linked_item_t   item;
156*2531c97eSMatthias Ringwald     connection_t  * connection;
157*2531c97eSMatthias Ringwald } btstack_linked_list_connection_t;
158*2531c97eSMatthias Ringwald 
159*2531c97eSMatthias Ringwald typedef struct btstack_linked_list_gatt_client_helper{
160*2531c97eSMatthias Ringwald     btstack_linked_item_t item;
161*2531c97eSMatthias Ringwald     uint16_t con_handle;
162*2531c97eSMatthias Ringwald     connection_t * active_connection;   // the one that started the current query
163*2531c97eSMatthias Ringwald     btstack_linked_list_t  all_connections;     // list of all connections that ever used this helper
164*2531c97eSMatthias Ringwald     uint16_t characteristic_length;
165*2531c97eSMatthias Ringwald     uint16_t characteristic_handle;
166*2531c97eSMatthias Ringwald     uint8_t  characteristic_buffer[10 + ATT_MAX_LONG_ATTRIBUTE_SIZE];   // header for sending event right away
167*2531c97eSMatthias Ringwald     uint8_t  long_query_type;
168*2531c97eSMatthias Ringwald } btstack_linked_list_gatt_client_helper_t;
169*2531c97eSMatthias Ringwald 
170*2531c97eSMatthias Ringwald // MARK: prototypes
171*2531c97eSMatthias Ringwald static void handle_sdp_rfcomm_service_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
172*2531c97eSMatthias Ringwald static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
173*2531c97eSMatthias Ringwald #ifdef ENABLE_BLE
174*2531c97eSMatthias Ringwald static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size);
175*2531c97eSMatthias Ringwald #endif
176*2531c97eSMatthias Ringwald static void dummy_bluetooth_status_handler(BLUETOOTH_STATE state);
177*2531c97eSMatthias Ringwald static client_state_t * client_for_connection(connection_t *connection);
178*2531c97eSMatthias Ringwald static int              clients_require_power_on(void);
179*2531c97eSMatthias Ringwald static int              clients_require_discoverable(void);
180*2531c97eSMatthias Ringwald static void              clients_clear_power_request(void);
181*2531c97eSMatthias Ringwald static void start_power_off_timer(void);
182*2531c97eSMatthias Ringwald static void stop_power_off_timer(void);
183*2531c97eSMatthias Ringwald static client_state_t * client_for_connection(connection_t *connection);
184*2531c97eSMatthias Ringwald static void hci_emit_system_bluetooth_enabled(uint8_t enabled);
185*2531c97eSMatthias Ringwald static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size);
186*2531c97eSMatthias Ringwald 
187*2531c97eSMatthias Ringwald 
188*2531c97eSMatthias Ringwald // MARK: globals
189*2531c97eSMatthias Ringwald static const hci_transport_t * transport;
190*2531c97eSMatthias Ringwald static hci_transport_config_uart_t hci_transport_config_uart;
191*2531c97eSMatthias Ringwald static btstack_timer_source_t timeout;
192*2531c97eSMatthias Ringwald static uint8_t timeout_active = 0;
193*2531c97eSMatthias Ringwald static int power_management_sleep = 0;
194*2531c97eSMatthias Ringwald static btstack_linked_list_t clients = NULL;        // list of connected clients `
195*2531c97eSMatthias Ringwald #ifdef ENABLE_BLE
196*2531c97eSMatthias Ringwald static btstack_linked_list_t gatt_client_helpers = NULL;   // list of used gatt client (helpers)
197*2531c97eSMatthias Ringwald #endif
198*2531c97eSMatthias Ringwald 
199*2531c97eSMatthias Ringwald static void (*bluetooth_status_handler)(BLUETOOTH_STATE state) = dummy_bluetooth_status_handler;
200*2531c97eSMatthias Ringwald 
201*2531c97eSMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
202*2531c97eSMatthias Ringwald 
203*2531c97eSMatthias Ringwald static int global_enable = 0;
204*2531c97eSMatthias Ringwald 
205*2531c97eSMatthias Ringwald static btstack_link_key_db_t    const * btstack_link_key_db = NULL;
206*2531c97eSMatthias Ringwald static btstack_device_name_db_t const * btstack_device_name_db = NULL;
207*2531c97eSMatthias Ringwald // static int rfcomm_channel_generator = 1;
208*2531c97eSMatthias Ringwald 
209*2531c97eSMatthias Ringwald static uint8_t   attribute_value[1000];
210*2531c97eSMatthias Ringwald static const int attribute_value_buffer_size = sizeof(attribute_value);
211*2531c97eSMatthias Ringwald static uint8_t serviceSearchPattern[200];
212*2531c97eSMatthias Ringwald static uint8_t attributeIDList[50];
213*2531c97eSMatthias Ringwald static void * sdp_client_query_connection;
214*2531c97eSMatthias Ringwald 
215*2531c97eSMatthias Ringwald static int loggingEnabled;
216*2531c97eSMatthias Ringwald 
217*2531c97eSMatthias Ringwald // stashed code from l2cap.c and rfcomm.c -- needed for new implementation
218*2531c97eSMatthias Ringwald #if 0
219*2531c97eSMatthias Ringwald static void l2cap_emit_credits(l2cap_channel_t *channel, uint8_t credits) {
220*2531c97eSMatthias Ringwald 
221*2531c97eSMatthias Ringwald     log_info("L2CAP_EVENT_CREDITS local_cid 0x%x credits %u", channel->local_cid, credits);
222*2531c97eSMatthias Ringwald 
223*2531c97eSMatthias Ringwald     uint8_t event[5];
224*2531c97eSMatthias Ringwald     event[0] = L2CAP_EVENT_CREDITS;
225*2531c97eSMatthias Ringwald     event[1] = sizeof(event) - 2;
226*2531c97eSMatthias Ringwald     little_endian_store_16(event, 2, channel->local_cid);
227*2531c97eSMatthias Ringwald     event[4] = credits;
228*2531c97eSMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
229*2531c97eSMatthias Ringwald     l2cap_dispatch(channel, HCI_EVENT_PACKET, event, sizeof(event));
230*2531c97eSMatthias Ringwald }
231*2531c97eSMatthias Ringwald 
232*2531c97eSMatthias Ringwald static void l2cap_hand_out_credits(void){
233*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
234*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &l2cap_channels);
235*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
236*2531c97eSMatthias Ringwald         l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
237*2531c97eSMatthias Ringwald         if (channel->state != L2CAP_STATE_OPEN) continue;
238*2531c97eSMatthias Ringwald         if (!hci_number_free_acl_slots_for_handle(channel->handle)) return;
239*2531c97eSMatthias Ringwald         l2cap_emit_credits(channel, 1);
240*2531c97eSMatthias Ringwald     }
241*2531c97eSMatthias Ringwald }
242*2531c97eSMatthias Ringwald static void rfcomm_emit_credits(rfcomm_channel_t * channel, uint8_t credits) {
243*2531c97eSMatthias Ringwald     log_info("RFCOMM_EVENT_CREDITS cid 0x%02x credits %u", channel->rfcomm_cid, credits);
244*2531c97eSMatthias Ringwald     uint8_t event[5];
245*2531c97eSMatthias Ringwald     event[0] = RFCOMM_EVENT_CREDITS;
246*2531c97eSMatthias Ringwald     event[1] = sizeof(event) - 2;
247*2531c97eSMatthias Ringwald     little_endian_store_16(event, 2, channel->rfcomm_cid);
248*2531c97eSMatthias Ringwald     event[4] = credits;
249*2531c97eSMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
250*2531c97eSMatthias Ringwald     (*app_packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
251*2531c97eSMatthias Ringwald }
252*2531c97eSMatthias Ringwald static void rfcomm_hand_out_credits(void){
253*2531c97eSMatthias Ringwald     btstack_linked_item_t * it;
254*2531c97eSMatthias Ringwald     for (it = (btstack_linked_item_t *) rfcomm_channels; it ; it = it->next){
255*2531c97eSMatthias Ringwald         rfcomm_channel_t * channel = (rfcomm_channel_t *) it;
256*2531c97eSMatthias Ringwald         if (channel->state != RFCOMM_CHANNEL_OPEN) {
257*2531c97eSMatthias Ringwald             // log_info("RFCOMM_EVENT_CREDITS: multiplexer not open");
258*2531c97eSMatthias Ringwald             continue;
259*2531c97eSMatthias Ringwald         }
260*2531c97eSMatthias Ringwald         if (!channel->credits_outgoing) {
261*2531c97eSMatthias Ringwald             // log_info("RFCOMM_EVENT_CREDITS: no outgoing credits");
262*2531c97eSMatthias Ringwald             continue;
263*2531c97eSMatthias Ringwald         }
264*2531c97eSMatthias Ringwald         // channel open, multiplexer has l2cap credits and we didn't hand out credit before -> go!
265*2531c97eSMatthias Ringwald         // log_info("RFCOMM_EVENT_CREDITS: 1");
266*2531c97eSMatthias Ringwald         rfcomm_emit_credits(channel, 1);
267*2531c97eSMatthias Ringwald     }
268*2531c97eSMatthias Ringwald }
269*2531c97eSMatthias Ringwald 
270*2531c97eSMatthias Ringwald #endif
271*2531c97eSMatthias Ringwald 
272*2531c97eSMatthias Ringwald static void dummy_bluetooth_status_handler(BLUETOOTH_STATE state){
273*2531c97eSMatthias Ringwald     log_info("Bluetooth status: %u\n", state);
274*2531c97eSMatthias Ringwald };
275*2531c97eSMatthias Ringwald 
276*2531c97eSMatthias Ringwald static void daemon_no_connections_timeout(struct btstack_timer_source *ts){
277*2531c97eSMatthias Ringwald     if (clients_require_power_on()) return;    // false alarm :)
278*2531c97eSMatthias Ringwald     log_info("No active client connection for %u seconds -> POWER OFF\n", DAEMON_NO_ACTIVE_CLIENT_TIMEOUT/1000);
279*2531c97eSMatthias Ringwald     hci_power_control(HCI_POWER_OFF);
280*2531c97eSMatthias Ringwald }
281*2531c97eSMatthias Ringwald 
282*2531c97eSMatthias Ringwald 
283*2531c97eSMatthias Ringwald static void add_uint32_to_list(btstack_linked_list_t *list, uint32_t value){
284*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
285*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, list);
286*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
287*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
288*2531c97eSMatthias Ringwald         if ( item->value == value) return; // already in list
289*2531c97eSMatthias Ringwald     }
290*2531c97eSMatthias Ringwald 
291*2531c97eSMatthias Ringwald     btstack_linked_list_uint32_t * item = malloc(sizeof(btstack_linked_list_uint32_t));
292*2531c97eSMatthias Ringwald     if (!item) return;
293*2531c97eSMatthias Ringwald     item->value = value;
294*2531c97eSMatthias Ringwald     btstack_linked_list_add(list, (btstack_linked_item_t *) item);
295*2531c97eSMatthias Ringwald }
296*2531c97eSMatthias Ringwald 
297*2531c97eSMatthias Ringwald static void remove_and_free_uint32_from_list(btstack_linked_list_t *list, uint32_t value){
298*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
299*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, list);
300*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
301*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
302*2531c97eSMatthias Ringwald         if ( item->value != value) continue;
303*2531c97eSMatthias Ringwald         btstack_linked_list_remove(list, (btstack_linked_item_t *) item);
304*2531c97eSMatthias Ringwald         free(item);
305*2531c97eSMatthias Ringwald     }
306*2531c97eSMatthias Ringwald }
307*2531c97eSMatthias Ringwald 
308*2531c97eSMatthias Ringwald static void daemon_add_client_rfcomm_service(connection_t * connection, uint16_t service_channel){
309*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
310*2531c97eSMatthias Ringwald     if (!client_state) return;
311*2531c97eSMatthias Ringwald     add_uint32_to_list(&client_state->rfcomm_services, service_channel);
312*2531c97eSMatthias Ringwald }
313*2531c97eSMatthias Ringwald 
314*2531c97eSMatthias Ringwald static void daemon_remove_client_rfcomm_service(connection_t * connection, uint16_t service_channel){
315*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
316*2531c97eSMatthias Ringwald     if (!client_state) return;
317*2531c97eSMatthias Ringwald     remove_and_free_uint32_from_list(&client_state->rfcomm_services, service_channel);
318*2531c97eSMatthias Ringwald }
319*2531c97eSMatthias Ringwald 
320*2531c97eSMatthias Ringwald static void daemon_add_client_rfcomm_channel(connection_t * connection, uint16_t cid){
321*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
322*2531c97eSMatthias Ringwald     if (!client_state) return;
323*2531c97eSMatthias Ringwald     add_uint32_to_list(&client_state->rfcomm_cids, cid);
324*2531c97eSMatthias Ringwald }
325*2531c97eSMatthias Ringwald 
326*2531c97eSMatthias Ringwald static void daemon_remove_client_rfcomm_channel(connection_t * connection, uint16_t cid){
327*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
328*2531c97eSMatthias Ringwald     if (!client_state) return;
329*2531c97eSMatthias Ringwald     remove_and_free_uint32_from_list(&client_state->rfcomm_cids, cid);
330*2531c97eSMatthias Ringwald }
331*2531c97eSMatthias Ringwald 
332*2531c97eSMatthias Ringwald static void daemon_add_client_l2cap_service(connection_t * connection, uint16_t psm){
333*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
334*2531c97eSMatthias Ringwald     if (!client_state) return;
335*2531c97eSMatthias Ringwald     add_uint32_to_list(&client_state->l2cap_psms, psm);
336*2531c97eSMatthias Ringwald }
337*2531c97eSMatthias Ringwald 
338*2531c97eSMatthias Ringwald static void daemon_remove_client_l2cap_service(connection_t * connection, uint16_t psm){
339*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
340*2531c97eSMatthias Ringwald     if (!client_state) return;
341*2531c97eSMatthias Ringwald     remove_and_free_uint32_from_list(&client_state->l2cap_psms, psm);
342*2531c97eSMatthias Ringwald }
343*2531c97eSMatthias Ringwald 
344*2531c97eSMatthias Ringwald static void daemon_add_client_l2cap_channel(connection_t * connection, uint16_t cid){
345*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
346*2531c97eSMatthias Ringwald     if (!client_state) return;
347*2531c97eSMatthias Ringwald     add_uint32_to_list(&client_state->l2cap_cids, cid);
348*2531c97eSMatthias Ringwald }
349*2531c97eSMatthias Ringwald 
350*2531c97eSMatthias Ringwald static void daemon_remove_client_l2cap_channel(connection_t * connection, uint16_t cid){
351*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
352*2531c97eSMatthias Ringwald     if (!client_state) return;
353*2531c97eSMatthias Ringwald     remove_and_free_uint32_from_list(&client_state->l2cap_cids, cid);
354*2531c97eSMatthias Ringwald }
355*2531c97eSMatthias Ringwald 
356*2531c97eSMatthias Ringwald static void daemon_add_client_sdp_service_record_handle(connection_t * connection, uint32_t handle){
357*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
358*2531c97eSMatthias Ringwald     if (!client_state) return;
359*2531c97eSMatthias Ringwald     add_uint32_to_list(&client_state->sdp_record_handles, handle);
360*2531c97eSMatthias Ringwald }
361*2531c97eSMatthias Ringwald 
362*2531c97eSMatthias Ringwald static void daemon_remove_client_sdp_service_record_handle(connection_t * connection, uint32_t handle){
363*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
364*2531c97eSMatthias Ringwald     if (!client_state) return;
365*2531c97eSMatthias Ringwald     remove_and_free_uint32_from_list(&client_state->sdp_record_handles, handle);
366*2531c97eSMatthias Ringwald }
367*2531c97eSMatthias Ringwald 
368*2531c97eSMatthias Ringwald #ifdef ENABLE_BLE
369*2531c97eSMatthias Ringwald static void daemon_add_gatt_client_handle(connection_t * connection, uint32_t handle){
370*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
371*2531c97eSMatthias Ringwald     if (!client_state) return;
372*2531c97eSMatthias Ringwald 
373*2531c97eSMatthias Ringwald     // check if handle already exists in the gatt_con_handles list
374*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
375*2531c97eSMatthias Ringwald     int handle_found = 0;
376*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &client_state->gatt_con_handles);
377*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
378*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
379*2531c97eSMatthias Ringwald         if (item->value == handle){
380*2531c97eSMatthias Ringwald             handle_found = 1;
381*2531c97eSMatthias Ringwald             break;
382*2531c97eSMatthias Ringwald         }
383*2531c97eSMatthias Ringwald     }
384*2531c97eSMatthias Ringwald     // if handle doesn't exist add it to gatt_con_handles
385*2531c97eSMatthias Ringwald     if (!handle_found){
386*2531c97eSMatthias Ringwald         add_uint32_to_list(&client_state->gatt_con_handles, handle);
387*2531c97eSMatthias Ringwald     }
388*2531c97eSMatthias Ringwald 
389*2531c97eSMatthias Ringwald     // check if there is a helper with given handle
390*2531c97eSMatthias Ringwald     btstack_linked_list_gatt_client_helper_t * gatt_helper = NULL;
391*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &gatt_client_helpers);
392*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
393*2531c97eSMatthias Ringwald         btstack_linked_list_gatt_client_helper_t * item = (btstack_linked_list_gatt_client_helper_t*) btstack_linked_list_iterator_next(&it);
394*2531c97eSMatthias Ringwald         if (item->con_handle == handle){
395*2531c97eSMatthias Ringwald             gatt_helper = item;
396*2531c97eSMatthias Ringwald             break;
397*2531c97eSMatthias Ringwald         }
398*2531c97eSMatthias Ringwald     }
399*2531c97eSMatthias Ringwald 
400*2531c97eSMatthias Ringwald     // if gatt_helper doesn't exist, create it and add it to gatt_client_helpers list
401*2531c97eSMatthias Ringwald     if (!gatt_helper){
402*2531c97eSMatthias Ringwald         gatt_helper = malloc(sizeof(btstack_linked_list_gatt_client_helper_t));
403*2531c97eSMatthias Ringwald         if (!gatt_helper) return;
404*2531c97eSMatthias Ringwald         memset(gatt_helper, 0, sizeof(btstack_linked_list_gatt_client_helper_t));
405*2531c97eSMatthias Ringwald         gatt_helper->con_handle = handle;
406*2531c97eSMatthias Ringwald         btstack_linked_list_add(&gatt_client_helpers, (btstack_linked_item_t *) gatt_helper);
407*2531c97eSMatthias Ringwald     }
408*2531c97eSMatthias Ringwald 
409*2531c97eSMatthias Ringwald     // check if connection exists
410*2531c97eSMatthias Ringwald     int connection_found = 0;
411*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &gatt_helper->all_connections);
412*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
413*2531c97eSMatthias Ringwald         btstack_linked_list_connection_t * item = (btstack_linked_list_connection_t*) btstack_linked_list_iterator_next(&it);
414*2531c97eSMatthias Ringwald         if (item->connection == connection){
415*2531c97eSMatthias Ringwald             connection_found = 1;
416*2531c97eSMatthias Ringwald             break;
417*2531c97eSMatthias Ringwald         }
418*2531c97eSMatthias Ringwald     }
419*2531c97eSMatthias Ringwald 
420*2531c97eSMatthias Ringwald     // if connection is not found, add it to the all_connections, and set it as active connection
421*2531c97eSMatthias Ringwald     if (!connection_found){
422*2531c97eSMatthias Ringwald         btstack_linked_list_connection_t * con = malloc(sizeof(btstack_linked_list_connection_t));
423*2531c97eSMatthias Ringwald         if (!con) return;
424*2531c97eSMatthias Ringwald         memset(con, 0, sizeof(btstack_linked_list_connection_t));
425*2531c97eSMatthias Ringwald         con->connection = connection;
426*2531c97eSMatthias Ringwald         btstack_linked_list_add(&gatt_helper->all_connections, (btstack_linked_item_t *)con);
427*2531c97eSMatthias Ringwald     }
428*2531c97eSMatthias Ringwald }
429*2531c97eSMatthias Ringwald 
430*2531c97eSMatthias Ringwald 
431*2531c97eSMatthias Ringwald static void daemon_remove_gatt_client_handle(connection_t * connection, uint32_t handle){
432*2531c97eSMatthias Ringwald     // PART 1 - uses connection & handle
433*2531c97eSMatthias Ringwald     // might be extracted or vanish totally
434*2531c97eSMatthias Ringwald     client_state_t * client_state = client_for_connection(connection);
435*2531c97eSMatthias Ringwald     if (!client_state) return;
436*2531c97eSMatthias Ringwald 
437*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
438*2531c97eSMatthias Ringwald     // remove handle from gatt_con_handles list
439*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &client_state->gatt_con_handles);
440*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
441*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
442*2531c97eSMatthias Ringwald         if (item->value == handle){
443*2531c97eSMatthias Ringwald             btstack_linked_list_remove(&client_state->gatt_con_handles, (btstack_linked_item_t *) item);
444*2531c97eSMatthias Ringwald             free(item);
445*2531c97eSMatthias Ringwald         }
446*2531c97eSMatthias Ringwald     }
447*2531c97eSMatthias Ringwald 
448*2531c97eSMatthias Ringwald     // PART 2 - only uses handle
449*2531c97eSMatthias Ringwald 
450*2531c97eSMatthias Ringwald     // find helper with given handle
451*2531c97eSMatthias Ringwald     btstack_linked_list_gatt_client_helper_t * helper = NULL;
452*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &gatt_client_helpers);
453*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
454*2531c97eSMatthias Ringwald         btstack_linked_list_gatt_client_helper_t * item = (btstack_linked_list_gatt_client_helper_t*) btstack_linked_list_iterator_next(&it);
455*2531c97eSMatthias Ringwald         if (item->con_handle == handle){
456*2531c97eSMatthias Ringwald             helper = item;
457*2531c97eSMatthias Ringwald             break;
458*2531c97eSMatthias Ringwald         }
459*2531c97eSMatthias Ringwald     }
460*2531c97eSMatthias Ringwald 
461*2531c97eSMatthias Ringwald     if (!helper) return;
462*2531c97eSMatthias Ringwald     // remove connection from helper
463*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &helper->all_connections);
464*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
465*2531c97eSMatthias Ringwald         btstack_linked_list_connection_t * item = (btstack_linked_list_connection_t*) btstack_linked_list_iterator_next(&it);
466*2531c97eSMatthias Ringwald         if (item->connection == connection){
467*2531c97eSMatthias Ringwald             btstack_linked_list_remove(&helper->all_connections, (btstack_linked_item_t *) item);
468*2531c97eSMatthias Ringwald             free(item);
469*2531c97eSMatthias Ringwald             break;
470*2531c97eSMatthias Ringwald         }
471*2531c97eSMatthias Ringwald     }
472*2531c97eSMatthias Ringwald 
473*2531c97eSMatthias Ringwald     if (helper->active_connection == connection){
474*2531c97eSMatthias Ringwald         helper->active_connection = NULL;
475*2531c97eSMatthias Ringwald     }
476*2531c97eSMatthias Ringwald     // if helper has no more connections, call disconnect
477*2531c97eSMatthias Ringwald     if (helper->all_connections == NULL){
478*2531c97eSMatthias Ringwald         gap_disconnect((hci_con_handle_t) helper->con_handle);
479*2531c97eSMatthias Ringwald     }
480*2531c97eSMatthias Ringwald }
481*2531c97eSMatthias Ringwald 
482*2531c97eSMatthias Ringwald 
483*2531c97eSMatthias Ringwald static void daemon_remove_gatt_client_helper(uint32_t con_handle){
484*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it, cl;
485*2531c97eSMatthias Ringwald     // find helper with given handle
486*2531c97eSMatthias Ringwald     btstack_linked_list_gatt_client_helper_t * helper = NULL;
487*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &gatt_client_helpers);
488*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
489*2531c97eSMatthias Ringwald         btstack_linked_list_gatt_client_helper_t * item = (btstack_linked_list_gatt_client_helper_t*) btstack_linked_list_iterator_next(&it);
490*2531c97eSMatthias Ringwald         if (item->con_handle == con_handle){
491*2531c97eSMatthias Ringwald             helper = item;
492*2531c97eSMatthias Ringwald             break;
493*2531c97eSMatthias Ringwald         }
494*2531c97eSMatthias Ringwald     }
495*2531c97eSMatthias Ringwald 
496*2531c97eSMatthias Ringwald     if (!helper) return;
497*2531c97eSMatthias Ringwald 
498*2531c97eSMatthias Ringwald     // remove all connection from helper
499*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &helper->all_connections);
500*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
501*2531c97eSMatthias Ringwald         btstack_linked_list_connection_t * item = (btstack_linked_list_connection_t*) btstack_linked_list_iterator_next(&it);
502*2531c97eSMatthias Ringwald         btstack_linked_list_remove(&helper->all_connections, (btstack_linked_item_t *) item);
503*2531c97eSMatthias Ringwald         free(item);
504*2531c97eSMatthias Ringwald     }
505*2531c97eSMatthias Ringwald 
506*2531c97eSMatthias Ringwald     btstack_linked_list_remove(&gatt_client_helpers, (btstack_linked_item_t *) helper);
507*2531c97eSMatthias Ringwald     free(helper);
508*2531c97eSMatthias Ringwald 
509*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&cl, &clients);
510*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&cl)){
511*2531c97eSMatthias Ringwald         client_state_t * client_state = (client_state_t *) btstack_linked_list_iterator_next(&cl);
512*2531c97eSMatthias Ringwald         btstack_linked_list_iterator_init(&it, &client_state->gatt_con_handles);
513*2531c97eSMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&it)){
514*2531c97eSMatthias Ringwald             btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
515*2531c97eSMatthias Ringwald             if (item->value == con_handle){
516*2531c97eSMatthias Ringwald                 btstack_linked_list_remove(&client_state->gatt_con_handles, (btstack_linked_item_t *) item);
517*2531c97eSMatthias Ringwald                 free(item);
518*2531c97eSMatthias Ringwald             }
519*2531c97eSMatthias Ringwald         }
520*2531c97eSMatthias Ringwald     }
521*2531c97eSMatthias Ringwald }
522*2531c97eSMatthias Ringwald #endif
523*2531c97eSMatthias Ringwald 
524*2531c97eSMatthias Ringwald static void daemon_rfcomm_close_connection(client_state_t * daemon_client){
525*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
526*2531c97eSMatthias Ringwald     btstack_linked_list_t *rfcomm_services = &daemon_client->rfcomm_services;
527*2531c97eSMatthias Ringwald     btstack_linked_list_t *rfcomm_cids = &daemon_client->rfcomm_cids;
528*2531c97eSMatthias Ringwald 
529*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, rfcomm_services);
530*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
531*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
532*2531c97eSMatthias Ringwald         rfcomm_unregister_service(item->value);
533*2531c97eSMatthias Ringwald         btstack_linked_list_remove(rfcomm_services, (btstack_linked_item_t *) item);
534*2531c97eSMatthias Ringwald         free(item);
535*2531c97eSMatthias Ringwald     }
536*2531c97eSMatthias Ringwald 
537*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, rfcomm_cids);
538*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
539*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
540*2531c97eSMatthias Ringwald         rfcomm_disconnect(item->value);
541*2531c97eSMatthias Ringwald         btstack_linked_list_remove(rfcomm_cids, (btstack_linked_item_t *) item);
542*2531c97eSMatthias Ringwald         free(item);
543*2531c97eSMatthias Ringwald     }
544*2531c97eSMatthias Ringwald }
545*2531c97eSMatthias Ringwald 
546*2531c97eSMatthias Ringwald 
547*2531c97eSMatthias Ringwald static void daemon_l2cap_close_connection(client_state_t * daemon_client){
548*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
549*2531c97eSMatthias Ringwald     btstack_linked_list_t *l2cap_psms = &daemon_client->l2cap_psms;
550*2531c97eSMatthias Ringwald     btstack_linked_list_t *l2cap_cids = &daemon_client->l2cap_cids;
551*2531c97eSMatthias Ringwald 
552*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, l2cap_psms);
553*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
554*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
555*2531c97eSMatthias Ringwald         l2cap_unregister_service(item->value);
556*2531c97eSMatthias Ringwald         btstack_linked_list_remove(l2cap_psms, (btstack_linked_item_t *) item);
557*2531c97eSMatthias Ringwald         free(item);
558*2531c97eSMatthias Ringwald     }
559*2531c97eSMatthias Ringwald 
560*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, l2cap_cids);
561*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
562*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
563*2531c97eSMatthias Ringwald         l2cap_disconnect(item->value, 0); // note: reason isn't used
564*2531c97eSMatthias Ringwald         btstack_linked_list_remove(l2cap_cids, (btstack_linked_item_t *) item);
565*2531c97eSMatthias Ringwald         free(item);
566*2531c97eSMatthias Ringwald     }
567*2531c97eSMatthias Ringwald }
568*2531c97eSMatthias Ringwald 
569*2531c97eSMatthias Ringwald static void daemon_sdp_close_connection(client_state_t * daemon_client){
570*2531c97eSMatthias Ringwald     btstack_linked_list_t * list = &daemon_client->sdp_record_handles;
571*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
572*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, list);
573*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
574*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
575*2531c97eSMatthias Ringwald         sdp_unregister_service(item->value);
576*2531c97eSMatthias Ringwald         btstack_linked_list_remove(list, (btstack_linked_item_t *) item);
577*2531c97eSMatthias Ringwald         free(item);
578*2531c97eSMatthias Ringwald     }
579*2531c97eSMatthias Ringwald }
580*2531c97eSMatthias Ringwald 
581*2531c97eSMatthias Ringwald static connection_t * connection_for_l2cap_cid(uint16_t cid){
582*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t cl;
583*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&cl, &clients);
584*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&cl)){
585*2531c97eSMatthias Ringwald         client_state_t * client_state = (client_state_t *) btstack_linked_list_iterator_next(&cl);
586*2531c97eSMatthias Ringwald         btstack_linked_list_iterator_t it;
587*2531c97eSMatthias Ringwald         btstack_linked_list_iterator_init(&it, &client_state->l2cap_cids);
588*2531c97eSMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&it)){
589*2531c97eSMatthias Ringwald             btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
590*2531c97eSMatthias Ringwald             if (item->value == cid){
591*2531c97eSMatthias Ringwald                 return client_state->connection;
592*2531c97eSMatthias Ringwald             }
593*2531c97eSMatthias Ringwald         }
594*2531c97eSMatthias Ringwald     }
595*2531c97eSMatthias Ringwald     return NULL;
596*2531c97eSMatthias Ringwald }
597*2531c97eSMatthias Ringwald 
598*2531c97eSMatthias Ringwald static const uint8_t removeServiceRecordHandleAttributeIDList[] = { 0x36, 0x00, 0x05, 0x0A, 0x00, 0x01, 0xFF, 0xFF };
599*2531c97eSMatthias Ringwald 
600*2531c97eSMatthias Ringwald // register a service record
601*2531c97eSMatthias Ringwald // pre: AttributeIDs are in ascending order
602*2531c97eSMatthias Ringwald // pre: ServiceRecordHandle is first attribute and is not already registered in database
603*2531c97eSMatthias Ringwald // @returns status
604*2531c97eSMatthias Ringwald static uint32_t daemon_sdp_create_and_register_service(uint8_t * record){
605*2531c97eSMatthias Ringwald 
606*2531c97eSMatthias Ringwald     // create new handle
607*2531c97eSMatthias Ringwald     uint32_t record_handle = sdp_create_service_record_handle();
608*2531c97eSMatthias Ringwald 
609*2531c97eSMatthias Ringwald     // calculate size of new service record: DES (2 byte len)
610*2531c97eSMatthias Ringwald     // + ServiceRecordHandle attribute (UINT16 UINT32) + size of existing attributes
611*2531c97eSMatthias Ringwald     uint16_t recordSize =  3 + (3 + 5) + de_get_data_size(record);
612*2531c97eSMatthias Ringwald 
613*2531c97eSMatthias Ringwald     // alloc memory for new service record
614*2531c97eSMatthias Ringwald     uint8_t * newRecord = malloc(recordSize);
615*2531c97eSMatthias Ringwald     if (!newRecord) return 0;
616*2531c97eSMatthias Ringwald 
617*2531c97eSMatthias Ringwald     // create DES for new record
618*2531c97eSMatthias Ringwald     de_create_sequence(newRecord);
619*2531c97eSMatthias Ringwald 
620*2531c97eSMatthias Ringwald     // set service record handle
621*2531c97eSMatthias Ringwald     de_add_number(newRecord, DE_UINT, DE_SIZE_16, 0);
622*2531c97eSMatthias Ringwald     de_add_number(newRecord, DE_UINT, DE_SIZE_32, record_handle);
623*2531c97eSMatthias Ringwald 
624*2531c97eSMatthias Ringwald     // add other attributes
625*2531c97eSMatthias Ringwald     sdp_append_attributes_in_attributeIDList(record, (uint8_t *) removeServiceRecordHandleAttributeIDList, 0, recordSize, newRecord);
626*2531c97eSMatthias Ringwald 
627*2531c97eSMatthias Ringwald     uint8_t status = sdp_register_service(newRecord);
628*2531c97eSMatthias Ringwald 
629*2531c97eSMatthias Ringwald     if (status) {
630*2531c97eSMatthias Ringwald         free(newRecord);
631*2531c97eSMatthias Ringwald         return 0;
632*2531c97eSMatthias Ringwald     }
633*2531c97eSMatthias Ringwald 
634*2531c97eSMatthias Ringwald     return record_handle;
635*2531c97eSMatthias Ringwald }
636*2531c97eSMatthias Ringwald 
637*2531c97eSMatthias Ringwald static connection_t * connection_for_rfcomm_cid(uint16_t cid){
638*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t cl;
639*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&cl, &clients);
640*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&cl)){
641*2531c97eSMatthias Ringwald         client_state_t * client_state = (client_state_t *) btstack_linked_list_iterator_next(&cl);
642*2531c97eSMatthias Ringwald         btstack_linked_list_iterator_t it;
643*2531c97eSMatthias Ringwald         btstack_linked_list_iterator_init(&it, &client_state->rfcomm_cids);
644*2531c97eSMatthias Ringwald         while (btstack_linked_list_iterator_has_next(&it)){
645*2531c97eSMatthias Ringwald             btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
646*2531c97eSMatthias Ringwald             if (item->value == cid){
647*2531c97eSMatthias Ringwald                 return client_state->connection;
648*2531c97eSMatthias Ringwald             }
649*2531c97eSMatthias Ringwald         }
650*2531c97eSMatthias Ringwald     }
651*2531c97eSMatthias Ringwald     return NULL;
652*2531c97eSMatthias Ringwald }
653*2531c97eSMatthias Ringwald 
654*2531c97eSMatthias Ringwald #ifdef ENABLE_BLE
655*2531c97eSMatthias Ringwald static void daemon_gatt_client_close_connection(connection_t * connection){
656*2531c97eSMatthias Ringwald     client_state_t * client = client_for_connection(connection);
657*2531c97eSMatthias Ringwald     if (!client) return;
658*2531c97eSMatthias Ringwald 
659*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
660*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &client->gatt_con_handles);
661*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
662*2531c97eSMatthias Ringwald         btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it);
663*2531c97eSMatthias Ringwald         daemon_remove_gatt_client_handle(connection, item->value);
664*2531c97eSMatthias Ringwald     }
665*2531c97eSMatthias Ringwald }
666*2531c97eSMatthias Ringwald #endif
667*2531c97eSMatthias Ringwald 
668*2531c97eSMatthias Ringwald static void daemon_disconnect_client(connection_t * connection){
669*2531c97eSMatthias Ringwald     log_info("Daemon disconnect client %p\n",connection);
670*2531c97eSMatthias Ringwald 
671*2531c97eSMatthias Ringwald     client_state_t * client = client_for_connection(connection);
672*2531c97eSMatthias Ringwald     if (!client) return;
673*2531c97eSMatthias Ringwald 
674*2531c97eSMatthias Ringwald     daemon_sdp_close_connection(client);
675*2531c97eSMatthias Ringwald     daemon_rfcomm_close_connection(client);
676*2531c97eSMatthias Ringwald     daemon_l2cap_close_connection(client);
677*2531c97eSMatthias Ringwald #ifdef ENABLE_BLE
678*2531c97eSMatthias Ringwald     // NOTE: experimental - disconnect all LE connections where GATT Client was used
679*2531c97eSMatthias Ringwald     // gatt_client_disconnect_connection(connection);
680*2531c97eSMatthias Ringwald     daemon_gatt_client_close_connection(connection);
681*2531c97eSMatthias Ringwald #endif
682*2531c97eSMatthias Ringwald 
683*2531c97eSMatthias Ringwald     btstack_linked_list_remove(&clients, (btstack_linked_item_t *) client);
684*2531c97eSMatthias Ringwald     free(client);
685*2531c97eSMatthias Ringwald }
686*2531c97eSMatthias Ringwald 
687*2531c97eSMatthias Ringwald static void hci_emit_btstack_version(void){
688*2531c97eSMatthias Ringwald     log_info("DAEMON_EVENT_VERSION %u.%u", BTSTACK_MAJOR, BTSTACK_MINOR);
689*2531c97eSMatthias Ringwald     uint8_t event[6];
690*2531c97eSMatthias Ringwald     event[0] = DAEMON_EVENT_VERSION;
691*2531c97eSMatthias Ringwald     event[1] = sizeof(event) - 2;
692*2531c97eSMatthias Ringwald     event[2] = BTSTACK_MAJOR;
693*2531c97eSMatthias Ringwald     event[3] = BTSTACK_MINOR;
694*2531c97eSMatthias Ringwald     little_endian_store_16(event, 4, 3257);    // last SVN commit on Google Code + 1
695*2531c97eSMatthias Ringwald     socket_connection_send_packet_all(HCI_EVENT_PACKET, 0, event, sizeof(event));
696*2531c97eSMatthias Ringwald }
697*2531c97eSMatthias Ringwald 
698*2531c97eSMatthias Ringwald static void hci_emit_system_bluetooth_enabled(uint8_t enabled){
699*2531c97eSMatthias Ringwald     log_info("DAEMON_EVENT_SYSTEM_BLUETOOTH_ENABLED %u", enabled);
700*2531c97eSMatthias Ringwald     uint8_t event[3];
701*2531c97eSMatthias Ringwald     event[0] = DAEMON_EVENT_SYSTEM_BLUETOOTH_ENABLED;
702*2531c97eSMatthias Ringwald     event[1] = sizeof(event) - 2;
703*2531c97eSMatthias Ringwald     event[2] = enabled;
704*2531c97eSMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
705*2531c97eSMatthias Ringwald     socket_connection_send_packet_all(HCI_EVENT_PACKET, 0, event, sizeof(event));
706*2531c97eSMatthias Ringwald }
707*2531c97eSMatthias Ringwald 
708*2531c97eSMatthias Ringwald static void send_l2cap_connection_open_failed(connection_t * connection, bd_addr_t address, uint16_t psm, uint8_t status){
709*2531c97eSMatthias Ringwald     // emit error - see l2cap.c:l2cap_emit_channel_opened(..)
710*2531c97eSMatthias Ringwald     uint8_t event[23];
711*2531c97eSMatthias Ringwald     memset(event, 0, sizeof(event));
712*2531c97eSMatthias Ringwald     event[0] = L2CAP_EVENT_CHANNEL_OPENED;
713*2531c97eSMatthias Ringwald     event[1] = sizeof(event) - 2;
714*2531c97eSMatthias Ringwald     event[2] = status;
715*2531c97eSMatthias Ringwald     reverse_bd_addr(address, &event[3]);
716*2531c97eSMatthias Ringwald     // little_endian_store_16(event,  9, channel->handle);
717*2531c97eSMatthias Ringwald     little_endian_store_16(event, 11, psm);
718*2531c97eSMatthias Ringwald     // little_endian_store_16(event, 13, channel->local_cid);
719*2531c97eSMatthias Ringwald     // little_endian_store_16(event, 15, channel->remote_cid);
720*2531c97eSMatthias Ringwald     // little_endian_store_16(event, 17, channel->local_mtu);
721*2531c97eSMatthias Ringwald     // little_endian_store_16(event, 19, channel->remote_mtu);
722*2531c97eSMatthias Ringwald     // little_endian_store_16(event, 21, channel->flush_timeout);
723*2531c97eSMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
724*2531c97eSMatthias Ringwald     socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event));
725*2531c97eSMatthias Ringwald }
726*2531c97eSMatthias Ringwald 
727*2531c97eSMatthias Ringwald static void l2cap_emit_service_registered(void *connection, uint8_t status, uint16_t psm){
728*2531c97eSMatthias Ringwald     uint8_t event[5];
729*2531c97eSMatthias Ringwald     event[0] = L2CAP_EVENT_SERVICE_REGISTERED;
730*2531c97eSMatthias Ringwald     event[1] = sizeof(event) - 2;
731*2531c97eSMatthias Ringwald     event[2] = status;
732*2531c97eSMatthias Ringwald     little_endian_store_16(event, 3, psm);
733*2531c97eSMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
734*2531c97eSMatthias Ringwald     socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event));
735*2531c97eSMatthias Ringwald }
736*2531c97eSMatthias Ringwald 
737*2531c97eSMatthias Ringwald static void rfcomm_emit_service_registered(void *connection, uint8_t status, uint8_t channel){
738*2531c97eSMatthias Ringwald     uint8_t event[4];
739*2531c97eSMatthias Ringwald     event[0] = RFCOMM_EVENT_SERVICE_REGISTERED;
740*2531c97eSMatthias Ringwald     event[1] = sizeof(event) - 2;
741*2531c97eSMatthias Ringwald     event[2] = status;
742*2531c97eSMatthias Ringwald     event[3] = channel;
743*2531c97eSMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
744*2531c97eSMatthias Ringwald     socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event));
745*2531c97eSMatthias Ringwald }
746*2531c97eSMatthias Ringwald 
747*2531c97eSMatthias Ringwald static void send_rfcomm_create_channel_failed(void * connection, bd_addr_t addr, uint8_t server_channel, uint8_t status){
748*2531c97eSMatthias Ringwald     // emit error - see rfcom.c:rfcomm_emit_channel_open_failed_outgoing_memory(..)
749*2531c97eSMatthias Ringwald     uint8_t event[16];
750*2531c97eSMatthias Ringwald     memset(event, 0, sizeof(event));
751*2531c97eSMatthias Ringwald     uint8_t pos = 0;
752*2531c97eSMatthias Ringwald     event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE;
753*2531c97eSMatthias Ringwald     event[pos++] = sizeof(event) - 2;
754*2531c97eSMatthias Ringwald     event[pos++] = status;
755*2531c97eSMatthias Ringwald     reverse_bd_addr(addr, &event[pos]); pos += 6;
756*2531c97eSMatthias Ringwald     little_endian_store_16(event,  pos, 0);   pos += 2;
757*2531c97eSMatthias Ringwald     event[pos++] = server_channel;
758*2531c97eSMatthias Ringwald     little_endian_store_16(event, pos, 0); pos += 2;   // channel ID
759*2531c97eSMatthias Ringwald     little_endian_store_16(event, pos, 0); pos += 2;   // max frame size
760*2531c97eSMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
761*2531c97eSMatthias Ringwald     socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event));
762*2531c97eSMatthias Ringwald }
763*2531c97eSMatthias Ringwald 
764*2531c97eSMatthias Ringwald // data: event(8), len(8), status(8), service_record_handle(32)
765*2531c97eSMatthias Ringwald static void sdp_emit_service_registered(void *connection, uint32_t handle, uint8_t status) {
766*2531c97eSMatthias Ringwald     uint8_t event[7];
767*2531c97eSMatthias Ringwald     event[0] = SDP_EVENT_SERVICE_REGISTERED;
768*2531c97eSMatthias Ringwald     event[1] = sizeof(event) - 2;
769*2531c97eSMatthias Ringwald     event[2] = status;
770*2531c97eSMatthias Ringwald     little_endian_store_32(event, 3, handle);
771*2531c97eSMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
772*2531c97eSMatthias Ringwald     socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event));
773*2531c97eSMatthias Ringwald }
774*2531c97eSMatthias Ringwald 
775*2531c97eSMatthias Ringwald #ifdef ENABLE_BLE
776*2531c97eSMatthias Ringwald 
777*2531c97eSMatthias Ringwald btstack_linked_list_gatt_client_helper_t * daemon_get_gatt_client_helper(uint16_t handle) {
778*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_t it;
779*2531c97eSMatthias Ringwald     if (!gatt_client_helpers) return NULL;
780*2531c97eSMatthias Ringwald     log_info("daemon_get_gatt_client_helper for handle 0x%02x", handle);
781*2531c97eSMatthias Ringwald 
782*2531c97eSMatthias Ringwald     btstack_linked_list_iterator_init(&it, &gatt_client_helpers);
783*2531c97eSMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
784*2531c97eSMatthias Ringwald         btstack_linked_list_gatt_client_helper_t * item = (btstack_linked_list_gatt_client_helper_t*) btstack_linked_list_iterator_next(&it);
785*2531c97eSMatthias Ringwald         if (!item ) {
786*2531c97eSMatthias Ringwald             log_info("daemon_get_gatt_client_helper gatt_client_helpers null item");
787*2531c97eSMatthias Ringwald             break;
788*2531c97eSMatthias Ringwald         }
789*2531c97eSMatthias Ringwald         if (item->con_handle == handle){
790*2531c97eSMatthias Ringwald             return item;
791*2531c97eSMatthias Ringwald         }
792*2531c97eSMatthias Ringwald     }
793*2531c97eSMatthias Ringwald     log_info("daemon_get_gatt_client_helper for handle 0x%02x is NULL.", handle);
794*2531c97eSMatthias Ringwald     return NULL;
795*2531c97eSMatthias Ringwald }
796*2531c97eSMatthias Ringwald 
797*2531c97eSMatthias Ringwald static void send_gatt_query_complete(connection_t * connection, uint16_t handle, uint8_t status){
798*2531c97eSMatthias Ringwald     // @format H1
799*2531c97eSMatthias Ringwald     uint8_t event[5];
800*2531c97eSMatthias Ringwald     event[0] = GATT_EVENT_QUERY_COMPLETE;
801*2531c97eSMatthias Ringwald     event[1] = 3;
802*2531c97eSMatthias Ringwald     little_endian_store_16(event, 2, handle);
803*2531c97eSMatthias Ringwald     event[4] = status;
804*2531c97eSMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
805*2531c97eSMatthias Ringwald     socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event));
806*2531c97eSMatthias Ringwald }
807*2531c97eSMatthias Ringwald 
808*2531c97eSMatthias Ringwald static void send_gatt_mtu_event(connection_t * connection, uint16_t handle, uint16_t mtu){
809*2531c97eSMatthias Ringwald     uint8_t event[6];
810*2531c97eSMatthias Ringwald     int pos = 0;
811*2531c97eSMatthias Ringwald     event[pos++] = GATT_EVENT_MTU;
812*2531c97eSMatthias Ringwald     event[pos++] = sizeof(event) - 2;
813*2531c97eSMatthias Ringwald     little_endian_store_16(event, pos, handle);
814*2531c97eSMatthias Ringwald     pos += 2;
815*2531c97eSMatthias Ringwald     little_endian_store_16(event, pos, mtu);
816*2531c97eSMatthias Ringwald     pos += 2;
817*2531c97eSMatthias Ringwald     hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
818*2531c97eSMatthias Ringwald     socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event));
819*2531c97eSMatthias Ringwald }
820*2531c97eSMatthias Ringwald 
821*2531c97eSMatthias Ringwald btstack_linked_list_gatt_client_helper_t * daemon_setup_gatt_client_request(connection_t *connection, uint8_t *packet, int track_active_connection) {
822*2531c97eSMatthias Ringwald     hci_con_handle_t handle = little_endian_read_16(packet, 3);
823*2531c97eSMatthias Ringwald     log_info("daemon_setup_gatt_client_request for handle 0x%02x", handle);
824*2531c97eSMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_handle(handle);
825*2531c97eSMatthias Ringwald     if ((hci_con == NULL) || (hci_con->state != OPEN)){
826*2531c97eSMatthias Ringwald         send_gatt_query_complete(connection, handle, GATT_CLIENT_NOT_CONNECTED);
827*2531c97eSMatthias Ringwald         return NULL;
828*2531c97eSMatthias Ringwald     }
829*2531c97eSMatthias Ringwald 
830*2531c97eSMatthias Ringwald     btstack_linked_list_gatt_client_helper_t * helper = daemon_get_gatt_client_helper(handle);
831*2531c97eSMatthias Ringwald 
832*2531c97eSMatthias Ringwald     if (!helper){
833*2531c97eSMatthias Ringwald         log_info("helper does not exist");
834*2531c97eSMatthias Ringwald         helper = malloc(sizeof(btstack_linked_list_gatt_client_helper_t));
835*2531c97eSMatthias Ringwald         if (!helper) return NULL;
836*2531c97eSMatthias Ringwald         memset(helper, 0, sizeof(btstack_linked_list_gatt_client_helper_t));
837*2531c97eSMatthias Ringwald         helper->con_handle = handle;
838*2531c97eSMatthias Ringwald         btstack_linked_list_add(&gatt_client_helpers, (btstack_linked_item_t *) helper);
839*2531c97eSMatthias Ringwald     }
840*2531c97eSMatthias Ringwald 
841*2531c97eSMatthias Ringwald     if (track_active_connection && helper->active_connection){
842*2531c97eSMatthias Ringwald         send_gatt_query_complete(connection, handle, GATT_CLIENT_BUSY);
843*2531c97eSMatthias Ringwald         return NULL;
844*2531c97eSMatthias Ringwald     }
845*2531c97eSMatthias Ringwald 
846*2531c97eSMatthias Ringwald     daemon_add_gatt_client_handle(connection, handle);
847*2531c97eSMatthias Ringwald 
848*2531c97eSMatthias Ringwald     if (track_active_connection){
849*2531c97eSMatthias Ringwald         // remember connection responsible for this request
850*2531c97eSMatthias Ringwald         helper->active_connection = connection;
851*2531c97eSMatthias Ringwald     }
852*2531c97eSMatthias Ringwald 
853*2531c97eSMatthias Ringwald     return helper;
854*2531c97eSMatthias Ringwald }
855*2531c97eSMatthias Ringwald 
856*2531c97eSMatthias Ringwald // (de)serialize structs from/to HCI commands/events
857*2531c97eSMatthias Ringwald 
858*2531c97eSMatthias Ringwald void daemon_gatt_serialize_service(gatt_client_service_t * service, uint8_t * event, int offset){
859*2531c97eSMatthias Ringwald     little_endian_store_16(event, offset, service->start_group_handle);
860*2531c97eSMatthias Ringwald     little_endian_store_16(event, offset+2, service->end_group_handle);
861*2531c97eSMatthias Ringwald     reverse_128(service->uuid128, &event[offset + 4]);
862*2531c97eSMatthias Ringwald }
863*2531c97eSMatthias Ringwald 
864*2531c97eSMatthias Ringwald void daemon_gatt_serialize_characteristic(gatt_client_characteristic_t * characteristic, uint8_t * event, int offset){
865*2531c97eSMatthias Ringwald     little_endian_store_16(event, offset, characteristic->start_handle);
866*2531c97eSMatthias Ringwald     little_endian_store_16(event, offset+2, characteristic->value_handle);
867*2531c97eSMatthias Ringwald     little_endian_store_16(event, offset+4, characteristic->end_handle);
868*2531c97eSMatthias Ringwald     little_endian_store_16(event, offset+6, characteristic->properties);
869*2531c97eSMatthias Ringwald     reverse_128(characteristic->uuid128, &event[offset+8]);
870*2531c97eSMatthias Ringwald }
871*2531c97eSMatthias Ringwald 
872*2531c97eSMatthias Ringwald void daemon_gatt_serialize_characteristic_descriptor(gatt_client_characteristic_descriptor_t * characteristic_descriptor, uint8_t * event, int offset){
873*2531c97eSMatthias Ringwald     little_endian_store_16(event, offset, characteristic_descriptor->handle);
874*2531c97eSMatthias Ringwald     reverse_128(characteristic_descriptor->uuid128, &event[offset+2]);
875*2531c97eSMatthias Ringwald }
876*2531c97eSMatthias Ringwald 
877*2531c97eSMatthias Ringwald #endif
878*2531c97eSMatthias Ringwald 
879*2531c97eSMatthias Ringwald static int btstack_command_handler(connection_t *connection, uint8_t *packet, uint16_t size){
880*2531c97eSMatthias Ringwald 
881*2531c97eSMatthias Ringwald     bd_addr_t addr;
882*2531c97eSMatthias Ringwald     bd_addr_type_t addr_type;
883*2531c97eSMatthias Ringwald     hci_con_handle_t handle;
884*2531c97eSMatthias Ringwald     uint16_t cid;
885*2531c97eSMatthias Ringwald     uint16_t psm;
886*2531c97eSMatthias Ringwald     uint16_t service_channel;
887*2531c97eSMatthias Ringwald     uint16_t mtu;
888*2531c97eSMatthias Ringwald     uint8_t  reason;
889*2531c97eSMatthias Ringwald     uint8_t  rfcomm_channel;
890*2531c97eSMatthias Ringwald     uint8_t  rfcomm_credits;
891*2531c97eSMatthias Ringwald     uint32_t service_record_handle;
892*2531c97eSMatthias Ringwald     client_state_t *client;
893*2531c97eSMatthias Ringwald     uint8_t status;
894*2531c97eSMatthias Ringwald     uint8_t  * data;
895*2531c97eSMatthias Ringwald #if defined(HAVE_MALLOC) && defined(ENABLE_BLE)
896*2531c97eSMatthias Ringwald     uint8_t uuid128[16];
897*2531c97eSMatthias Ringwald     gatt_client_service_t service;
898*2531c97eSMatthias Ringwald     gatt_client_characteristic_t characteristic;
899*2531c97eSMatthias Ringwald     gatt_client_characteristic_descriptor_t descriptor;
900*2531c97eSMatthias Ringwald     uint16_t data_length;
901*2531c97eSMatthias Ringwald     btstack_linked_list_gatt_client_helper_t * gatt_helper;
902*2531c97eSMatthias Ringwald #endif
903*2531c97eSMatthias Ringwald 
904*2531c97eSMatthias Ringwald     uint16_t serviceSearchPatternLen;
905*2531c97eSMatthias Ringwald     uint16_t attributeIDListLen;
906*2531c97eSMatthias Ringwald 
907*2531c97eSMatthias Ringwald     // verbose log info before other info to allow for better tracking
908*2531c97eSMatthias Ringwald     hci_dump_packet( HCI_COMMAND_DATA_PACKET, 1, packet, size);
909*2531c97eSMatthias Ringwald 
910*2531c97eSMatthias Ringwald     // BTstack internal commands - 16 Bit OpCode, 8 Bit ParamLen, Params...
911*2531c97eSMatthias Ringwald     switch (READ_CMD_OCF(packet)){
912*2531c97eSMatthias Ringwald         case BTSTACK_GET_STATE:
913*2531c97eSMatthias Ringwald             log_info("BTSTACK_GET_STATE");
914*2531c97eSMatthias Ringwald             hci_emit_state();
915*2531c97eSMatthias Ringwald             break;
916*2531c97eSMatthias Ringwald         case BTSTACK_SET_POWER_MODE:
917*2531c97eSMatthias Ringwald             log_info("BTSTACK_SET_POWER_MODE %u", packet[3]);
918*2531c97eSMatthias Ringwald             // track client power requests
919*2531c97eSMatthias Ringwald             client = client_for_connection(connection);
920*2531c97eSMatthias Ringwald             if (!client) break;
921*2531c97eSMatthias Ringwald             client->power_mode = packet[3];
922*2531c97eSMatthias Ringwald             // handle merged state
923*2531c97eSMatthias Ringwald             if (!clients_require_power_on()){
924*2531c97eSMatthias Ringwald                 start_power_off_timer();
925*2531c97eSMatthias Ringwald             } else if (!power_management_sleep) {
926*2531c97eSMatthias Ringwald                 stop_power_off_timer();
927*2531c97eSMatthias Ringwald                 hci_power_control(HCI_POWER_ON);
928*2531c97eSMatthias Ringwald             }
929*2531c97eSMatthias Ringwald             break;
930*2531c97eSMatthias Ringwald         case BTSTACK_GET_VERSION:
931*2531c97eSMatthias Ringwald             log_info("BTSTACK_GET_VERSION");
932*2531c97eSMatthias Ringwald             hci_emit_btstack_version();
933*2531c97eSMatthias Ringwald             break;
934*2531c97eSMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
935*2531c97eSMatthias Ringwald         case BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED:
936*2531c97eSMatthias Ringwald             log_info("BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED %u", packet[3]);
937*2531c97eSMatthias Ringwald             btstack_control_iphone_bt_set_enabled(packet[3]);
938*2531c97eSMatthias Ringwald             hci_emit_system_bluetooth_enabled(btstack_control_iphone_bt_enabled());
939*2531c97eSMatthias Ringwald             break;
940*2531c97eSMatthias Ringwald 
941*2531c97eSMatthias Ringwald         case BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED:
942*2531c97eSMatthias Ringwald             log_info("BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED");
943*2531c97eSMatthias Ringwald             hci_emit_system_bluetooth_enabled(btstack_control_iphone_bt_enabled());
944*2531c97eSMatthias Ringwald             break;
945*2531c97eSMatthias Ringwald #else
946*2531c97eSMatthias Ringwald         case BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED:
947*2531c97eSMatthias Ringwald         case BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED:
948*2531c97eSMatthias Ringwald             hci_emit_system_bluetooth_enabled(0);
949*2531c97eSMatthias Ringwald             break;
950*2531c97eSMatthias Ringwald #endif
951*2531c97eSMatthias Ringwald         case BTSTACK_SET_DISCOVERABLE:
952*2531c97eSMatthias Ringwald             log_info("BTSTACK_SET_DISCOVERABLE discoverable %u)", packet[3]);
953*2531c97eSMatthias Ringwald             // track client discoverable requests
954*2531c97eSMatthias Ringwald             client = client_for_connection(connection);
955*2531c97eSMatthias Ringwald             if (!client) break;
956*2531c97eSMatthias Ringwald             client->discoverable = packet[3];
957*2531c97eSMatthias Ringwald             // merge state
958*2531c97eSMatthias Ringwald             gap_discoverable_control(clients_require_discoverable());
959*2531c97eSMatthias Ringwald             break;
960*2531c97eSMatthias Ringwald         case BTSTACK_SET_BLUETOOTH_ENABLED:
961*2531c97eSMatthias Ringwald             log_info("BTSTACK_SET_BLUETOOTH_ENABLED: %u\n", packet[3]);
962*2531c97eSMatthias Ringwald             if (packet[3]) {
963*2531c97eSMatthias Ringwald                 // global enable
964*2531c97eSMatthias Ringwald                 global_enable = 1;
965*2531c97eSMatthias Ringwald                 hci_power_control(HCI_POWER_ON);
966*2531c97eSMatthias Ringwald             } else {
967*2531c97eSMatthias Ringwald                 global_enable = 0;
968*2531c97eSMatthias Ringwald                 clients_clear_power_request();
969*2531c97eSMatthias Ringwald                 hci_power_control(HCI_POWER_OFF);
970*2531c97eSMatthias Ringwald             }
971*2531c97eSMatthias Ringwald             break;
972*2531c97eSMatthias Ringwald         case L2CAP_CREATE_CHANNEL_MTU:
973*2531c97eSMatthias Ringwald             reverse_bd_addr(&packet[3], addr);
974*2531c97eSMatthias Ringwald             psm = little_endian_read_16(packet, 9);
975*2531c97eSMatthias Ringwald             mtu = little_endian_read_16(packet, 11);
976*2531c97eSMatthias Ringwald             status = l2cap_create_channel(NULL, addr, psm, mtu, &cid);
977*2531c97eSMatthias Ringwald             if (status){
978*2531c97eSMatthias Ringwald                 send_l2cap_connection_open_failed(connection, addr, psm, status);
979*2531c97eSMatthias Ringwald             } else {
980*2531c97eSMatthias Ringwald                 daemon_add_client_l2cap_channel(connection, cid);
981*2531c97eSMatthias Ringwald             }
982*2531c97eSMatthias Ringwald             break;
983*2531c97eSMatthias Ringwald         case L2CAP_CREATE_CHANNEL:
984*2531c97eSMatthias Ringwald             reverse_bd_addr(&packet[3], addr);
985*2531c97eSMatthias Ringwald             psm = little_endian_read_16(packet, 9);
986*2531c97eSMatthias Ringwald             mtu = 150; // until r865
987*2531c97eSMatthias Ringwald             status = l2cap_create_channel(NULL, addr, psm, mtu, &cid);
988*2531c97eSMatthias Ringwald             if (status){
989*2531c97eSMatthias Ringwald                 send_l2cap_connection_open_failed(connection, addr, psm, status);
990*2531c97eSMatthias Ringwald             } else {
991*2531c97eSMatthias Ringwald                 daemon_add_client_l2cap_channel(connection, cid);
992*2531c97eSMatthias Ringwald             }
993*2531c97eSMatthias Ringwald             break;
994*2531c97eSMatthias Ringwald         case L2CAP_DISCONNECT:
995*2531c97eSMatthias Ringwald             cid = little_endian_read_16(packet, 3);
996*2531c97eSMatthias Ringwald             reason = packet[5];
997*2531c97eSMatthias Ringwald             l2cap_disconnect(cid, reason);
998*2531c97eSMatthias Ringwald             break;
999*2531c97eSMatthias Ringwald         case L2CAP_REGISTER_SERVICE:
1000*2531c97eSMatthias Ringwald             psm = little_endian_read_16(packet, 3);
1001*2531c97eSMatthias Ringwald             mtu = little_endian_read_16(packet, 5);
1002*2531c97eSMatthias Ringwald             status = l2cap_register_service(NULL, psm, mtu, LEVEL_0);
1003*2531c97eSMatthias Ringwald             daemon_add_client_l2cap_service(connection, little_endian_read_16(packet, 3));
1004*2531c97eSMatthias Ringwald             l2cap_emit_service_registered(connection, status, psm);
1005*2531c97eSMatthias Ringwald             break;
1006*2531c97eSMatthias Ringwald         case L2CAP_UNREGISTER_SERVICE:
1007*2531c97eSMatthias Ringwald             psm = little_endian_read_16(packet, 3);
1008*2531c97eSMatthias Ringwald             daemon_remove_client_l2cap_service(connection, psm);
1009*2531c97eSMatthias Ringwald             l2cap_unregister_service(psm);
1010*2531c97eSMatthias Ringwald             break;
1011*2531c97eSMatthias Ringwald         case L2CAP_ACCEPT_CONNECTION:
1012*2531c97eSMatthias Ringwald             cid    = little_endian_read_16(packet, 3);
1013*2531c97eSMatthias Ringwald             l2cap_accept_connection(cid);
1014*2531c97eSMatthias Ringwald             break;
1015*2531c97eSMatthias Ringwald         case L2CAP_DECLINE_CONNECTION:
1016*2531c97eSMatthias Ringwald             cid    = little_endian_read_16(packet, 3);
1017*2531c97eSMatthias Ringwald             reason = packet[7];
1018*2531c97eSMatthias Ringwald             l2cap_decline_connection(cid, reason);
1019*2531c97eSMatthias Ringwald             break;
1020*2531c97eSMatthias Ringwald         case RFCOMM_CREATE_CHANNEL:
1021*2531c97eSMatthias Ringwald             reverse_bd_addr(&packet[3], addr);
1022*2531c97eSMatthias Ringwald             rfcomm_channel = packet[9];
1023*2531c97eSMatthias Ringwald             status = rfcomm_create_channel(&rfcomm_packet_handler, addr, rfcomm_channel, &cid);
1024*2531c97eSMatthias Ringwald             if (status){
1025*2531c97eSMatthias Ringwald                 send_rfcomm_create_channel_failed(connection, addr, rfcomm_channel, status);
1026*2531c97eSMatthias Ringwald             } else {
1027*2531c97eSMatthias Ringwald                 daemon_add_client_rfcomm_channel(connection, cid);
1028*2531c97eSMatthias Ringwald             }
1029*2531c97eSMatthias Ringwald             break;
1030*2531c97eSMatthias Ringwald         case RFCOMM_CREATE_CHANNEL_WITH_CREDITS:
1031*2531c97eSMatthias Ringwald             reverse_bd_addr(&packet[3], addr);
1032*2531c97eSMatthias Ringwald             rfcomm_channel = packet[9];
1033*2531c97eSMatthias Ringwald             rfcomm_credits = packet[10];
1034*2531c97eSMatthias Ringwald             status = rfcomm_create_channel_with_initial_credits(&rfcomm_packet_handler, addr, rfcomm_channel, rfcomm_credits, &cid );
1035*2531c97eSMatthias Ringwald             if (status){
1036*2531c97eSMatthias Ringwald                 send_rfcomm_create_channel_failed(connection, addr, rfcomm_channel, status);
1037*2531c97eSMatthias Ringwald             } else {
1038*2531c97eSMatthias Ringwald                 daemon_add_client_rfcomm_channel(connection, cid);
1039*2531c97eSMatthias Ringwald             }
1040*2531c97eSMatthias Ringwald             break;
1041*2531c97eSMatthias Ringwald         case RFCOMM_DISCONNECT:
1042*2531c97eSMatthias Ringwald             cid = little_endian_read_16(packet, 3);
1043*2531c97eSMatthias Ringwald             reason = packet[5];
1044*2531c97eSMatthias Ringwald             rfcomm_disconnect(cid);
1045*2531c97eSMatthias Ringwald             break;
1046*2531c97eSMatthias Ringwald         case RFCOMM_REGISTER_SERVICE:
1047*2531c97eSMatthias Ringwald             rfcomm_channel = packet[3];
1048*2531c97eSMatthias Ringwald             mtu = little_endian_read_16(packet, 4);
1049*2531c97eSMatthias Ringwald             status = rfcomm_register_service(&rfcomm_packet_handler, rfcomm_channel, mtu);
1050*2531c97eSMatthias Ringwald             rfcomm_emit_service_registered(connection, status, rfcomm_channel);
1051*2531c97eSMatthias Ringwald             break;
1052*2531c97eSMatthias Ringwald         case RFCOMM_REGISTER_SERVICE_WITH_CREDITS:
1053*2531c97eSMatthias Ringwald             rfcomm_channel = packet[3];
1054*2531c97eSMatthias Ringwald             mtu = little_endian_read_16(packet, 4);
1055*2531c97eSMatthias Ringwald             rfcomm_credits = packet[6];
1056*2531c97eSMatthias Ringwald             status = rfcomm_register_service_with_initial_credits(&rfcomm_packet_handler, rfcomm_channel, mtu, rfcomm_credits);
1057*2531c97eSMatthias Ringwald             rfcomm_emit_service_registered(connection, status, rfcomm_channel);
1058*2531c97eSMatthias Ringwald             break;
1059*2531c97eSMatthias Ringwald         case RFCOMM_UNREGISTER_SERVICE:
1060*2531c97eSMatthias Ringwald             service_channel = little_endian_read_16(packet, 3);
1061*2531c97eSMatthias Ringwald             daemon_remove_client_rfcomm_service(connection, service_channel);
1062*2531c97eSMatthias Ringwald             rfcomm_unregister_service(service_channel);
1063*2531c97eSMatthias Ringwald             break;
1064*2531c97eSMatthias Ringwald         case RFCOMM_ACCEPT_CONNECTION:
1065*2531c97eSMatthias Ringwald             cid    = little_endian_read_16(packet, 3);
1066*2531c97eSMatthias Ringwald             rfcomm_accept_connection(cid);
1067*2531c97eSMatthias Ringwald             break;
1068*2531c97eSMatthias Ringwald         case RFCOMM_DECLINE_CONNECTION:
1069*2531c97eSMatthias Ringwald             cid    = little_endian_read_16(packet, 3);
1070*2531c97eSMatthias Ringwald             reason = packet[7];
1071*2531c97eSMatthias Ringwald             rfcomm_decline_connection(cid);
1072*2531c97eSMatthias Ringwald             break;
1073*2531c97eSMatthias Ringwald         case RFCOMM_GRANT_CREDITS:
1074*2531c97eSMatthias Ringwald             cid    = little_endian_read_16(packet, 3);
1075*2531c97eSMatthias Ringwald             rfcomm_credits = packet[5];
1076*2531c97eSMatthias Ringwald             rfcomm_grant_credits(cid, rfcomm_credits);
1077*2531c97eSMatthias Ringwald             break;
1078*2531c97eSMatthias Ringwald         case RFCOMM_PERSISTENT_CHANNEL: {
1079*2531c97eSMatthias Ringwald             // enforce \0
1080*2531c97eSMatthias Ringwald             packet[3+248] = 0;
1081*2531c97eSMatthias Ringwald             rfcomm_channel = rfcomm_service_db_channel_for_service((char*)&packet[3]);
1082*2531c97eSMatthias Ringwald             log_info("RFCOMM_EVENT_PERSISTENT_CHANNEL %u", rfcomm_channel);
1083*2531c97eSMatthias Ringwald             uint8_t event[4];
1084*2531c97eSMatthias Ringwald             event[0] = RFCOMM_EVENT_PERSISTENT_CHANNEL;
1085*2531c97eSMatthias Ringwald             event[1] = sizeof(event) - 2;
1086*2531c97eSMatthias Ringwald             event[2] = 0;
1087*2531c97eSMatthias Ringwald             event[3] = rfcomm_channel;
1088*2531c97eSMatthias Ringwald             hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
1089*2531c97eSMatthias Ringwald             socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1090*2531c97eSMatthias Ringwald             break;
1091*2531c97eSMatthias Ringwald         }
1092*2531c97eSMatthias Ringwald         case SDP_REGISTER_SERVICE_RECORD:
1093*2531c97eSMatthias Ringwald             log_info("SDP_REGISTER_SERVICE_RECORD size %u\n", size);
1094*2531c97eSMatthias Ringwald             service_record_handle = daemon_sdp_create_and_register_service(&packet[3]);
1095*2531c97eSMatthias Ringwald             if (service_record_handle){
1096*2531c97eSMatthias Ringwald                 daemon_add_client_sdp_service_record_handle(connection, service_record_handle);
1097*2531c97eSMatthias Ringwald                 sdp_emit_service_registered(connection, service_record_handle, 0);
1098*2531c97eSMatthias Ringwald             } else {
1099*2531c97eSMatthias Ringwald                sdp_emit_service_registered(connection, 0, BTSTACK_MEMORY_ALLOC_FAILED);
1100*2531c97eSMatthias Ringwald             }
1101*2531c97eSMatthias Ringwald             break;
1102*2531c97eSMatthias Ringwald         case SDP_UNREGISTER_SERVICE_RECORD:
1103*2531c97eSMatthias Ringwald             service_record_handle = little_endian_read_32(packet, 3);
1104*2531c97eSMatthias Ringwald             log_info("SDP_UNREGISTER_SERVICE_RECORD handle 0x%x ", service_record_handle);
1105*2531c97eSMatthias Ringwald             data = sdp_get_record_for_handle(service_record_handle);
1106*2531c97eSMatthias Ringwald             sdp_unregister_service(service_record_handle);
1107*2531c97eSMatthias Ringwald             daemon_remove_client_sdp_service_record_handle(connection, service_record_handle);
1108*2531c97eSMatthias Ringwald             if (data){
1109*2531c97eSMatthias Ringwald                 free(data);
1110*2531c97eSMatthias Ringwald             }
1111*2531c97eSMatthias Ringwald             break;
1112*2531c97eSMatthias Ringwald         case SDP_CLIENT_QUERY_RFCOMM_SERVICES:
1113*2531c97eSMatthias Ringwald             reverse_bd_addr(&packet[3], addr);
1114*2531c97eSMatthias Ringwald 
1115*2531c97eSMatthias Ringwald             serviceSearchPatternLen = de_get_len(&packet[9]);
1116*2531c97eSMatthias Ringwald             memcpy(serviceSearchPattern, &packet[9], serviceSearchPatternLen);
1117*2531c97eSMatthias Ringwald 
1118*2531c97eSMatthias Ringwald             sdp_client_query_connection = connection;
1119*2531c97eSMatthias Ringwald             sdp_query_rfcomm_channel_and_name_for_search_pattern(&handle_sdp_rfcomm_service_result, addr, serviceSearchPattern);
1120*2531c97eSMatthias Ringwald 
1121*2531c97eSMatthias Ringwald             break;
1122*2531c97eSMatthias Ringwald         case SDP_CLIENT_QUERY_SERVICES:
1123*2531c97eSMatthias Ringwald             reverse_bd_addr(&packet[3], addr);
1124*2531c97eSMatthias Ringwald             sdp_client_query_connection = connection;
1125*2531c97eSMatthias Ringwald 
1126*2531c97eSMatthias Ringwald             serviceSearchPatternLen = de_get_len(&packet[9]);
1127*2531c97eSMatthias Ringwald             memcpy(serviceSearchPattern, &packet[9], serviceSearchPatternLen);
1128*2531c97eSMatthias Ringwald 
1129*2531c97eSMatthias Ringwald             attributeIDListLen = de_get_len(&packet[9+serviceSearchPatternLen]);
1130*2531c97eSMatthias Ringwald             memcpy(attributeIDList, &packet[9+serviceSearchPatternLen], attributeIDListLen);
1131*2531c97eSMatthias Ringwald 
1132*2531c97eSMatthias Ringwald             sdp_client_query(&handle_sdp_client_query_result, addr, (uint8_t*)&serviceSearchPattern[0], (uint8_t*)&attributeIDList[0]);
1133*2531c97eSMatthias Ringwald             break;
1134*2531c97eSMatthias Ringwald         case GAP_LE_SCAN_START:
1135*2531c97eSMatthias Ringwald             gap_start_scan();
1136*2531c97eSMatthias Ringwald             break;
1137*2531c97eSMatthias Ringwald         case GAP_LE_SCAN_STOP:
1138*2531c97eSMatthias Ringwald             gap_stop_scan();
1139*2531c97eSMatthias Ringwald             break;
1140*2531c97eSMatthias Ringwald         case GAP_LE_SET_SCAN_PARAMETERS:
1141*2531c97eSMatthias Ringwald             gap_set_scan_parameters(packet[3], little_endian_read_16(packet, 4), little_endian_read_16(packet, 6));
1142*2531c97eSMatthias Ringwald             break;
1143*2531c97eSMatthias Ringwald         case GAP_LE_CONNECT:
1144*2531c97eSMatthias Ringwald             reverse_bd_addr(&packet[4], addr);
1145*2531c97eSMatthias Ringwald             addr_type = packet[3];
1146*2531c97eSMatthias Ringwald             gap_connect(addr, addr_type);
1147*2531c97eSMatthias Ringwald             break;
1148*2531c97eSMatthias Ringwald         case GAP_LE_CONNECT_CANCEL:
1149*2531c97eSMatthias Ringwald             gap_connect_cancel();
1150*2531c97eSMatthias Ringwald             break;
1151*2531c97eSMatthias Ringwald         case GAP_DISCONNECT:
1152*2531c97eSMatthias Ringwald             handle = little_endian_read_16(packet, 3);
1153*2531c97eSMatthias Ringwald             gap_disconnect(handle);
1154*2531c97eSMatthias Ringwald             break;
1155*2531c97eSMatthias Ringwald #if defined(HAVE_MALLOC) && defined(ENABLE_BLE)
1156*2531c97eSMatthias Ringwald         case GATT_DISCOVER_ALL_PRIMARY_SERVICES:
1157*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1158*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1159*2531c97eSMatthias Ringwald             gatt_client_discover_primary_services(&handle_gatt_client_event, gatt_helper->con_handle);
1160*2531c97eSMatthias Ringwald             break;
1161*2531c97eSMatthias Ringwald         case GATT_DISCOVER_PRIMARY_SERVICES_BY_UUID16:
1162*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1163*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1164*2531c97eSMatthias Ringwald             gatt_client_discover_primary_services_by_uuid16(&handle_gatt_client_event, gatt_helper->con_handle, little_endian_read_16(packet, 5));
1165*2531c97eSMatthias Ringwald             break;
1166*2531c97eSMatthias Ringwald         case GATT_DISCOVER_PRIMARY_SERVICES_BY_UUID128:
1167*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1168*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1169*2531c97eSMatthias Ringwald             reverse_128(&packet[5], uuid128);
1170*2531c97eSMatthias Ringwald             gatt_client_discover_primary_services_by_uuid128(&handle_gatt_client_event, gatt_helper->con_handle, uuid128);
1171*2531c97eSMatthias Ringwald             break;
1172*2531c97eSMatthias Ringwald         case GATT_FIND_INCLUDED_SERVICES_FOR_SERVICE:
1173*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1174*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1175*2531c97eSMatthias Ringwald             gatt_client_deserialize_service(packet, 5, &service);
1176*2531c97eSMatthias Ringwald             gatt_client_find_included_services_for_service(&handle_gatt_client_event, gatt_helper->con_handle, &service);
1177*2531c97eSMatthias Ringwald             break;
1178*2531c97eSMatthias Ringwald 
1179*2531c97eSMatthias Ringwald         case GATT_DISCOVER_CHARACTERISTICS_FOR_SERVICE:
1180*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1181*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1182*2531c97eSMatthias Ringwald             gatt_client_deserialize_service(packet, 5, &service);
1183*2531c97eSMatthias Ringwald             gatt_client_discover_characteristics_for_service(&handle_gatt_client_event, gatt_helper->con_handle, &service);
1184*2531c97eSMatthias Ringwald             break;
1185*2531c97eSMatthias Ringwald         case GATT_DISCOVER_CHARACTERISTICS_FOR_SERVICE_BY_UUID128:
1186*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1187*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1188*2531c97eSMatthias Ringwald             gatt_client_deserialize_service(packet, 5, &service);
1189*2531c97eSMatthias Ringwald             reverse_128(&packet[5 + SERVICE_LENGTH], uuid128);
1190*2531c97eSMatthias Ringwald             gatt_client_discover_characteristics_for_service_by_uuid128(&handle_gatt_client_event, gatt_helper->con_handle, &service, uuid128);
1191*2531c97eSMatthias Ringwald             break;
1192*2531c97eSMatthias Ringwald         case GATT_DISCOVER_CHARACTERISTIC_DESCRIPTORS:
1193*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1194*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1195*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic(packet, 5, &characteristic);
1196*2531c97eSMatthias Ringwald             gatt_client_discover_characteristic_descriptors(&handle_gatt_client_event, gatt_helper->con_handle, &characteristic);
1197*2531c97eSMatthias Ringwald             break;
1198*2531c97eSMatthias Ringwald 
1199*2531c97eSMatthias Ringwald         case GATT_READ_VALUE_OF_CHARACTERISTIC:
1200*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1201*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1202*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic(packet, 5, &characteristic);
1203*2531c97eSMatthias Ringwald             gatt_client_read_value_of_characteristic(&handle_gatt_client_event, gatt_helper->con_handle, &characteristic);
1204*2531c97eSMatthias Ringwald             break;
1205*2531c97eSMatthias Ringwald         case GATT_READ_LONG_VALUE_OF_CHARACTERISTIC:
1206*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1207*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1208*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic(packet, 5, &characteristic);
1209*2531c97eSMatthias Ringwald             gatt_client_read_long_value_of_characteristic(&handle_gatt_client_event, gatt_helper->con_handle, &characteristic);
1210*2531c97eSMatthias Ringwald             break;
1211*2531c97eSMatthias Ringwald 
1212*2531c97eSMatthias Ringwald         case GATT_WRITE_VALUE_OF_CHARACTERISTIC_WITHOUT_RESPONSE:
1213*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 0);  // note: don't track active connection
1214*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1215*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic(packet, 5, &characteristic);
1216*2531c97eSMatthias Ringwald             data_length = little_endian_read_16(packet, 5 + CHARACTERISTIC_LENGTH);
1217*2531c97eSMatthias Ringwald             data = gatt_helper->characteristic_buffer;
1218*2531c97eSMatthias Ringwald             memcpy(data, &packet[7 + CHARACTERISTIC_LENGTH], data_length);
1219*2531c97eSMatthias Ringwald             gatt_client_write_value_of_characteristic_without_response(&handle_gatt_client_event, gatt_helper->con_handle, characteristic.value_handle, data_length, data);
1220*2531c97eSMatthias Ringwald             break;
1221*2531c97eSMatthias Ringwald         case GATT_WRITE_VALUE_OF_CHARACTERISTIC:
1222*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1223*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1224*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic(packet, 5, &characteristic);
1225*2531c97eSMatthias Ringwald             data_length = little_endian_read_16(packet, 5 + CHARACTERISTIC_LENGTH);
1226*2531c97eSMatthias Ringwald             data = gatt_helper->characteristic_buffer;
1227*2531c97eSMatthias Ringwald             memcpy(data, &packet[7 + CHARACTERISTIC_LENGTH], data_length);
1228*2531c97eSMatthias Ringwald             gatt_client_write_value_of_characteristic(&handle_gatt_client_event, gatt_helper->con_handle, characteristic.value_handle, data_length, data);
1229*2531c97eSMatthias Ringwald             break;
1230*2531c97eSMatthias Ringwald         case GATT_WRITE_LONG_VALUE_OF_CHARACTERISTIC:
1231*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1232*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1233*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic(packet, 5, &characteristic);
1234*2531c97eSMatthias Ringwald             data_length = little_endian_read_16(packet, 5 + CHARACTERISTIC_LENGTH);
1235*2531c97eSMatthias Ringwald             data = gatt_helper->characteristic_buffer;
1236*2531c97eSMatthias Ringwald             memcpy(data, &packet[7 + CHARACTERISTIC_LENGTH], data_length);
1237*2531c97eSMatthias Ringwald             gatt_client_write_long_value_of_characteristic(&handle_gatt_client_event, gatt_helper->con_handle, characteristic.value_handle, data_length, data);
1238*2531c97eSMatthias Ringwald             break;
1239*2531c97eSMatthias Ringwald         case GATT_RELIABLE_WRITE_LONG_VALUE_OF_CHARACTERISTIC:
1240*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1241*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1242*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic(packet, 5, &characteristic);
1243*2531c97eSMatthias Ringwald             data_length = little_endian_read_16(packet, 5 + CHARACTERISTIC_LENGTH);
1244*2531c97eSMatthias Ringwald             data = gatt_helper->characteristic_buffer;
1245*2531c97eSMatthias Ringwald             memcpy(data, &packet[7 + CHARACTERISTIC_LENGTH], data_length);
1246*2531c97eSMatthias Ringwald             gatt_client_write_long_value_of_characteristic(&handle_gatt_client_event, gatt_helper->con_handle, characteristic.value_handle, data_length, data);
1247*2531c97eSMatthias Ringwald             break;
1248*2531c97eSMatthias Ringwald         case GATT_READ_CHARACTERISTIC_DESCRIPTOR:
1249*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1250*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1251*2531c97eSMatthias Ringwald             handle = little_endian_read_16(packet, 3);
1252*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic_descriptor(packet, 5, &descriptor);
1253*2531c97eSMatthias Ringwald             gatt_client_read_characteristic_descriptor(&handle_gatt_client_event, gatt_helper->con_handle, &descriptor);
1254*2531c97eSMatthias Ringwald             break;
1255*2531c97eSMatthias Ringwald         case GATT_READ_LONG_CHARACTERISTIC_DESCRIPTOR:
1256*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1257*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1258*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic_descriptor(packet, 5, &descriptor);
1259*2531c97eSMatthias Ringwald             gatt_client_read_long_characteristic_descriptor(&handle_gatt_client_event, gatt_helper->con_handle, &descriptor);
1260*2531c97eSMatthias Ringwald             break;
1261*2531c97eSMatthias Ringwald 
1262*2531c97eSMatthias Ringwald         case GATT_WRITE_CHARACTERISTIC_DESCRIPTOR:
1263*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1264*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1265*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic_descriptor(packet, 5, &descriptor);
1266*2531c97eSMatthias Ringwald             data = gatt_helper->characteristic_buffer;
1267*2531c97eSMatthias Ringwald             data_length = little_endian_read_16(packet, 5 + CHARACTERISTIC_DESCRIPTOR_LENGTH);
1268*2531c97eSMatthias Ringwald             gatt_client_write_characteristic_descriptor(&handle_gatt_client_event, gatt_helper->con_handle, &descriptor, data_length, data);
1269*2531c97eSMatthias Ringwald             break;
1270*2531c97eSMatthias Ringwald         case GATT_WRITE_LONG_CHARACTERISTIC_DESCRIPTOR:
1271*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1272*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1273*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic_descriptor(packet, 5, &descriptor);
1274*2531c97eSMatthias Ringwald             data = gatt_helper->characteristic_buffer;
1275*2531c97eSMatthias Ringwald             data_length = little_endian_read_16(packet, 5 + CHARACTERISTIC_DESCRIPTOR_LENGTH);
1276*2531c97eSMatthias Ringwald             gatt_client_write_long_characteristic_descriptor(&handle_gatt_client_event, gatt_helper->con_handle, &descriptor, data_length, data);
1277*2531c97eSMatthias Ringwald             break;
1278*2531c97eSMatthias Ringwald         case GATT_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:{
1279*2531c97eSMatthias Ringwald             uint16_t configuration = little_endian_read_16(packet, 5 + CHARACTERISTIC_LENGTH);
1280*2531c97eSMatthias Ringwald             gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1);
1281*2531c97eSMatthias Ringwald             if (!gatt_helper) break;
1282*2531c97eSMatthias Ringwald             data = gatt_helper->characteristic_buffer;
1283*2531c97eSMatthias Ringwald             gatt_client_deserialize_characteristic(packet, 5, &characteristic);
1284*2531c97eSMatthias Ringwald             gatt_client_write_client_characteristic_configuration(&handle_gatt_client_event, gatt_helper->con_handle, &characteristic, configuration);
1285*2531c97eSMatthias Ringwald             break;
1286*2531c97eSMatthias Ringwald         case GATT_GET_MTU:
1287*2531c97eSMatthias Ringwald             handle = little_endian_read_16(packet, 3);
1288*2531c97eSMatthias Ringwald             gatt_client_get_mtu(handle, &mtu);
1289*2531c97eSMatthias Ringwald             send_gatt_mtu_event(connection, handle, mtu);
1290*2531c97eSMatthias Ringwald             break;
1291*2531c97eSMatthias Ringwald         }
1292*2531c97eSMatthias Ringwald #endif
1293*2531c97eSMatthias Ringwald     default:
1294*2531c97eSMatthias Ringwald             log_error("Error: command %u not implemented:", READ_CMD_OCF(packet));
1295*2531c97eSMatthias Ringwald             break;
1296*2531c97eSMatthias Ringwald     }
1297*2531c97eSMatthias Ringwald 
1298*2531c97eSMatthias Ringwald     return 0;
1299*2531c97eSMatthias Ringwald }
1300*2531c97eSMatthias Ringwald 
1301*2531c97eSMatthias Ringwald static int daemon_client_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length){
1302*2531c97eSMatthias Ringwald 
1303*2531c97eSMatthias Ringwald     int err = 0;
1304*2531c97eSMatthias Ringwald     client_state_t * client;
1305*2531c97eSMatthias Ringwald 
1306*2531c97eSMatthias Ringwald     switch (packet_type){
1307*2531c97eSMatthias Ringwald         case HCI_COMMAND_DATA_PACKET:
1308*2531c97eSMatthias Ringwald             if (READ_CMD_OGF(data) != OGF_BTSTACK) {
1309*2531c97eSMatthias Ringwald                 // HCI Command
1310*2531c97eSMatthias Ringwald                 hci_send_cmd_packet(data, length);
1311*2531c97eSMatthias Ringwald             } else {
1312*2531c97eSMatthias Ringwald                 // BTstack command
1313*2531c97eSMatthias Ringwald                 btstack_command_handler(connection, data, length);
1314*2531c97eSMatthias Ringwald             }
1315*2531c97eSMatthias Ringwald             break;
1316*2531c97eSMatthias Ringwald         case L2CAP_DATA_PACKET:
1317*2531c97eSMatthias Ringwald             // process l2cap packet...
1318*2531c97eSMatthias Ringwald             err = l2cap_send(channel, data, length);
1319*2531c97eSMatthias Ringwald             break;
1320*2531c97eSMatthias Ringwald         case RFCOMM_DATA_PACKET:
1321*2531c97eSMatthias Ringwald             // process l2cap packet...
1322*2531c97eSMatthias Ringwald             err = rfcomm_send(channel, data, length);
1323*2531c97eSMatthias Ringwald             break;
1324*2531c97eSMatthias Ringwald         case DAEMON_EVENT_PACKET:
1325*2531c97eSMatthias Ringwald             switch (data[0]) {
1326*2531c97eSMatthias Ringwald                 case DAEMON_EVENT_CONNECTION_OPENED:
1327*2531c97eSMatthias Ringwald                     log_info("DAEMON_EVENT_CONNECTION_OPENED %p\n",connection);
1328*2531c97eSMatthias Ringwald 
1329*2531c97eSMatthias Ringwald                     client = malloc(sizeof(client_state_t));
1330*2531c97eSMatthias Ringwald                     if (!client) break; // fail
1331*2531c97eSMatthias Ringwald                     memset(client, 0, sizeof(client_state_t));
1332*2531c97eSMatthias Ringwald                     client->connection   = connection;
1333*2531c97eSMatthias Ringwald                     client->power_mode   = HCI_POWER_OFF;
1334*2531c97eSMatthias Ringwald                     client->discoverable = 0;
1335*2531c97eSMatthias Ringwald                     btstack_linked_list_add(&clients, (btstack_linked_item_t *) client);
1336*2531c97eSMatthias Ringwald                     break;
1337*2531c97eSMatthias Ringwald                 case DAEMON_EVENT_CONNECTION_CLOSED:
1338*2531c97eSMatthias Ringwald                     log_info("DAEMON_EVENT_CONNECTION_CLOSED %p\n",connection);
1339*2531c97eSMatthias Ringwald                     daemon_disconnect_client(connection);
1340*2531c97eSMatthias Ringwald                     // no clients -> no HCI connections
1341*2531c97eSMatthias Ringwald                     if (!clients){
1342*2531c97eSMatthias Ringwald                         hci_disconnect_all();
1343*2531c97eSMatthias Ringwald                     }
1344*2531c97eSMatthias Ringwald 
1345*2531c97eSMatthias Ringwald                     // update discoverable mode
1346*2531c97eSMatthias Ringwald                     gap_discoverable_control(clients_require_discoverable());
1347*2531c97eSMatthias Ringwald                     // start power off, if last active client
1348*2531c97eSMatthias Ringwald                     if (!clients_require_power_on()){
1349*2531c97eSMatthias Ringwald                         start_power_off_timer();
1350*2531c97eSMatthias Ringwald                     }
1351*2531c97eSMatthias Ringwald                     break;
1352*2531c97eSMatthias Ringwald                 default:
1353*2531c97eSMatthias Ringwald                     break;
1354*2531c97eSMatthias Ringwald             }
1355*2531c97eSMatthias Ringwald             break;
1356*2531c97eSMatthias Ringwald     }
1357*2531c97eSMatthias Ringwald     if (err) {
1358*2531c97eSMatthias Ringwald         log_info("Daemon Handler: err %d\n", err);
1359*2531c97eSMatthias Ringwald     }
1360*2531c97eSMatthias Ringwald     return err;
1361*2531c97eSMatthias Ringwald }
1362*2531c97eSMatthias Ringwald 
1363*2531c97eSMatthias Ringwald 
1364*2531c97eSMatthias Ringwald static void daemon_set_logging_enabled(int enabled){
1365*2531c97eSMatthias Ringwald     if (enabled && !loggingEnabled){
1366*2531c97eSMatthias Ringwald         hci_dump_open(BTSTACK_LOG_FILE, BTSTACK_LOG_TYPE);
1367*2531c97eSMatthias Ringwald     }
1368*2531c97eSMatthias Ringwald     if (!enabled && loggingEnabled){
1369*2531c97eSMatthias Ringwald         hci_dump_close();
1370*2531c97eSMatthias Ringwald     }
1371*2531c97eSMatthias Ringwald     loggingEnabled = enabled;
1372*2531c97eSMatthias Ringwald }
1373*2531c97eSMatthias Ringwald 
1374*2531c97eSMatthias Ringwald // local cache used to manage UI status
1375*2531c97eSMatthias Ringwald static HCI_STATE hci_state = HCI_STATE_OFF;
1376*2531c97eSMatthias Ringwald static int num_connections = 0;
1377*2531c97eSMatthias Ringwald static void update_ui_status(void){
1378*2531c97eSMatthias Ringwald     if (hci_state != HCI_STATE_WORKING) {
1379*2531c97eSMatthias Ringwald         bluetooth_status_handler(BLUETOOTH_OFF);
1380*2531c97eSMatthias Ringwald     } else {
1381*2531c97eSMatthias Ringwald         if (num_connections) {
1382*2531c97eSMatthias Ringwald             bluetooth_status_handler(BLUETOOTH_ACTIVE);
1383*2531c97eSMatthias Ringwald         } else {
1384*2531c97eSMatthias Ringwald             bluetooth_status_handler(BLUETOOTH_ON);
1385*2531c97eSMatthias Ringwald         }
1386*2531c97eSMatthias Ringwald     }
1387*2531c97eSMatthias Ringwald }
1388*2531c97eSMatthias Ringwald 
1389*2531c97eSMatthias Ringwald #ifdef USE_SPRINGBOARD
1390*2531c97eSMatthias Ringwald static void preferences_changed_callback(void){
1391*2531c97eSMatthias Ringwald     int logging = platform_iphone_logging_enabled();
1392*2531c97eSMatthias Ringwald     log_info("Logging enabled: %u\n", logging);
1393*2531c97eSMatthias Ringwald     daemon_set_logging_enabled(logging);
1394*2531c97eSMatthias Ringwald }
1395*2531c97eSMatthias Ringwald #endif
1396*2531c97eSMatthias Ringwald 
1397*2531c97eSMatthias Ringwald static void deamon_status_event_handler(uint8_t *packet, uint16_t size){
1398*2531c97eSMatthias Ringwald 
1399*2531c97eSMatthias Ringwald     uint8_t update_status = 0;
1400*2531c97eSMatthias Ringwald 
1401*2531c97eSMatthias Ringwald     // handle state event
1402*2531c97eSMatthias Ringwald     switch (packet[0]) {
1403*2531c97eSMatthias Ringwald         case BTSTACK_EVENT_STATE:
1404*2531c97eSMatthias Ringwald             hci_state = packet[2];
1405*2531c97eSMatthias Ringwald             log_info("New state: %u\n", hci_state);
1406*2531c97eSMatthias Ringwald             update_status = 1;
1407*2531c97eSMatthias Ringwald             break;
1408*2531c97eSMatthias Ringwald         case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED:
1409*2531c97eSMatthias Ringwald             num_connections = packet[2];
1410*2531c97eSMatthias Ringwald             log_info("New nr connections: %u\n", num_connections);
1411*2531c97eSMatthias Ringwald             update_status = 1;
1412*2531c97eSMatthias Ringwald             break;
1413*2531c97eSMatthias Ringwald         default:
1414*2531c97eSMatthias Ringwald             break;
1415*2531c97eSMatthias Ringwald     }
1416*2531c97eSMatthias Ringwald 
1417*2531c97eSMatthias Ringwald     // choose full bluetooth state
1418*2531c97eSMatthias Ringwald     if (update_status) {
1419*2531c97eSMatthias Ringwald         update_ui_status();
1420*2531c97eSMatthias Ringwald     }
1421*2531c97eSMatthias Ringwald }
1422*2531c97eSMatthias Ringwald 
1423*2531c97eSMatthias Ringwald static void daemon_retry_parked(void){
1424*2531c97eSMatthias Ringwald 
1425*2531c97eSMatthias Ringwald     // socket_connection_retry_parked is not reentrant
1426*2531c97eSMatthias Ringwald     static int retry_mutex = 0;
1427*2531c97eSMatthias Ringwald 
1428*2531c97eSMatthias Ringwald     // lock mutex
1429*2531c97eSMatthias Ringwald     if (retry_mutex) return;
1430*2531c97eSMatthias Ringwald     retry_mutex = 1;
1431*2531c97eSMatthias Ringwald 
1432*2531c97eSMatthias Ringwald     // ... try sending again
1433*2531c97eSMatthias Ringwald     socket_connection_retry_parked();
1434*2531c97eSMatthias Ringwald 
1435*2531c97eSMatthias Ringwald     // unlock mutex
1436*2531c97eSMatthias Ringwald     retry_mutex = 0;
1437*2531c97eSMatthias Ringwald }
1438*2531c97eSMatthias Ringwald 
1439*2531c97eSMatthias Ringwald #if 0
1440*2531c97eSMatthias Ringwald 
1441*2531c97eSMatthias Ringwald Minimal Code for LE Peripheral
1442*2531c97eSMatthias Ringwald 
1443*2531c97eSMatthias Ringwald enum {
1444*2531c97eSMatthias Ringwald     SET_ADVERTISEMENT_PARAMS = 1 << 0,
1445*2531c97eSMatthias Ringwald     SET_ADVERTISEMENT_DATA   = 1 << 1,
1446*2531c97eSMatthias Ringwald     ENABLE_ADVERTISEMENTS    = 1 << 2,
1447*2531c97eSMatthias Ringwald };
1448*2531c97eSMatthias Ringwald 
1449*2531c97eSMatthias Ringwald const uint8_t adv_data[] = {
1450*2531c97eSMatthias Ringwald     // Flags general discoverable
1451*2531c97eSMatthias Ringwald     0x02, 0x01, 0x02,
1452*2531c97eSMatthias Ringwald     // Name
1453*2531c97eSMatthias Ringwald     0x08, 0x09, 'B', 'T', 's', 't', 'a', 'c', 'k'
1454*2531c97eSMatthias Ringwald };
1455*2531c97eSMatthias Ringwald uint8_t adv_data_len = sizeof(adv_data);
1456*2531c97eSMatthias Ringwald static uint16_t todos = 0;
1457*2531c97eSMatthias Ringwald 
1458*2531c97eSMatthias Ringwald static void app_run(void){
1459*2531c97eSMatthias Ringwald 
1460*2531c97eSMatthias Ringwald     if (!hci_can_send_command_packet_now()) return;
1461*2531c97eSMatthias Ringwald 
1462*2531c97eSMatthias Ringwald     if (todos & SET_ADVERTISEMENT_DATA){
1463*2531c97eSMatthias Ringwald         log_info("app_run: set advertisement data\n");
1464*2531c97eSMatthias Ringwald         todos &= ~SET_ADVERTISEMENT_DATA;
1465*2531c97eSMatthias Ringwald         hci_send_cmd(&hci_le_set_advertising_data, adv_data_len, adv_data);
1466*2531c97eSMatthias Ringwald         return;
1467*2531c97eSMatthias Ringwald     }
1468*2531c97eSMatthias Ringwald 
1469*2531c97eSMatthias Ringwald     if (todos & SET_ADVERTISEMENT_PARAMS){
1470*2531c97eSMatthias Ringwald         todos &= ~SET_ADVERTISEMENT_PARAMS;
1471*2531c97eSMatthias Ringwald         uint8_t adv_type = 0;   // default
1472*2531c97eSMatthias Ringwald         bd_addr_t null_addr;
1473*2531c97eSMatthias Ringwald         memset(null_addr, 0, 6);
1474*2531c97eSMatthias Ringwald         uint16_t adv_int_min = 0x0030;
1475*2531c97eSMatthias Ringwald         uint16_t adv_int_max = 0x0030;
1476*2531c97eSMatthias Ringwald         hci_send_cmd(&hci_le_set_advertising_parameters, adv_int_min, adv_int_max, adv_type, 0, 0, &null_addr, 0x07, 0x00);
1477*2531c97eSMatthias Ringwald         return;
1478*2531c97eSMatthias Ringwald     }
1479*2531c97eSMatthias Ringwald 
1480*2531c97eSMatthias Ringwald     if (todos & ENABLE_ADVERTISEMENTS){
1481*2531c97eSMatthias Ringwald         log_info("app_run: enable advertisements\n");
1482*2531c97eSMatthias Ringwald         todos &= ~ENABLE_ADVERTISEMENTS;
1483*2531c97eSMatthias Ringwald         hci_send_cmd(&hci_le_set_advertise_enable, 1);
1484*2531c97eSMatthias Ringwald         return;
1485*2531c97eSMatthias Ringwald     }
1486*2531c97eSMatthias Ringwald }
1487*2531c97eSMatthias Ringwald #endif
1488*2531c97eSMatthias Ringwald 
1489*2531c97eSMatthias Ringwald static void daemon_emit_packet(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1490*2531c97eSMatthias Ringwald     if (connection) {
1491*2531c97eSMatthias Ringwald         socket_connection_send_packet(connection, packet_type, channel, packet, size);
1492*2531c97eSMatthias Ringwald     } else {
1493*2531c97eSMatthias Ringwald         socket_connection_send_packet_all(packet_type, channel, packet, size);
1494*2531c97eSMatthias Ringwald     }
1495*2531c97eSMatthias Ringwald }
1496*2531c97eSMatthias Ringwald 
1497*2531c97eSMatthias Ringwald static uint8_t remote_name_event[2+1+6+DEVICE_NAME_LEN+1]; // +1 for \0 in log_info
1498*2531c97eSMatthias Ringwald static void daemon_packet_handler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1499*2531c97eSMatthias Ringwald     uint16_t cid;
1500*2531c97eSMatthias Ringwald     int i;
1501*2531c97eSMatthias Ringwald     bd_addr_t addr;
1502*2531c97eSMatthias Ringwald     switch (packet_type) {
1503*2531c97eSMatthias Ringwald         case HCI_EVENT_PACKET:
1504*2531c97eSMatthias Ringwald             deamon_status_event_handler(packet, size);
1505*2531c97eSMatthias Ringwald             switch (packet[0]){
1506*2531c97eSMatthias Ringwald 
1507*2531c97eSMatthias Ringwald                 case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
1508*2531c97eSMatthias Ringwald                     // ACL buffer freed...
1509*2531c97eSMatthias Ringwald                     daemon_retry_parked();
1510*2531c97eSMatthias Ringwald                     // no need to tell clients
1511*2531c97eSMatthias Ringwald                     return;
1512*2531c97eSMatthias Ringwald 
1513*2531c97eSMatthias Ringwald                 case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
1514*2531c97eSMatthias Ringwald                     if (!btstack_device_name_db) break;
1515*2531c97eSMatthias Ringwald                     if (packet[2]) break; // status not ok
1516*2531c97eSMatthias Ringwald 
1517*2531c97eSMatthias Ringwald                     reverse_bd_addr(&packet[3], addr);
1518*2531c97eSMatthias Ringwald                     // fix for invalid remote names - terminate on 0xff
1519*2531c97eSMatthias Ringwald                     for (i=0; i<248;i++){
1520*2531c97eSMatthias Ringwald                         if (packet[9+i] == 0xff){
1521*2531c97eSMatthias Ringwald                             packet[9+i] = 0;
1522*2531c97eSMatthias Ringwald                             break;
1523*2531c97eSMatthias Ringwald                         }
1524*2531c97eSMatthias Ringwald                     }
1525*2531c97eSMatthias Ringwald                     packet[9+248] = 0;
1526*2531c97eSMatthias Ringwald                     btstack_device_name_db->put_name(addr, (device_name_t *)&packet[9]);
1527*2531c97eSMatthias Ringwald                     break;
1528*2531c97eSMatthias Ringwald 
1529*2531c97eSMatthias Ringwald                 case HCI_EVENT_INQUIRY_RESULT:
1530*2531c97eSMatthias Ringwald                 case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:{
1531*2531c97eSMatthias Ringwald                     if (!btstack_device_name_db) break;
1532*2531c97eSMatthias Ringwald 
1533*2531c97eSMatthias Ringwald                     // first send inq result packet
1534*2531c97eSMatthias Ringwald                     daemon_emit_packet(connection, packet_type, channel, packet, size);
1535*2531c97eSMatthias Ringwald 
1536*2531c97eSMatthias Ringwald                     // then send cached remote names
1537*2531c97eSMatthias Ringwald                     int offset = 3;
1538*2531c97eSMatthias Ringwald                     for (i=0; i<packet[2];i++){
1539*2531c97eSMatthias Ringwald                         reverse_bd_addr(&packet[offset], addr);
1540*2531c97eSMatthias Ringwald                         if (btstack_device_name_db->get_name(addr, (device_name_t *) &remote_name_event[9])){
1541*2531c97eSMatthias Ringwald                             remote_name_event[0] = DAEMON_EVENT_REMOTE_NAME_CACHED;
1542*2531c97eSMatthias Ringwald                             remote_name_event[1] = sizeof(remote_name_event) - 2 - 1;
1543*2531c97eSMatthias Ringwald                             remote_name_event[2] = 0;   // just to be compatible with HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE
1544*2531c97eSMatthias Ringwald                             reverse_bd_addr(addr, &remote_name_event[3]);
1545*2531c97eSMatthias Ringwald 
1546*2531c97eSMatthias Ringwald                             remote_name_event[9+248] = 0;   // assert \0 for log_info
1547*2531c97eSMatthias Ringwald                             log_info("DAEMON_EVENT_REMOTE_NAME_CACHED %s = '%s'", bd_addr_to_str(addr), &remote_name_event[9]);
1548*2531c97eSMatthias Ringwald                             hci_dump_packet(HCI_EVENT_PACKET, 0, remote_name_event, sizeof(remote_name_event)-1);
1549*2531c97eSMatthias Ringwald                             daemon_emit_packet(connection, HCI_EVENT_PACKET, channel, remote_name_event, sizeof(remote_name_event) -1);
1550*2531c97eSMatthias Ringwald                         }
1551*2531c97eSMatthias Ringwald                         offset += 14; // 6 + 1 + 1 + 1 + 3 + 2;
1552*2531c97eSMatthias Ringwald                     }
1553*2531c97eSMatthias Ringwald                     return;
1554*2531c97eSMatthias Ringwald                 }
1555*2531c97eSMatthias Ringwald 
1556*2531c97eSMatthias Ringwald                 case RFCOMM_EVENT_CREDITS:
1557*2531c97eSMatthias Ringwald                     // RFCOMM CREDITS received...
1558*2531c97eSMatthias Ringwald                     daemon_retry_parked();
1559*2531c97eSMatthias Ringwald                     break;
1560*2531c97eSMatthias Ringwald 
1561*2531c97eSMatthias Ringwald                 case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
1562*2531c97eSMatthias Ringwald                     cid = little_endian_read_16(packet, 13);
1563*2531c97eSMatthias Ringwald                     connection = connection_for_rfcomm_cid(cid);
1564*2531c97eSMatthias Ringwald                     if (!connection) break;
1565*2531c97eSMatthias Ringwald                     if (packet[2]) {
1566*2531c97eSMatthias Ringwald                         daemon_remove_client_rfcomm_channel(connection, cid);
1567*2531c97eSMatthias Ringwald                     } else {
1568*2531c97eSMatthias Ringwald                         daemon_add_client_rfcomm_channel(connection, cid);
1569*2531c97eSMatthias Ringwald                     }
1570*2531c97eSMatthias Ringwald                     break;
1571*2531c97eSMatthias Ringwald                 case RFCOMM_EVENT_CHANNEL_CLOSED:
1572*2531c97eSMatthias Ringwald                     cid = little_endian_read_16(packet, 2);
1573*2531c97eSMatthias Ringwald                     connection = connection_for_rfcomm_cid(cid);
1574*2531c97eSMatthias Ringwald                     if (!connection) break;
1575*2531c97eSMatthias Ringwald                     daemon_remove_client_rfcomm_channel(connection, cid);
1576*2531c97eSMatthias Ringwald                     break;
1577*2531c97eSMatthias Ringwald                 case RFCOMM_EVENT_SERVICE_REGISTERED:
1578*2531c97eSMatthias Ringwald                     if (packet[2]) break;
1579*2531c97eSMatthias Ringwald                     daemon_add_client_rfcomm_service(connection, packet[3]);
1580*2531c97eSMatthias Ringwald                     break;
1581*2531c97eSMatthias Ringwald                 case L2CAP_EVENT_CHANNEL_OPENED:
1582*2531c97eSMatthias Ringwald                     cid = little_endian_read_16(packet, 13);
1583*2531c97eSMatthias Ringwald                     connection = connection_for_l2cap_cid(cid);
1584*2531c97eSMatthias Ringwald                     if (!connection) break;
1585*2531c97eSMatthias Ringwald                     if (packet[2]) {
1586*2531c97eSMatthias Ringwald                         daemon_remove_client_l2cap_channel(connection, cid);
1587*2531c97eSMatthias Ringwald                     } else {
1588*2531c97eSMatthias Ringwald                         daemon_add_client_l2cap_channel(connection, cid);
1589*2531c97eSMatthias Ringwald                     }
1590*2531c97eSMatthias Ringwald                     break;
1591*2531c97eSMatthias Ringwald                 case L2CAP_EVENT_CHANNEL_CLOSED:
1592*2531c97eSMatthias Ringwald                     cid = little_endian_read_16(packet, 2);
1593*2531c97eSMatthias Ringwald                     connection = connection_for_l2cap_cid(cid);
1594*2531c97eSMatthias Ringwald                     if (!connection) break;
1595*2531c97eSMatthias Ringwald                     daemon_remove_client_l2cap_channel(connection, cid);
1596*2531c97eSMatthias Ringwald                     break;
1597*2531c97eSMatthias Ringwald #if defined(ENABLE_BLE) && defined(HAVE_MALLOC)
1598*2531c97eSMatthias Ringwald                 case HCI_EVENT_DISCONNECTION_COMPLETE:
1599*2531c97eSMatthias Ringwald                     log_info("daemon : ignore HCI_EVENT_DISCONNECTION_COMPLETE ingnoring.");
1600*2531c97eSMatthias Ringwald                     // note: moved to gatt_client_handler because it's received here prematurely
1601*2531c97eSMatthias Ringwald                     // daemon_remove_gatt_client_helper(little_endian_read_16(packet, 3));
1602*2531c97eSMatthias Ringwald                     break;
1603*2531c97eSMatthias Ringwald #endif
1604*2531c97eSMatthias Ringwald                 default:
1605*2531c97eSMatthias Ringwald                     break;
1606*2531c97eSMatthias Ringwald             }
1607*2531c97eSMatthias Ringwald             break;
1608*2531c97eSMatthias Ringwald         case L2CAP_DATA_PACKET:
1609*2531c97eSMatthias Ringwald             connection = connection_for_l2cap_cid(channel);
1610*2531c97eSMatthias Ringwald             if (!connection) return;
1611*2531c97eSMatthias Ringwald             break;
1612*2531c97eSMatthias Ringwald         case RFCOMM_DATA_PACKET:
1613*2531c97eSMatthias Ringwald             connection = connection_for_l2cap_cid(channel);
1614*2531c97eSMatthias Ringwald             if (!connection) return;
1615*2531c97eSMatthias Ringwald             break;
1616*2531c97eSMatthias Ringwald         default:
1617*2531c97eSMatthias Ringwald             break;
1618*2531c97eSMatthias Ringwald     }
1619*2531c97eSMatthias Ringwald 
1620*2531c97eSMatthias Ringwald     daemon_emit_packet(connection, packet_type, channel, packet, size);
1621*2531c97eSMatthias Ringwald }
1622*2531c97eSMatthias Ringwald 
1623*2531c97eSMatthias Ringwald static void l2cap_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){
1624*2531c97eSMatthias Ringwald     daemon_packet_handler(NULL, packet_type, channel, packet, size);
1625*2531c97eSMatthias Ringwald }
1626*2531c97eSMatthias Ringwald static void rfcomm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){
1627*2531c97eSMatthias Ringwald     daemon_packet_handler(NULL, packet_type, channel, packet, size);
1628*2531c97eSMatthias Ringwald }
1629*2531c97eSMatthias Ringwald 
1630*2531c97eSMatthias Ringwald static void handle_sdp_rfcomm_service_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1631*2531c97eSMatthias Ringwald     switch (packet[0]){
1632*2531c97eSMatthias Ringwald         case SDP_EVENT_QUERY_RFCOMM_SERVICE:
1633*2531c97eSMatthias Ringwald         case SDP_EVENT_QUERY_COMPLETE:
1634*2531c97eSMatthias Ringwald             // already HCI Events, just forward them
1635*2531c97eSMatthias Ringwald             hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size);
1636*2531c97eSMatthias Ringwald             socket_connection_send_packet(sdp_client_query_connection, HCI_EVENT_PACKET, 0, packet, size);
1637*2531c97eSMatthias Ringwald             break;
1638*2531c97eSMatthias Ringwald         default:
1639*2531c97eSMatthias Ringwald             break;
1640*2531c97eSMatthias Ringwald     }
1641*2531c97eSMatthias Ringwald }
1642*2531c97eSMatthias Ringwald 
1643*2531c97eSMatthias Ringwald static void sdp_client_assert_buffer(int size){
1644*2531c97eSMatthias Ringwald     if (size > attribute_value_buffer_size){
1645*2531c97eSMatthias Ringwald         log_error("SDP attribute value buffer size exceeded: available %d, required %d", attribute_value_buffer_size, size);
1646*2531c97eSMatthias Ringwald     }
1647*2531c97eSMatthias Ringwald }
1648*2531c97eSMatthias Ringwald 
1649*2531c97eSMatthias Ringwald // define new packet type SDP_CLIENT_PACKET
1650*2531c97eSMatthias Ringwald static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1651*2531c97eSMatthias Ringwald     int event_len;
1652*2531c97eSMatthias Ringwald 
1653*2531c97eSMatthias Ringwald     switch (packet[0]){
1654*2531c97eSMatthias Ringwald         case SDP_EVENT_QUERY_ATTRIBUTE_BYTE:
1655*2531c97eSMatthias Ringwald             sdp_client_assert_buffer(sdp_event_query_attribute_byte_get_attribute_length(packet));
1656*2531c97eSMatthias Ringwald             attribute_value[sdp_event_query_attribute_byte_get_data_offset(packet)] = sdp_event_query_attribute_byte_get_data(packet);
1657*2531c97eSMatthias Ringwald             if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)){
1658*2531c97eSMatthias Ringwald                 log_info_hexdump(attribute_value, sdp_event_query_attribute_byte_get_attribute_length(packet));
1659*2531c97eSMatthias Ringwald 
1660*2531c97eSMatthias Ringwald                 int event_len = 1 + 3 * 2 + sdp_event_query_attribute_byte_get_attribute_length(packet);
1661*2531c97eSMatthias Ringwald                 uint8_t event[event_len];
1662*2531c97eSMatthias Ringwald                 event[0] = SDP_EVENT_QUERY_ATTRIBUTE_VALUE;
1663*2531c97eSMatthias Ringwald                 little_endian_store_16(event, 1, sdp_event_query_attribute_byte_get_record_id(packet));
1664*2531c97eSMatthias Ringwald                 little_endian_store_16(event, 3, sdp_event_query_attribute_byte_get_attribute_id(packet));
1665*2531c97eSMatthias Ringwald                 little_endian_store_16(event, 5, (uint16_t)sdp_event_query_attribute_byte_get_attribute_length(packet));
1666*2531c97eSMatthias Ringwald                 memcpy(&event[7], attribute_value, sdp_event_query_attribute_byte_get_attribute_length(packet));
1667*2531c97eSMatthias Ringwald                 hci_dump_packet(SDP_CLIENT_PACKET, 0, event, event_len);
1668*2531c97eSMatthias Ringwald                 socket_connection_send_packet(sdp_client_query_connection, SDP_CLIENT_PACKET, 0, event, event_len);
1669*2531c97eSMatthias Ringwald             }
1670*2531c97eSMatthias Ringwald             break;
1671*2531c97eSMatthias Ringwald         case SDP_EVENT_QUERY_COMPLETE:
1672*2531c97eSMatthias Ringwald             event_len = packet[1] + 2;
1673*2531c97eSMatthias Ringwald             hci_dump_packet(HCI_EVENT_PACKET, 0, packet, event_len);
1674*2531c97eSMatthias Ringwald             socket_connection_send_packet(sdp_client_query_connection, HCI_EVENT_PACKET, 0, packet, event_len);
1675*2531c97eSMatthias Ringwald             break;
1676*2531c97eSMatthias Ringwald     }
1677*2531c97eSMatthias Ringwald }
1678*2531c97eSMatthias Ringwald 
1679*2531c97eSMatthias Ringwald static void power_notification_callback(POWER_NOTIFICATION_t notification){
1680*2531c97eSMatthias Ringwald     switch (notification) {
1681*2531c97eSMatthias Ringwald         case POWER_WILL_SLEEP:
1682*2531c97eSMatthias Ringwald             // let's sleep
1683*2531c97eSMatthias Ringwald             power_management_sleep = 1;
1684*2531c97eSMatthias Ringwald             hci_power_control(HCI_POWER_SLEEP);
1685*2531c97eSMatthias Ringwald             break;
1686*2531c97eSMatthias Ringwald         case POWER_WILL_WAKE_UP:
1687*2531c97eSMatthias Ringwald             // assume that all clients use Bluetooth -> if connection, start Bluetooth
1688*2531c97eSMatthias Ringwald             power_management_sleep = 0;
1689*2531c97eSMatthias Ringwald             if (clients_require_power_on()) {
1690*2531c97eSMatthias Ringwald                 hci_power_control(HCI_POWER_ON);
1691*2531c97eSMatthias Ringwald             }
1692*2531c97eSMatthias Ringwald             break;
1693*2531c97eSMatthias Ringwald         default:
1694*2531c97eSMatthias Ringwald             break;
1695*2531c97eSMatthias Ringwald     }
1696*2531c97eSMatthias Ringwald }
1697*2531c97eSMatthias Ringwald 
1698*2531c97eSMatthias Ringwald static void daemon_sigint_handler(int param){
1699*2531c97eSMatthias Ringwald 
1700*2531c97eSMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
1701*2531c97eSMatthias Ringwald     // notify daemons
1702*2531c97eSMatthias Ringwald     notify_post("ch.ringwald.btstack.stopped");
1703*2531c97eSMatthias Ringwald #endif
1704*2531c97eSMatthias Ringwald 
1705*2531c97eSMatthias Ringwald     log_info(" <= SIGINT received, shutting down..\n");
1706*2531c97eSMatthias Ringwald 
1707*2531c97eSMatthias Ringwald     hci_power_control( HCI_POWER_OFF);
1708*2531c97eSMatthias Ringwald     hci_close();
1709*2531c97eSMatthias Ringwald 
1710*2531c97eSMatthias Ringwald     log_info("Good bye, see you.\n");
1711*2531c97eSMatthias Ringwald 
1712*2531c97eSMatthias Ringwald     exit(0);
1713*2531c97eSMatthias Ringwald }
1714*2531c97eSMatthias Ringwald 
1715*2531c97eSMatthias Ringwald // MARK: manage power off timer
1716*2531c97eSMatthias Ringwald 
1717*2531c97eSMatthias Ringwald #define USE_POWER_OFF_TIMER
1718*2531c97eSMatthias Ringwald 
1719*2531c97eSMatthias Ringwald static void stop_power_off_timer(void){
1720*2531c97eSMatthias Ringwald #ifdef USE_POWER_OFF_TIMER
1721*2531c97eSMatthias Ringwald     if (timeout_active) {
1722*2531c97eSMatthias Ringwald         btstack_run_loop_remove_timer(&timeout);
1723*2531c97eSMatthias Ringwald         timeout_active = 0;
1724*2531c97eSMatthias Ringwald     }
1725*2531c97eSMatthias Ringwald #endif
1726*2531c97eSMatthias Ringwald }
1727*2531c97eSMatthias Ringwald 
1728*2531c97eSMatthias Ringwald static void start_power_off_timer(void){
1729*2531c97eSMatthias Ringwald #ifdef USE_POWER_OFF_TIMER
1730*2531c97eSMatthias Ringwald     stop_power_off_timer();
1731*2531c97eSMatthias Ringwald     btstack_run_loop_set_timer(&timeout, DAEMON_NO_ACTIVE_CLIENT_TIMEOUT);
1732*2531c97eSMatthias Ringwald     btstack_run_loop_add_timer(&timeout);
1733*2531c97eSMatthias Ringwald     timeout_active = 1;
1734*2531c97eSMatthias Ringwald #else
1735*2531c97eSMatthias Ringwald     hci_power_control(HCI_POWER_OFF);
1736*2531c97eSMatthias Ringwald #endif
1737*2531c97eSMatthias Ringwald }
1738*2531c97eSMatthias Ringwald 
1739*2531c97eSMatthias Ringwald // MARK: manage list of clients
1740*2531c97eSMatthias Ringwald 
1741*2531c97eSMatthias Ringwald 
1742*2531c97eSMatthias Ringwald static client_state_t * client_for_connection(connection_t *connection) {
1743*2531c97eSMatthias Ringwald     btstack_linked_item_t *it;
1744*2531c97eSMatthias Ringwald     for (it = (btstack_linked_item_t *) clients; it ; it = it->next){
1745*2531c97eSMatthias Ringwald         client_state_t * client_state = (client_state_t *) it;
1746*2531c97eSMatthias Ringwald         if (client_state->connection == connection) {
1747*2531c97eSMatthias Ringwald             return client_state;
1748*2531c97eSMatthias Ringwald         }
1749*2531c97eSMatthias Ringwald     }
1750*2531c97eSMatthias Ringwald     return NULL;
1751*2531c97eSMatthias Ringwald }
1752*2531c97eSMatthias Ringwald 
1753*2531c97eSMatthias Ringwald static void clients_clear_power_request(void){
1754*2531c97eSMatthias Ringwald     btstack_linked_item_t *it;
1755*2531c97eSMatthias Ringwald     for (it = (btstack_linked_item_t *) clients; it ; it = it->next){
1756*2531c97eSMatthias Ringwald         client_state_t * client_state = (client_state_t *) it;
1757*2531c97eSMatthias Ringwald         client_state->power_mode = HCI_POWER_OFF;
1758*2531c97eSMatthias Ringwald     }
1759*2531c97eSMatthias Ringwald }
1760*2531c97eSMatthias Ringwald 
1761*2531c97eSMatthias Ringwald static int clients_require_power_on(void){
1762*2531c97eSMatthias Ringwald 
1763*2531c97eSMatthias Ringwald     if (global_enable) return 1;
1764*2531c97eSMatthias Ringwald 
1765*2531c97eSMatthias Ringwald     btstack_linked_item_t *it;
1766*2531c97eSMatthias Ringwald     for (it = (btstack_linked_item_t *) clients; it ; it = it->next){
1767*2531c97eSMatthias Ringwald         client_state_t * client_state = (client_state_t *) it;
1768*2531c97eSMatthias Ringwald         if (client_state->power_mode == HCI_POWER_ON) {
1769*2531c97eSMatthias Ringwald             return 1;
1770*2531c97eSMatthias Ringwald         }
1771*2531c97eSMatthias Ringwald     }
1772*2531c97eSMatthias Ringwald     return 0;
1773*2531c97eSMatthias Ringwald }
1774*2531c97eSMatthias Ringwald 
1775*2531c97eSMatthias Ringwald static int clients_require_discoverable(void){
1776*2531c97eSMatthias Ringwald     btstack_linked_item_t *it;
1777*2531c97eSMatthias Ringwald     for (it = (btstack_linked_item_t *) clients; it ; it = it->next){
1778*2531c97eSMatthias Ringwald         client_state_t * client_state = (client_state_t *) it;
1779*2531c97eSMatthias Ringwald         if (client_state->discoverable) {
1780*2531c97eSMatthias Ringwald             return 1;
1781*2531c97eSMatthias Ringwald         }
1782*2531c97eSMatthias Ringwald     }
1783*2531c97eSMatthias Ringwald     return 0;
1784*2531c97eSMatthias Ringwald }
1785*2531c97eSMatthias Ringwald 
1786*2531c97eSMatthias Ringwald static void usage(const char * name) {
1787*2531c97eSMatthias Ringwald     printf("%s, BTstack background daemon\n", name);
1788*2531c97eSMatthias Ringwald     printf("usage: %s [--help] [--tcp port]\n", name);
1789*2531c97eSMatthias Ringwald     printf("    --help   display this usage\n");
1790*2531c97eSMatthias Ringwald     printf("    --tcp    use TCP server on port %u\n", BTSTACK_PORT);
1791*2531c97eSMatthias Ringwald     printf("Without the --tcp option, BTstack daemon is listening on unix domain socket %s\n\n", BTSTACK_UNIX);
1792*2531c97eSMatthias Ringwald }
1793*2531c97eSMatthias Ringwald 
1794*2531c97eSMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
1795*2531c97eSMatthias Ringwald static void * btstack_run_loop_thread(void *context){
1796*2531c97eSMatthias Ringwald     btstack_run_loop_execute();
1797*2531c97eSMatthias Ringwald     return NULL;
1798*2531c97eSMatthias Ringwald }
1799*2531c97eSMatthias Ringwald #endif
1800*2531c97eSMatthias Ringwald 
1801*2531c97eSMatthias Ringwald #ifdef ENABLE_BLE
1802*2531c97eSMatthias Ringwald 
1803*2531c97eSMatthias Ringwald static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){
1804*2531c97eSMatthias Ringwald 
1805*2531c97eSMatthias Ringwald     // hack: handle disconnection_complete_here instead of main hci event packet handler
1806*2531c97eSMatthias Ringwald     // we receive a HCI event packet in disguise
1807*2531c97eSMatthias Ringwald     if (packet[0] == HCI_EVENT_DISCONNECTION_COMPLETE){
1808*2531c97eSMatthias Ringwald         log_info("daemon hack: handle disconnection_complete in handle_gatt_client_event instead of main hci event packet handler");
1809*2531c97eSMatthias Ringwald         uint16_t handle = little_endian_read_16(packet, 3);
1810*2531c97eSMatthias Ringwald         daemon_remove_gatt_client_helper(handle);
1811*2531c97eSMatthias Ringwald         return;
1812*2531c97eSMatthias Ringwald     }
1813*2531c97eSMatthias Ringwald 
1814*2531c97eSMatthias Ringwald     // only handle GATT Events
1815*2531c97eSMatthias Ringwald     switch(packet[0]){
1816*2531c97eSMatthias Ringwald         case GATT_EVENT_SERVICE_QUERY_RESULT:
1817*2531c97eSMatthias Ringwald         case GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT:
1818*2531c97eSMatthias Ringwald         case GATT_EVENT_NOTIFICATION:
1819*2531c97eSMatthias Ringwald         case GATT_EVENT_INDICATION:
1820*2531c97eSMatthias Ringwald         case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
1821*2531c97eSMatthias Ringwald         case GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT:
1822*2531c97eSMatthias Ringwald         case GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT:
1823*2531c97eSMatthias Ringwald         case GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT:
1824*2531c97eSMatthias Ringwald         case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
1825*2531c97eSMatthias Ringwald         case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT:
1826*2531c97eSMatthias Ringwald         case GATT_EVENT_QUERY_COMPLETE:
1827*2531c97eSMatthias Ringwald            break;
1828*2531c97eSMatthias Ringwald         default:
1829*2531c97eSMatthias Ringwald             return;
1830*2531c97eSMatthias Ringwald     }
1831*2531c97eSMatthias Ringwald 
1832*2531c97eSMatthias Ringwald     uint16_t con_handle = little_endian_read_16(packet, 2);
1833*2531c97eSMatthias Ringwald     btstack_linked_list_gatt_client_helper_t * gatt_client_helper = daemon_get_gatt_client_helper(con_handle);
1834*2531c97eSMatthias Ringwald     if (!gatt_client_helper){
1835*2531c97eSMatthias Ringwald         log_info("daemon handle_gatt_client_event: gc helper for handle 0x%2x is NULL.", con_handle);
1836*2531c97eSMatthias Ringwald         return;
1837*2531c97eSMatthias Ringwald     }
1838*2531c97eSMatthias Ringwald 
1839*2531c97eSMatthias Ringwald     connection_t *connection = NULL;
1840*2531c97eSMatthias Ringwald 
1841*2531c97eSMatthias Ringwald     // daemon doesn't track which connection subscribed to this particular handle, so we just notify all connections
1842*2531c97eSMatthias Ringwald     switch(packet[0]){
1843*2531c97eSMatthias Ringwald         case GATT_EVENT_NOTIFICATION:
1844*2531c97eSMatthias Ringwald         case GATT_EVENT_INDICATION:{
1845*2531c97eSMatthias Ringwald             hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size);
1846*2531c97eSMatthias Ringwald 
1847*2531c97eSMatthias Ringwald             btstack_linked_item_t *it;
1848*2531c97eSMatthias Ringwald             for (it = (btstack_linked_item_t *) clients; it ; it = it->next){
1849*2531c97eSMatthias Ringwald                 client_state_t * client_state = (client_state_t *) it;
1850*2531c97eSMatthias Ringwald                 socket_connection_send_packet(client_state->connection, HCI_EVENT_PACKET, 0, packet, size);
1851*2531c97eSMatthias Ringwald             }
1852*2531c97eSMatthias Ringwald             return;
1853*2531c97eSMatthias Ringwald         }
1854*2531c97eSMatthias Ringwald         default:
1855*2531c97eSMatthias Ringwald             break;
1856*2531c97eSMatthias Ringwald     }
1857*2531c97eSMatthias Ringwald 
1858*2531c97eSMatthias Ringwald     // otherwise, we have to have an active connection
1859*2531c97eSMatthias Ringwald     connection = gatt_client_helper->active_connection;
1860*2531c97eSMatthias Ringwald     uint16_t offset;
1861*2531c97eSMatthias Ringwald     uint16_t length;
1862*2531c97eSMatthias Ringwald 
1863*2531c97eSMatthias Ringwald     if (!connection) return;
1864*2531c97eSMatthias Ringwald 
1865*2531c97eSMatthias Ringwald     switch(packet[0]){
1866*2531c97eSMatthias Ringwald 
1867*2531c97eSMatthias Ringwald         case GATT_EVENT_SERVICE_QUERY_RESULT:
1868*2531c97eSMatthias Ringwald         case GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT:
1869*2531c97eSMatthias Ringwald         case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
1870*2531c97eSMatthias Ringwald         case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
1871*2531c97eSMatthias Ringwald         case GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT:
1872*2531c97eSMatthias Ringwald         case GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT:
1873*2531c97eSMatthias Ringwald             hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size);
1874*2531c97eSMatthias Ringwald             socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, packet, size);
1875*2531c97eSMatthias Ringwald             break;
1876*2531c97eSMatthias Ringwald 
1877*2531c97eSMatthias Ringwald         case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT:
1878*2531c97eSMatthias Ringwald         case GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT:
1879*2531c97eSMatthias Ringwald             offset = little_endian_read_16(packet, 6);
1880*2531c97eSMatthias Ringwald             length = little_endian_read_16(packet, 8);
1881*2531c97eSMatthias Ringwald             gatt_client_helper->characteristic_buffer[0] = packet[0];               // store type (characteristic/descriptor)
1882*2531c97eSMatthias Ringwald             gatt_client_helper->characteristic_handle    = little_endian_read_16(packet, 4);   // store attribute handle
1883*2531c97eSMatthias Ringwald             gatt_client_helper->characteristic_length = offset + length;            // update length
1884*2531c97eSMatthias Ringwald             memcpy(&gatt_client_helper->characteristic_buffer[10 + offset], &packet[10], length);
1885*2531c97eSMatthias Ringwald             break;
1886*2531c97eSMatthias Ringwald 
1887*2531c97eSMatthias Ringwald         case GATT_EVENT_QUERY_COMPLETE:{
1888*2531c97eSMatthias Ringwald             gatt_client_helper->active_connection = NULL;
1889*2531c97eSMatthias Ringwald             if (gatt_client_helper->characteristic_length){
1890*2531c97eSMatthias Ringwald                 // send re-combined long characteristic value or long characteristic descriptor value
1891*2531c97eSMatthias Ringwald                 uint8_t * event = gatt_client_helper->characteristic_buffer;
1892*2531c97eSMatthias Ringwald                 uint16_t event_size = 10 + gatt_client_helper->characteristic_length;
1893*2531c97eSMatthias Ringwald                 // event[0] == already set by previsous case
1894*2531c97eSMatthias Ringwald                 event[1] = 8 + gatt_client_helper->characteristic_length;
1895*2531c97eSMatthias Ringwald                 little_endian_store_16(event, 2, little_endian_read_16(packet, 2));
1896*2531c97eSMatthias Ringwald                 little_endian_store_16(event, 4, gatt_client_helper->characteristic_handle);
1897*2531c97eSMatthias Ringwald                 little_endian_store_16(event, 6, 0);   // offset
1898*2531c97eSMatthias Ringwald                 little_endian_store_16(event, 8, gatt_client_helper->characteristic_length);
1899*2531c97eSMatthias Ringwald                 hci_dump_packet(HCI_EVENT_PACKET, 0, event, event_size);
1900*2531c97eSMatthias Ringwald                 socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, event_size);
1901*2531c97eSMatthias Ringwald                 gatt_client_helper->characteristic_length = 0;
1902*2531c97eSMatthias Ringwald             }
1903*2531c97eSMatthias Ringwald             hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size);
1904*2531c97eSMatthias Ringwald             socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, packet, size);
1905*2531c97eSMatthias Ringwald             break;
1906*2531c97eSMatthias Ringwald         }
1907*2531c97eSMatthias Ringwald         default:
1908*2531c97eSMatthias Ringwald             break;
1909*2531c97eSMatthias Ringwald     }
1910*2531c97eSMatthias Ringwald }
1911*2531c97eSMatthias Ringwald #endif
1912*2531c97eSMatthias Ringwald 
1913*2531c97eSMatthias Ringwald static char hostname[30];
1914*2531c97eSMatthias Ringwald 
1915*2531c97eSMatthias Ringwald int main (int argc,  char * const * argv){
1916*2531c97eSMatthias Ringwald 
1917*2531c97eSMatthias Ringwald     static int tcp_flag = 0;
1918*2531c97eSMatthias Ringwald 
1919*2531c97eSMatthias Ringwald     while (1) {
1920*2531c97eSMatthias Ringwald         static struct option long_options[] = {
1921*2531c97eSMatthias Ringwald             { "tcp", no_argument, &tcp_flag, 1 },
1922*2531c97eSMatthias Ringwald             { "help", no_argument, 0, 0 },
1923*2531c97eSMatthias Ringwald             { 0,0,0,0 } // This is a filler for -1
1924*2531c97eSMatthias Ringwald         };
1925*2531c97eSMatthias Ringwald 
1926*2531c97eSMatthias Ringwald         int c;
1927*2531c97eSMatthias Ringwald         int option_index = -1;
1928*2531c97eSMatthias Ringwald 
1929*2531c97eSMatthias Ringwald         c = getopt_long(argc, argv, "h", long_options, &option_index);
1930*2531c97eSMatthias Ringwald 
1931*2531c97eSMatthias Ringwald         if (c == -1) break; // no more option
1932*2531c97eSMatthias Ringwald 
1933*2531c97eSMatthias Ringwald         // treat long parameter first
1934*2531c97eSMatthias Ringwald         if (option_index == -1) {
1935*2531c97eSMatthias Ringwald             switch (c) {
1936*2531c97eSMatthias Ringwald                 case '?':
1937*2531c97eSMatthias Ringwald                 case 'h':
1938*2531c97eSMatthias Ringwald                     usage(argv[0]);
1939*2531c97eSMatthias Ringwald                     return 0;
1940*2531c97eSMatthias Ringwald                     break;
1941*2531c97eSMatthias Ringwald             }
1942*2531c97eSMatthias Ringwald         } else {
1943*2531c97eSMatthias Ringwald             switch (option_index) {
1944*2531c97eSMatthias Ringwald                 case 1:
1945*2531c97eSMatthias Ringwald                     usage(argv[0]);
1946*2531c97eSMatthias Ringwald                     return 0;
1947*2531c97eSMatthias Ringwald                     break;
1948*2531c97eSMatthias Ringwald             }
1949*2531c97eSMatthias Ringwald         }
1950*2531c97eSMatthias Ringwald     }
1951*2531c97eSMatthias Ringwald 
1952*2531c97eSMatthias Ringwald     if (tcp_flag){
1953*2531c97eSMatthias Ringwald         printf("BTstack Daemon started on port %u\n", BTSTACK_PORT);
1954*2531c97eSMatthias Ringwald     } else {
1955*2531c97eSMatthias Ringwald         printf("BTstack Daemon started on socket %s\n", BTSTACK_UNIX);
1956*2531c97eSMatthias Ringwald     }
1957*2531c97eSMatthias Ringwald 
1958*2531c97eSMatthias Ringwald     // make stdout unbuffered
1959*2531c97eSMatthias Ringwald     setbuf(stdout, NULL);
1960*2531c97eSMatthias Ringwald 
1961*2531c97eSMatthias Ringwald     // handle CTRL-c
1962*2531c97eSMatthias Ringwald     signal(SIGINT, daemon_sigint_handler);
1963*2531c97eSMatthias Ringwald     // handle SIGTERM - suggested for launchd
1964*2531c97eSMatthias Ringwald     signal(SIGTERM, daemon_sigint_handler);
1965*2531c97eSMatthias Ringwald 
1966*2531c97eSMatthias Ringwald     // TODO: win32 variant
1967*2531c97eSMatthias Ringwald #ifndef _WIN32
1968*2531c97eSMatthias Ringwald     // handle SIGPIPE
1969*2531c97eSMatthias Ringwald     struct sigaction act;
1970*2531c97eSMatthias Ringwald     act.sa_handler = SIG_IGN;
1971*2531c97eSMatthias Ringwald     sigemptyset (&act.sa_mask);
1972*2531c97eSMatthias Ringwald     act.sa_flags = 0;
1973*2531c97eSMatthias Ringwald     sigaction (SIGPIPE, &act, NULL);
1974*2531c97eSMatthias Ringwald #endif
1975*2531c97eSMatthias Ringwald 
1976*2531c97eSMatthias Ringwald     btstack_control_t * control = NULL;
1977*2531c97eSMatthias Ringwald     void * config;
1978*2531c97eSMatthias Ringwald 
1979*2531c97eSMatthias Ringwald #ifdef HAVE_TRANSPORT_H4
1980*2531c97eSMatthias Ringwald     hci_transport_config_uart.type = HCI_TRANSPORT_CONFIG_UART;
1981*2531c97eSMatthias Ringwald     hci_transport_config_uart.baudrate_init = UART_SPEED;
1982*2531c97eSMatthias Ringwald     hci_transport_config_uart.baudrate_main = 0;
1983*2531c97eSMatthias Ringwald     hci_transport_config_uart.flowcontrol = 1;
1984*2531c97eSMatthias Ringwald     hci_transport_config_uart.device_name   = UART_DEVICE;
1985*2531c97eSMatthias Ringwald     transport = hci_transport_h4_instance();
1986*2531c97eSMatthias Ringwald 
1987*2531c97eSMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
1988*2531c97eSMatthias Ringwald     // use default (max) UART baudrate over netgraph interface
1989*2531c97eSMatthias Ringwald     hci_transport_config_uart.baudrate_init = 0;
1990*2531c97eSMatthias Ringwald #endif
1991*2531c97eSMatthias Ringwald 
1992*2531c97eSMatthias Ringwald     config = &hci_transport_config_uart;
1993*2531c97eSMatthias Ringwald #endif
1994*2531c97eSMatthias Ringwald 
1995*2531c97eSMatthias Ringwald #ifdef HAVE_TRANSPORT_USB
1996*2531c97eSMatthias Ringwald     transport = hci_transport_usb_instance();
1997*2531c97eSMatthias Ringwald #endif
1998*2531c97eSMatthias Ringwald 
1999*2531c97eSMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
2000*2531c97eSMatthias Ringwald     control = &btstack_control_iphone;
2001*2531c97eSMatthias Ringwald     if (btstack_control_iphone_power_management_supported()){
2002*2531c97eSMatthias Ringwald         hci_transport_h4_iphone_set_enforce_wake_device("/dev/btwake");
2003*2531c97eSMatthias Ringwald     }
2004*2531c97eSMatthias Ringwald     bluetooth_status_handler = platform_iphone_status_handler;
2005*2531c97eSMatthias Ringwald     platform_iphone_register_window_manager_restart(update_ui_status);
2006*2531c97eSMatthias Ringwald     platform_iphone_register_preferences_changed(preferences_changed_callback);
2007*2531c97eSMatthias Ringwald #endif
2008*2531c97eSMatthias Ringwald 
2009*2531c97eSMatthias Ringwald #ifdef BTSTACK_LINK_KEY_DB_INSTANCE
2010*2531c97eSMatthias Ringwald     btstack_link_key_db = BTSTACK_LINK_KEY_DB_INSTANCE();
2011*2531c97eSMatthias Ringwald #endif
2012*2531c97eSMatthias Ringwald 
2013*2531c97eSMatthias Ringwald #ifdef BTSTACK_DEVICE_NAME_DB_INSTANCE
2014*2531c97eSMatthias Ringwald     btstack_device_name_db = BTSTACK_DEVICE_NAME_DB_INSTANCE();
2015*2531c97eSMatthias Ringwald #endif
2016*2531c97eSMatthias Ringwald 
2017*2531c97eSMatthias Ringwald     btstack_run_loop_init(btstack_run_loop_posix_get_instance());
2018*2531c97eSMatthias Ringwald 
2019*2531c97eSMatthias Ringwald     // init power management notifications
2020*2531c97eSMatthias Ringwald     if (control && control->register_for_power_notifications){
2021*2531c97eSMatthias Ringwald         control->register_for_power_notifications(power_notification_callback);
2022*2531c97eSMatthias Ringwald     }
2023*2531c97eSMatthias Ringwald 
2024*2531c97eSMatthias Ringwald     // logging
2025*2531c97eSMatthias Ringwald     loggingEnabled = 0;
2026*2531c97eSMatthias Ringwald     int newLoggingEnabled = 1;
2027*2531c97eSMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
2028*2531c97eSMatthias Ringwald     // iPhone has toggle in Preferences.app
2029*2531c97eSMatthias Ringwald     newLoggingEnabled = platform_iphone_logging_enabled();
2030*2531c97eSMatthias Ringwald #endif
2031*2531c97eSMatthias Ringwald     daemon_set_logging_enabled(newLoggingEnabled);
2032*2531c97eSMatthias Ringwald 
2033*2531c97eSMatthias Ringwald     // dump version
2034*2531c97eSMatthias Ringwald     log_info("BTdaemon started\n");
2035*2531c97eSMatthias Ringwald     log_info("version %s, build %s", BTSTACK_VERSION, BTSTACK_DATE);
2036*2531c97eSMatthias Ringwald 
2037*2531c97eSMatthias Ringwald     // init HCI
2038*2531c97eSMatthias Ringwald     hci_init(transport, config);
2039*2531c97eSMatthias Ringwald     if (btstack_link_key_db){
2040*2531c97eSMatthias Ringwald         hci_set_link_key_db(btstack_link_key_db);
2041*2531c97eSMatthias Ringwald     }
2042*2531c97eSMatthias Ringwald     if (control){
2043*2531c97eSMatthias Ringwald         hci_set_control(control);
2044*2531c97eSMatthias Ringwald     }
2045*2531c97eSMatthias Ringwald 
2046*2531c97eSMatthias Ringwald     // hostname for POSIX systems
2047*2531c97eSMatthias Ringwald     gethostname(hostname, 30);
2048*2531c97eSMatthias Ringwald     hostname[29] = '\0';
2049*2531c97eSMatthias Ringwald     gap_set_local_name(hostname);
2050*2531c97eSMatthias Ringwald 
2051*2531c97eSMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
2052*2531c97eSMatthias Ringwald     // iPhone doesn't use SSP yet as there's no UI for it yet and auto accept is not an option
2053*2531c97eSMatthias Ringwald     gap_ssp_set_enable(0);
2054*2531c97eSMatthias Ringwald #endif
2055*2531c97eSMatthias Ringwald 
2056*2531c97eSMatthias Ringwald     // register for HCI events
2057*2531c97eSMatthias Ringwald     hci_event_callback_registration.callback = &l2cap_packet_handler;
2058*2531c97eSMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
2059*2531c97eSMatthias Ringwald 
2060*2531c97eSMatthias Ringwald     // init L2CAP
2061*2531c97eSMatthias Ringwald     l2cap_init();
2062*2531c97eSMatthias Ringwald     l2cap_register_packet_handler(&l2cap_packet_handler);
2063*2531c97eSMatthias Ringwald     timeout.process = daemon_no_connections_timeout;
2064*2531c97eSMatthias Ringwald 
2065*2531c97eSMatthias Ringwald #ifdef ENABLE_RFCOMM
2066*2531c97eSMatthias Ringwald     log_info("config.h: ENABLE_RFCOMM\n");
2067*2531c97eSMatthias Ringwald     rfcomm_init();
2068*2531c97eSMatthias Ringwald #endif
2069*2531c97eSMatthias Ringwald 
2070*2531c97eSMatthias Ringwald #ifdef ENABLE_SDP
2071*2531c97eSMatthias Ringwald     sdp_init();
2072*2531c97eSMatthias Ringwald #endif
2073*2531c97eSMatthias Ringwald 
2074*2531c97eSMatthias Ringwald #ifdef ENABLE_BLE
2075*2531c97eSMatthias Ringwald     // GATT Client
2076*2531c97eSMatthias Ringwald     gatt_client_init();
2077*2531c97eSMatthias Ringwald 
2078*2531c97eSMatthias Ringwald     // sm_init();
2079*2531c97eSMatthias Ringwald     // sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY);
2080*2531c97eSMatthias Ringwald     // sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION);
2081*2531c97eSMatthias Ringwald 
2082*2531c97eSMatthias Ringwald     // GATT Server - empty attribute database
2083*2531c97eSMatthias Ringwald     le_device_db_init();
2084*2531c97eSMatthias Ringwald     att_server_init(NULL, NULL, NULL);
2085*2531c97eSMatthias Ringwald 
2086*2531c97eSMatthias Ringwald #endif
2087*2531c97eSMatthias Ringwald 
2088*2531c97eSMatthias Ringwald #ifdef USE_LAUNCHD
2089*2531c97eSMatthias Ringwald     socket_connection_create_launchd();
2090*2531c97eSMatthias Ringwald #else
2091*2531c97eSMatthias Ringwald     // create server
2092*2531c97eSMatthias Ringwald     if (tcp_flag) {
2093*2531c97eSMatthias Ringwald         socket_connection_create_tcp(BTSTACK_PORT);
2094*2531c97eSMatthias Ringwald     } else {
2095*2531c97eSMatthias Ringwald         socket_connection_create_unix(BTSTACK_UNIX);
2096*2531c97eSMatthias Ringwald     }
2097*2531c97eSMatthias Ringwald #endif
2098*2531c97eSMatthias Ringwald     socket_connection_register_packet_callback(&daemon_client_handler);
2099*2531c97eSMatthias Ringwald 
2100*2531c97eSMatthias Ringwald #ifdef HAVE_PLATFORM_IPHONE_OS
2101*2531c97eSMatthias Ringwald     // notify daemons
2102*2531c97eSMatthias Ringwald     notify_post("ch.ringwald.btstack.started");
2103*2531c97eSMatthias Ringwald 
2104*2531c97eSMatthias Ringwald     // spawn thread to have BTstack run loop on new thread, while main thread is used to keep CFRunLoop
2105*2531c97eSMatthias Ringwald     pthread_t run_loop;
2106*2531c97eSMatthias Ringwald     pthread_create(&run_loop, NULL, &btstack_run_loop_thread, NULL);
2107*2531c97eSMatthias Ringwald 
2108*2531c97eSMatthias Ringwald     // needed to receive notifications
2109*2531c97eSMatthias Ringwald     CFRunLoopRun();
2110*2531c97eSMatthias Ringwald #endif
2111*2531c97eSMatthias Ringwald         // go!
2112*2531c97eSMatthias Ringwald     btstack_run_loop_execute();
2113*2531c97eSMatthias Ringwald     return 0;
2114*2531c97eSMatthias Ringwald }
2115