xref: /btstack/src/ble/gatt-service/scan_parameters_service_client.c (revision c75b474d0b27c8ce1f802e81470eecb22cebf93f)
1 /*
2  * Copyright (C) 2021 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "scan_parameters_service_client.c"
39 
40 #include "btstack_config.h"
41 
42 #include <stdint.h>
43 #include <string.h>
44 
45 #ifdef ENABLE_TESTING_SUPPORT
46 #include <stdio.h>
47 #endif
48 
49 #include "scan_parameters_service_client.h"
50 
51 #include "btstack_memory.h"
52 #include "ble/core.h"
53 #include "ble/gatt_client.h"
54 #include "bluetooth_gatt.h"
55 #include "btstack_debug.h"
56 #include "btstack_event.h"
57 #include "btstack_run_loop.h"
58 #include "gap.h"
59 
60 #include "ble/gatt_service_client.h"
61 
62 static btstack_packet_callback_registration_t hci_event_callback_registration;
63 
64 static btstack_linked_list_t clients;
65 static uint16_t scan_parameters_service_cid_counter = 0;
66 static uint16_t scan_parameters_service_scan_window = 0;
67 static uint16_t scan_parameters_service_scan_interval = 0;
68 
69 static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
70 static void scan_parameters_service_send_next_query(void * context);
71 static btstack_context_callback_registration_t scan_parameters_service_handle_can_send_now;
72 
73 static uint16_t scan_parameters_service_get_next_cid(void){
74     if (scan_parameters_service_cid_counter == 0xffff) {
75         scan_parameters_service_cid_counter = 1;
76     } else {
77         scan_parameters_service_cid_counter++;
78     }
79     return scan_parameters_service_cid_counter;
80 }
81 
82 static uint8_t scan_parameters_client_request_send_gatt_query(scan_parameters_service_client_t * client){
83     scan_parameters_service_handle_can_send_now.context = (void *) (uintptr_t)client->cid;
84     uint8_t status = gatt_client_request_to_send_gatt_query(&scan_parameters_service_handle_can_send_now, client->con_handle);
85     if (status != ERROR_CODE_SUCCESS){
86         if (client->state >= SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE){
87             client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_IDLE;
88         }
89     }
90     return status;
91 }
92 
93 static scan_parameters_service_client_t * scan_parameters_service_create_client(hci_con_handle_t con_handle, uint16_t cid){
94     scan_parameters_service_client_t * client = btstack_memory_scan_parameters_service_client_get();
95     if (!client){
96         log_error("Not enough memory to create client");
97         return NULL;
98     }
99 
100     client->cid = cid;
101     client->con_handle = con_handle;
102     client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_IDLE;
103 
104     client->start_handle = 0;
105     client->end_handle = 0;
106 
107     client->scan_interval_window_value_handle = 0;
108     client->scan_interval_window_value_update = false;
109     btstack_linked_list_add(&clients, (btstack_linked_item_t *) client);
110     return client;
111 }
112 
113 static void scan_parameters_service_finalize_client(scan_parameters_service_client_t * client){
114     gatt_client_stop_listening_for_characteristic_value_updates(&client->notification_listener);
115     btstack_linked_list_remove(&clients, (btstack_linked_item_t *) client);
116     btstack_memory_scan_parameters_service_client_free(client);
117 }
118 
119 static scan_parameters_service_client_t * scan_parameters_service_get_client_for_con_handle(hci_con_handle_t con_handle){
120     btstack_linked_list_iterator_t it;
121     btstack_linked_list_iterator_init(&it, &clients);
122     while (btstack_linked_list_iterator_has_next(&it)){
123         scan_parameters_service_client_t * client = (scan_parameters_service_client_t *)btstack_linked_list_iterator_next(&it);
124         if (client->con_handle != con_handle) continue;
125         return client;
126     }
127     return NULL;
128 }
129 
130 static scan_parameters_service_client_t * scan_parameters_service_get_client_for_cid(uint16_t scan_parameters_service_cid){
131     btstack_linked_list_iterator_t it;
132     btstack_linked_list_iterator_init(&it, &clients);
133     while (btstack_linked_list_iterator_has_next(&it)){
134         scan_parameters_service_client_t * client = (scan_parameters_service_client_t *)btstack_linked_list_iterator_next(&it);
135         if (client->cid != scan_parameters_service_cid) continue;
136         return client;
137     }
138     return NULL;
139 }
140 
141 static void scan_parameters_service_emit_connection_established(scan_parameters_service_client_t * client, uint8_t status){
142     uint8_t event[6];
143     int pos = 0;
144     event[pos++] = HCI_EVENT_GATTSERVICE_META;
145     event[pos++] = sizeof(event) - 2;
146     event[pos++] = GATTSERVICE_SUBEVENT_SCAN_PARAMETERS_SERVICE_CONNECTED;
147     little_endian_store_16(event, pos, client->cid);
148     pos += 2;
149     event[pos++] = status;
150     (*client->client_handler)(HCI_EVENT_GATTSERVICE_META, 0, event, sizeof(event));
151 }
152 
153 static void scan_parameters_service_emit_disconnected(btstack_packet_handler_t packet_handler, uint16_t cid){
154     uint8_t event[5];
155     int pos = 0;
156     event[pos++] = HCI_EVENT_GATTSERVICE_META;
157     event[pos++] = sizeof(event) - 2;
158     event[pos++] = GATTSERVICE_SUBEVENT_SCAN_PARAMETERS_SERVICE_DISCONNECTED;
159     little_endian_store_16(event, pos, cid);
160     pos += 2;
161     btstack_assert(pos == sizeof(event));
162     (*packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
163 }
164 
165 static void handle_notification_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
166     UNUSED(packet_type);
167     UNUSED(channel);
168     UNUSED(size);
169 
170     if (hci_event_packet_get_type(packet) != GATT_EVENT_NOTIFICATION) return;
171 
172     scan_parameters_service_client_t * client = scan_parameters_service_get_client_for_con_handle(gatt_event_notification_get_handle(packet));
173     btstack_assert(client != NULL);
174     client->scan_interval_window_value_update = true;
175     scan_parameters_client_request_send_gatt_query(client);
176 }
177 
178 static void scan_parameters_service_send_next_query(void * context){
179     uint16_t cid = (uint16_t)(uintptr_t)context;
180     scan_parameters_service_client_t * client = scan_parameters_service_get_client_for_cid(cid);
181     if (client == NULL){
182         return;
183     }
184 
185     uint8_t att_status;
186     gatt_client_service_t service;
187 
188     gatt_client_characteristic_t characteristic;
189 
190     switch (client->state){
191         case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE:
192 #ifdef ENABLE_TESTING_SUPPORT
193             printf("\n\nQuery Services:\n");
194 #endif
195             client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT;
196             att_status = gatt_client_discover_primary_services_by_uuid16(handle_gatt_client_event, client->con_handle, ORG_BLUETOOTH_SERVICE_SCAN_PARAMETERS);
197             // TODO handle status
198             UNUSED(att_status);
199             break;
200 
201         case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTIC:
202 #ifdef ENABLE_TESTING_SUPPORT
203             printf("\n\nQuery Characteristics of service\n");
204 #endif
205             client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_RESULT;
206             service.start_group_handle = client->start_handle;
207             service.end_group_handle = client->end_handle;
208             att_status = gatt_client_discover_characteristics_for_service(
209                 handle_gatt_client_event, client->con_handle, &service);
210             // TODO handle status
211             UNUSED(att_status);
212             break;
213 
214         case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_CONNECTED:
215             if (client->scan_interval_window_value_update){
216                 client->scan_interval_window_value_update = false;
217 
218 #ifdef ENABLE_TESTING_SUPPORT
219                 printf("\n\nUpdate - interval %d, window %d:\n", scan_parameters_service_scan_interval, scan_parameters_service_scan_window);
220 #endif
221                 uint8_t value[4];
222                 little_endian_store_16(value, 0, scan_parameters_service_scan_interval);
223                 little_endian_store_16(value, 2, scan_parameters_service_scan_window);
224 
225                 att_status = gatt_client_write_value_of_characteristic_without_response(client->con_handle, client->scan_interval_window_value_handle, 4, value);
226                 // TODO handle status
227                 UNUSED(att_status);
228             }
229             break;
230 #ifdef ENABLE_TESTING_SUPPORT
231         case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_CCC:
232             client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_CCC;
233 
234             characteristic.value_handle = client->scan_refresh_value_handle;
235             characteristic.end_handle   =  client->scan_refresh_end_handle;
236 
237             // result in GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT
238             att_status = gatt_client_discover_characteristic_descriptors(&handle_gatt_client_event, client->con_handle, &characteristic);
239             UNUSED(att_status);
240             break;
241 #endif
242         case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_CONFIGURE_NOTIFICATIONS:
243 #ifdef ENABLE_TESTING_SUPPORT
244             printf("    Notification configuration enable ");
245 #endif
246 
247             client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_NOTIFICATIONS_CONFIGURED;
248 
249             characteristic.value_handle = client->scan_refresh_value_handle;
250             characteristic.end_handle = client->scan_refresh_end_handle;
251             characteristic.properties = client->scan_refresh_properties;
252 
253             // end of write marked in GATT_EVENT_QUERY_COMPLETE
254 
255             att_status = gatt_client_write_client_characteristic_configuration(&handle_gatt_client_event, client->con_handle, &characteristic, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
256 
257             if (att_status == ERROR_CODE_SUCCESS){
258                 gatt_client_listen_for_characteristic_value_updates(
259                             &client->notification_listener,
260                             &handle_notification_event, client->con_handle, &characteristic);
261             }
262             client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_CONNECTED;
263             break;
264         default:
265             break;
266     }
267 }
268 
269 static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
270     UNUSED(packet_type);
271     UNUSED(channel);
272     UNUSED(size);
273 
274     scan_parameters_service_client_t * client = NULL;
275     gatt_client_service_t service;
276     gatt_client_characteristic_t characteristic;
277     uint8_t status;
278 
279 #ifdef ENABLE_TESTING_SUPPORT
280     gatt_client_characteristic_descriptor_t characteristic_descriptor;
281 #endif
282 
283     switch(hci_event_packet_get_type(packet)){
284         case GATT_EVENT_SERVICE_QUERY_RESULT:
285             client = scan_parameters_service_get_client_for_con_handle(gatt_event_service_query_result_get_handle(packet));
286             btstack_assert(client != NULL);
287 
288             if (client->state != SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT) {
289                 scan_parameters_service_emit_connection_established(client, GATT_CLIENT_IN_WRONG_STATE);
290                 scan_parameters_service_finalize_client(client);
291                 return;
292             }
293 
294             gatt_event_service_query_result_get_service(packet, &service);
295             client->start_handle = service.start_group_handle;
296             client->end_handle = service.end_group_handle;
297 #ifdef ENABLE_TESTING_SUPPORT
298             printf("ScS Service: start handle 0x%04X, end handle 0x%04X\n", client->start_handle, client->end_handle);
299 #endif
300             break;
301 
302         case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
303             client = scan_parameters_service_get_client_for_con_handle(gatt_event_characteristic_query_result_get_handle(packet));
304             btstack_assert(client != NULL);
305 
306             // found scan_interval_window_value_handle, check att_status
307             gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
308             switch (characteristic.uuid16){
309                 case ORG_BLUETOOTH_CHARACTERISTIC_SCAN_INTERVAL_WINDOW:
310                     client->scan_interval_window_value_handle = characteristic.value_handle;
311 
312 #ifdef ENABLE_TESTING_SUPPORT
313                     printf("ScS Scan Interval Characteristic:  \n    Attribute Handle 0x%04X, Properties 0x%02X, Handle 0x%04X, UUID 0x%04X\n",
314                         characteristic.start_handle,
315                         characteristic.properties,
316                         characteristic.value_handle, characteristic.uuid16);
317 #endif
318                     break;
319                 case ORG_BLUETOOTH_CHARACTERISTIC_SCAN_REFRESH:
320                     client->scan_refresh_value_handle = characteristic.value_handle;
321                     client->scan_refresh_end_handle = characteristic.end_handle;
322                     client->scan_refresh_properties = characteristic.properties;
323 
324 #ifdef ENABLE_TESTING_SUPPORT
325                     printf("ScS Scan Refresh Characteristic:  \n    Attribute Handle 0x%04X, Properties 0x%02X, Handle 0x%04X, UUID 0x%04X\n",
326                         characteristic.start_handle,
327                         characteristic.properties,
328                         characteristic.value_handle, characteristic.uuid16);
329 #endif
330                     break;
331                 default:
332                     break;
333             }
334             break;
335 
336 #ifdef ENABLE_TESTING_SUPPORT
337         case GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT:
338             client = scan_parameters_service_get_client_for_con_handle(gatt_event_all_characteristic_descriptors_query_result_get_handle(packet));
339             btstack_assert(client != NULL);
340 
341             gatt_event_all_characteristic_descriptors_query_result_get_characteristic_descriptor(packet, &characteristic_descriptor);
342             if (characteristic_descriptor.uuid16 == ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION){
343                 printf("    Client Characteristic Configuration Descriptor: Handle 0x%04X, UUID 0x%04X\n",
344                     characteristic_descriptor.handle,
345                     characteristic_descriptor.uuid16);
346             }
347             break;
348 
349         case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
350             client = scan_parameters_service_get_client_for_con_handle(gatt_event_characteristic_value_query_result_get_handle(packet));
351             btstack_assert(client != NULL);
352 
353             printf("    Received CCC value: ");
354             printf_hexdump(gatt_event_characteristic_value_query_result_get_value(packet),  gatt_event_characteristic_value_query_result_get_value_length(packet));
355             break;
356 #endif
357 
358         case GATT_EVENT_QUERY_COMPLETE:
359             client = scan_parameters_service_get_client_for_con_handle(gatt_event_query_complete_get_handle(packet));
360             btstack_assert(client != NULL);
361 
362             status = gatt_client_att_status_to_error_code(gatt_event_query_complete_get_att_status(packet));
363 
364             switch (client->state){
365                 case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_SERVICE_RESULT:
366                     if (status != ERROR_CODE_SUCCESS){
367                         scan_parameters_service_emit_connection_established(client, status);
368                         scan_parameters_service_finalize_client(client);
369                         return;
370                     }
371 
372                     if (client->start_handle != 0){
373                         client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_CHARACTERISTIC;
374                         break;
375                     }
376 
377                     scan_parameters_service_emit_connection_established(client, ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
378                     scan_parameters_service_finalize_client(client);
379                     return;
380 
381                 case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_CHARACTERISTIC_RESULT:
382                     if (status != ERROR_CODE_SUCCESS){
383                         scan_parameters_service_emit_connection_established(client, status);
384                         scan_parameters_service_finalize_client(client);
385                         break;
386                     }
387                     if (client->scan_interval_window_value_handle == 0){
388                         scan_parameters_service_emit_connection_established(client, ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
389                         scan_parameters_service_finalize_client(client);
390                         return;
391                     }
392 #ifdef ENABLE_TESTING_SUPPORT
393                     client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_CCC;
394 #else
395                     client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_CONNECTED;
396                     client->scan_interval_window_value_update = true;
397                     scan_parameters_service_emit_connection_established(client, ERROR_CODE_SUCCESS);
398 #endif
399                     break;
400 
401 #ifdef ENABLE_TESTING_SUPPORT
402                 case SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W4_CCC:
403                     client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_CONNECTED;
404                     client->scan_interval_window_value_update = true;
405                     scan_parameters_service_emit_connection_established(client, ERROR_CODE_SUCCESS);
406                     break;
407 #endif
408                 default:
409                     break;
410             }
411             break;
412         default:
413             break;
414     }
415 
416     if (client != NULL){
417         scan_parameters_client_request_send_gatt_query(client);
418     }
419 }
420 
421 static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
422     UNUSED(packet_type); // ok: only hci events
423     UNUSED(channel);     // ok: there is no channel
424     UNUSED(size);        // ok: fixed format events read from HCI buffer
425 
426     hci_con_handle_t con_handle;
427     scan_parameters_service_client_t * client;
428 
429     switch (hci_event_packet_get_type(packet)) {
430         case HCI_EVENT_DISCONNECTION_COMPLETE:
431             con_handle = hci_event_disconnection_complete_get_connection_handle(packet);
432             client = scan_parameters_service_get_client_for_con_handle(con_handle);
433             if (client != NULL){
434                 // emit disconnected
435                 btstack_packet_handler_t packet_handler = client->client_handler;
436                 uint16_t cid = client->cid;
437                 scan_parameters_service_emit_disconnected(packet_handler, cid);
438                 // finalize
439                 scan_parameters_service_finalize_client(client);
440             }
441             break;
442         default:
443             break;
444     }
445 }
446 
447 void scan_parameters_service_client_set(uint16_t scan_interval, uint16_t scan_window){
448     scan_parameters_service_scan_interval = scan_interval;
449     scan_parameters_service_scan_window = scan_window;
450 
451     btstack_linked_list_iterator_t it;
452     btstack_linked_list_iterator_init(&it, &clients);
453     while (btstack_linked_list_iterator_has_next(&it)){
454         scan_parameters_service_client_t * client = (scan_parameters_service_client_t*) btstack_linked_list_iterator_next(&it);
455         client->scan_interval_window_value_update = true;
456         scan_parameters_client_request_send_gatt_query(client);
457     }
458 }
459 
460 uint8_t scan_parameters_service_client_enable_notifications(uint16_t scan_parameters_service_cid){
461     scan_parameters_service_client_t * client = scan_parameters_service_get_client_for_cid(scan_parameters_service_cid);
462 
463     if (client == NULL){
464         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
465     }
466 
467     if (client->state != SCAN_PARAMETERS_SERVICE_CLIENT_STATE_CONNECTED) {
468         return ERROR_CODE_COMMAND_DISALLOWED;
469     }
470 
471     client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_CONFIGURE_NOTIFICATIONS;
472     return scan_parameters_client_request_send_gatt_query(client);
473 }
474 
475 uint8_t scan_parameters_service_client_connect(hci_con_handle_t con_handle, btstack_packet_handler_t packet_handler, uint16_t * scan_parameters_service_cid){
476     btstack_assert(packet_handler != NULL);
477 
478     scan_parameters_service_client_t * client = scan_parameters_service_get_client_for_con_handle(con_handle);
479     if (client != NULL){
480         return ERROR_CODE_COMMAND_DISALLOWED;
481     }
482 
483     uint16_t cid = scan_parameters_service_get_next_cid();
484     if (scan_parameters_service_cid != NULL) {
485         *scan_parameters_service_cid = cid;
486     }
487 
488     client = scan_parameters_service_create_client(con_handle, cid);
489     if (client == NULL) {
490         return BTSTACK_MEMORY_ALLOC_FAILED;
491     }
492 
493     client->client_handler = packet_handler;
494     client->state = SCAN_PARAMETERS_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE;
495     return scan_parameters_client_request_send_gatt_query(client);
496 }
497 
498 uint8_t scan_parameters_service_client_disconnect(uint16_t scan_parameters_service_cid){
499     scan_parameters_service_client_t * client = scan_parameters_service_get_client_for_cid(scan_parameters_service_cid);
500     if (client == NULL){
501         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
502     }
503     // finalize connections
504     scan_parameters_service_finalize_client(client);
505     return ERROR_CODE_SUCCESS;
506 }
507 
508 void scan_parameters_service_client_init(void){
509     hci_event_callback_registration.callback = &handle_hci_event;
510     hci_add_event_handler(&hci_event_callback_registration);
511     scan_parameters_service_handle_can_send_now.callback = &scan_parameters_service_send_next_query;
512 }
513 
514 void scan_parameters_service_client_deinit(void){
515 }
516 
517