xref: /btstack/src/le-audio/gatt-service/broadcast_audio_scan_service_server.c (revision 54461c8047b3c5f9654296103bcf995fc81d2a8c)
1 /*
2  * Copyright (C) 2022 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__ "broadcast_audio_scan_service_server.c"
39 
40 #include <stdio.h>
41 
42 #include "ble/att_db.h"
43 #include "ble/att_server.h"
44 #include "bluetooth_gatt.h"
45 #include "btstack_debug.h"
46 #include "btstack_defines.h"
47 #include "btstack_event.h"
48 #include "btstack_util.h"
49 
50 #include "le-audio/gatt-service/broadcast_audio_scan_service_server.h"
51 #include "le-audio/le_audio_util.h"
52 
53 #ifdef ENABLE_TESTING_SUPPORT
54 #include <stdio.h>
55 #endif
56 
57 #define BASS_MAX_NOTIFY_BUFFER_SIZE                             200
58 #define BASS_INVALID_SOURCE_INDEX                               0xFF
59 
60 static att_service_handler_t    broadcast_audio_scan_service;
61 static btstack_packet_handler_t bass_event_callback;
62 
63 // characteristic: AUDIO_SCAN_CONTROL_POINT
64 static uint16_t bass_audio_scan_control_point_handle;
65 
66 static uint8_t  bass_logic_time = 0;
67 
68 static bass_server_source_t * bass_sources;
69 static uint8_t  bass_sources_num = 0;
70 static bass_remote_client_t * bass_clients;
71 static uint8_t  bass_clients_num = 0;
72 static btstack_context_callback_registration_t  scheduled_tasks_callback;
73 
74 static uint8_t bass_get_next_update_counter(void){
75     uint8_t next_update_counter;
76     if (bass_logic_time == 0xff) {
77         next_update_counter = 0;
78     } else {
79         next_update_counter = bass_logic_time + 1;
80     }
81     bass_logic_time = next_update_counter;
82     return next_update_counter;
83 }
84 
85 // returns positive number if counter a > b
86 static int8_t bass_counter_delta(uint8_t counter_a, uint8_t counter_b){
87     return (int8_t)(counter_a - counter_b);
88 }
89 
90 static uint8_t bass_find_empty_or_last_used_source_index(void){
91     bass_server_source_t * last_used_source = NULL;
92     uint8_t last_used_source_index = BASS_INVALID_SOURCE_INDEX;
93 
94     uint8_t i;
95     for (i = 0; i < bass_sources_num; i++){
96         if (!bass_sources[i].in_use){
97             return i;
98         }
99         if (last_used_source == NULL){
100             last_used_source = &bass_sources[i];
101             last_used_source_index = i;
102             continue;
103         }
104         if (bass_counter_delta(bass_sources[i].update_counter, last_used_source->update_counter) < 0 ){
105             last_used_source = &bass_sources[i];
106             last_used_source_index = i;
107         }
108     }
109     return last_used_source_index;
110 }
111 
112 static bass_server_source_t *  bass_find_empty_or_last_used_source(void){
113     uint8_t last_used_source_index = bass_find_empty_or_last_used_source_index();
114     if (last_used_source_index == BASS_INVALID_SOURCE_INDEX){
115         return NULL;
116     }
117     return &bass_sources[last_used_source_index];
118 }
119 
120 static bass_server_source_t * bass_find_receive_state_for_value_handle(uint16_t attribute_handle){
121     uint16_t i;
122     for (i = 0; i < bass_sources_num; i++){
123         if (attribute_handle == bass_sources[i].bass_receive_state_handle){
124             return &bass_sources[i];
125         }
126     }
127     return NULL;
128 }
129 
130 static bass_server_source_t * bass_find_receive_state_for_client_configuration_handle(uint16_t attribute_handle){
131     if (attribute_handle == 0){
132         return NULL;
133     }
134     uint8_t i;
135     for (i = 0; i < bass_sources_num; i++){
136         if (bass_sources[i].bass_receive_state_client_configuration_handle == attribute_handle){
137             return &bass_sources[i];
138         }
139     }
140     return NULL;
141 }
142 
143 static bass_server_source_t * bass_find_source_for_source_id(uint8_t source_id){
144     if (source_id < bass_sources_num){
145         return &bass_sources[source_id];
146     }
147     return NULL;
148 }
149 
150 static bass_remote_client_t * bass_find_client_for_con_handle(hci_con_handle_t con_handle){
151     uint16_t i;
152     for (i = 0; i < bass_clients_num; i++){
153         if (bass_clients[i].con_handle == con_handle) {
154             return &bass_clients[i];
155         }
156     }
157     return NULL;
158 }
159 
160 static void bass_register_con_handle(hci_con_handle_t con_handle, uint16_t client_configuration){
161     bass_remote_client_t * client = bass_find_client_for_con_handle(con_handle);
162     if (client == NULL){
163         client = bass_find_client_for_con_handle(HCI_CON_HANDLE_INVALID);
164         if (client == NULL){
165             return;
166         }
167 
168     }
169     client->con_handle = (client_configuration == 0) ? HCI_CON_HANDLE_INVALID : con_handle;
170 }
171 
172 static void bass_emit_remote_scan_stoped(hci_con_handle_t con_handle){
173     btstack_assert(bass_event_callback != NULL);
174 
175     uint8_t event[5];
176     uint8_t pos = 0;
177     event[pos++] = HCI_EVENT_GATTSERVICE_META;
178     event[pos++] = sizeof(event) - 2;
179     event[pos++] = GATTSERVICE_SUBEVENT_BASS_REMOTE_SCAN_STOPPED;
180     little_endian_store_16(event, pos, con_handle);
181     pos += 2;
182     (*bass_event_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
183 }
184 
185 static void bass_emit_remote_scan_started(hci_con_handle_t con_handle){
186     btstack_assert(bass_event_callback != NULL);
187 
188     uint8_t event[5];
189     uint8_t pos = 0;
190     event[pos++] = HCI_EVENT_GATTSERVICE_META;
191     event[pos++] = sizeof(event) - 2;
192     event[pos++] = GATTSERVICE_SUBEVENT_BASS_REMOTE_SCAN_STARTED;
193     little_endian_store_16(event, pos, con_handle);
194     pos += 2;
195     (*bass_event_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
196 }
197 
198 
199 static void bass_emit_source_state_changed(uint8_t subevent_id, hci_con_handle_t con_handle, uint8_t source_id, le_audio_pa_sync_t pa_sync){
200     btstack_assert(bass_event_callback != NULL);
201 
202     uint8_t event[7];
203     uint8_t pos = 0;
204     event[pos++] = HCI_EVENT_GATTSERVICE_META;
205     event[pos++] = sizeof(event) - 2;
206     event[pos++] = subevent_id;
207     little_endian_store_16(event, pos, con_handle);
208     pos += 2;
209     event[pos++] = source_id;
210     event[pos++] = (uint8_t)pa_sync;
211     (*bass_event_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
212 }
213 
214 static void bass_emit_source_added(hci_con_handle_t con_handle, bass_server_source_t * source){
215     bass_emit_source_state_changed(GATTSERVICE_SUBEVENT_BASS_SOURCE_ADDED, con_handle, source->source_id, source->data.pa_sync);
216 }
217 
218 static void bass_emit_source_modified(hci_con_handle_t con_handle, bass_server_source_t * source){
219     bass_emit_source_state_changed(GATTSERVICE_SUBEVENT_BASS_SOURCE_MODIFIED, con_handle, source->source_id, source->data.pa_sync);
220 }
221 
222 static void bass_emit_source_deleted(hci_con_handle_t con_handle, bass_server_source_t * source){
223     bass_emit_source_state_changed(GATTSERVICE_SUBEVENT_BASS_SOURCE_DELETED, con_handle, source->source_id, LE_AUDIO_PA_SYNC_DO_NOT_SYNCHRONIZE_TO_PA);
224 }
225 
226 static void bass_emit_broadcast_code(hci_con_handle_t con_handle, uint8_t source_id, const uint8_t * broadcast_code){
227     btstack_assert(bass_event_callback != NULL);
228 
229     uint8_t event[22];
230     uint8_t pos = 0;
231     event[pos++] = HCI_EVENT_GATTSERVICE_META;
232     event[pos++] = sizeof(event) - 2;
233     event[pos++] = GATTSERVICE_SUBEVENT_BASS_BROADCAST_CODE;
234     little_endian_store_16(event, pos, con_handle);
235     pos += 2;
236     event[pos++] = source_id;
237     reverse_128(broadcast_code, &event[pos]);
238     pos += 16;
239     (*bass_event_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
240 }
241 
242 // offset gives position into fully serialized bass record
243 static uint16_t bass_server_copy_source_to_buffer(bass_server_source_t * source, uint16_t buffer_offset, uint8_t * buffer, uint16_t buffer_size){
244     uint8_t  field_data[16];
245     uint16_t source_offset = 0;
246     uint16_t stored_bytes = 0;
247     memset(buffer, 0, buffer_size);
248 
249     if (!source->in_use){
250         return 0;
251     }
252     field_data[0] = source->source_id;
253     stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 1, source_offset, buffer, buffer_size,
254                                                         buffer_offset);
255     source_offset++;
256 
257     stored_bytes += bass_util_copy_source_common_data_to_buffer(&source->data, &source_offset, buffer_offset, buffer, buffer_size);
258 
259     field_data[0] = (uint8_t)source->data.pa_sync_state;
260     stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 1, source_offset, buffer, buffer_size,
261                                                         buffer_offset);
262     source_offset++;
263 
264     field_data[0] = (uint8_t)source->big_encryption;
265     stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 1, source_offset, buffer, buffer_size,
266                                                         buffer_offset);
267     source_offset++;
268 
269     if (source->big_encryption == LE_AUDIO_BIG_ENCRYPTION_BAD_CODE){
270         reverse_128(source->bad_code, &field_data[0]);
271         stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 16, source_offset, buffer, buffer_size,
272                                                             buffer_offset);
273         source_offset += 16;
274     }
275 
276     stored_bytes += bass_util_store_source_subgroups_into_buffer(&source->data, true, &source_offset, buffer_offset,
277                                                                  buffer,
278                                                                  buffer_size);
279     return stored_bytes;
280 }
281 
282 static uint16_t broadcast_audio_scan_service_read_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
283     UNUSED(con_handle);
284 
285     bass_server_source_t * source;
286     source = bass_find_receive_state_for_value_handle(attribute_handle);
287     if (source){
288         return bass_server_copy_source_to_buffer(source, offset, buffer, buffer_size);
289     }
290 
291     source = bass_find_receive_state_for_client_configuration_handle(attribute_handle);
292     if (source){
293         return att_read_callback_handle_little_endian_16(source->bass_receive_state_client_configuration, offset, buffer, buffer_size);
294     }
295 
296     return 0;
297 }
298 
299 static bool bass_source_remote_modify_source_buffer_valid(uint8_t *buffer, uint16_t buffer_size){
300     if (buffer_size < 10){
301         log_info("Modify Source opcode, buffer too small");
302         return false;
303     }
304 
305     uint8_t pos = 1; // source_id
306     return bass_util_pa_sync_state_and_subgroups_in_valid_range(buffer+pos, buffer_size-pos);
307 }
308 
309 static void bass_server_add_source_from_buffer(uint8_t *buffer, uint16_t buffer_size, bass_server_source_t * source){
310     UNUSED(buffer_size);
311 
312     source->update_counter = bass_get_next_update_counter();
313     source->in_use = true;
314 
315     bass_util_get_source_from_buffer(buffer, buffer_size, &source->data, false);
316 }
317 
318 static bool bass_pa_synchronized(bass_server_source_t * source){
319     return source->data.pa_sync_state == LE_AUDIO_PA_SYNC_STATE_SYNCHRONIZED_TO_PA;
320 }
321 
322 
323 static bool bass_bis_synchronized(bass_server_source_t * source){
324     uint8_t i;
325     for (i = 0; i < source->data.subgroups_num; i++){
326         if ((source->data.subgroups[i].bis_sync_state > 0) && (source->data.subgroups[i].bis_sync_state < 0xFFFFFFFF)){
327             return true;
328         }
329     }
330     return false;
331 }
332 
333 
334 static void bass_reset_source(bass_server_source_t * source){
335     source->in_use = false;
336     source->data.address_type = BD_ADDR_TYPE_LE_PUBLIC;
337     memset(source->data.address, 0, sizeof(source->data.address));
338     source->data.adv_sid = 0;
339     source->data.broadcast_id = 0;
340     source->data.pa_sync = LE_AUDIO_PA_SYNC_DO_NOT_SYNCHRONIZE_TO_PA;
341     source->data.pa_sync_state = LE_AUDIO_PA_SYNC_STATE_NOT_SYNCHRONIZED_TO_PA;
342     source->big_encryption = LE_AUDIO_BIG_ENCRYPTION_NOT_ENCRYPTED;
343     memset(source->bad_code, 0, sizeof(source->bad_code));
344     source->data.pa_interval = 0;
345     source->data.subgroups_num = 0;
346     memset(source->data.subgroups, 0, sizeof(source->data.subgroups));
347 }
348 
349 static void bass_reset_client_long_write_buffer(bass_remote_client_t * client){
350     memset(client->long_write_buffer, 0, sizeof(client->long_write_buffer));
351     client->long_write_value_size = 0;
352 }
353 
354 static int broadcast_audio_scan_service_write_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
355     // printf("broadcast_audio_scan_service_write_callback con_handle 0x%02x, attr_handle 0x%02x \n", con_handle, attribute_handle);
356     if (attribute_handle != 0 && attribute_handle != bass_audio_scan_control_point_handle){
357 
358         bass_server_source_t * source = bass_find_receive_state_for_client_configuration_handle(attribute_handle);
359         if (source){
360             source->bass_receive_state_client_configuration = little_endian_read_16(buffer, 0);
361             bass_register_con_handle(con_handle, source->bass_receive_state_client_configuration);
362         }
363         return 0;
364     }
365 
366 
367     bass_remote_client_t * client = bass_find_client_for_con_handle(con_handle);
368     if (client == NULL){
369         return ATT_ERROR_WRITE_REQUEST_REJECTED;
370     }
371 
372     uint16_t total_value_len = buffer_size + offset;
373 
374     switch (transaction_mode){
375         case ATT_TRANSACTION_MODE_NONE:
376             if (buffer_size > sizeof(client->long_write_buffer)){
377                 bass_reset_client_long_write_buffer(client);
378                 return ATT_ERROR_WRITE_REQUEST_REJECTED;
379             }
380             memcpy(&client->long_write_buffer[0], buffer, buffer_size);
381             client->long_write_value_size = total_value_len;
382             break;
383 
384         case ATT_TRANSACTION_MODE_ACTIVE:
385             if (total_value_len > sizeof(client->long_write_buffer)){
386                 bass_reset_client_long_write_buffer(client);
387                 return ATT_ERROR_WRITE_REQUEST_REJECTED;
388             }
389             // allow overlapped and/or mixed order chunks
390             client->long_write_attribute_handle = attribute_handle;
391 
392             memcpy(&client->long_write_buffer[offset], buffer, buffer_size);
393             if (total_value_len > client->long_write_value_size){
394                 client->long_write_value_size = total_value_len;
395             }
396             return 0;
397 
398         case ATT_TRANSACTION_MODE_VALIDATE:
399             return 0;
400 
401         case ATT_TRANSACTION_MODE_EXECUTE:
402             attribute_handle = client->long_write_attribute_handle;
403             break;
404 
405         default:
406             return 0;
407     }
408 
409     if (attribute_handle == bass_audio_scan_control_point_handle){
410         if (client->long_write_value_size < 2){
411             return ATT_ERROR_WRITE_REQUEST_REJECTED;
412         }
413 
414         bass_opcode_t opcode = (bass_opcode_t)client->long_write_buffer[0];
415         uint8_t  *remote_data = &client->long_write_buffer[1];
416         uint16_t remote_data_size = client->long_write_value_size - 1;
417 
418         bass_server_source_t * source;
419         uint8_t broadcast_code[16];
420         switch (opcode){
421             case BASS_OPCODE_REMOTE_SCAN_STOPPED:
422                 if (remote_data_size != 1){
423                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
424                 }
425                 bass_emit_remote_scan_stoped(con_handle);
426                 break;
427 
428             case BASS_OPCODE_REMOTE_SCAN_STARTED:
429                 if (remote_data_size != 1){
430                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
431                 }
432                 bass_emit_remote_scan_started(con_handle);
433                 break;
434 
435             case BASS_OPCODE_ADD_SOURCE:
436                 if (!bass_util_add_source_buffer_in_valid_range(remote_data, remote_data_size)){
437                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
438                 }
439                 source = bass_find_empty_or_last_used_source();
440                 btstack_assert(source != NULL);
441                 log_info("add source %d", source->source_id);
442                 bass_server_add_source_from_buffer(remote_data, remote_data_size, source);
443                 bass_emit_source_added(con_handle, source);
444                 // server needs to trigger notification
445                 break;
446 
447             case BASS_OPCODE_MODIFY_SOURCE:
448                 if (!bass_source_remote_modify_source_buffer_valid(remote_data, remote_data_size)){
449                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
450                 }
451 
452                 source = bass_find_source_for_source_id(remote_data[0]);
453                 if (source == NULL){
454                     return BASS_ERROR_CODE_INVALID_SOURCE_ID;
455                 }
456                 bass_util_get_pa_info_and_subgroups_from_buffer(remote_data + 1, remote_data_size - 1, &source->data,false);
457                 bass_emit_source_modified(con_handle, source);
458                 // server needs to trigger notification
459                 break;
460 
461             case BASS_OPCODE_SET_BROADCAST_CODE:
462                 if (remote_data_size != 17){
463                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
464                 }
465 
466                 source = bass_find_source_for_source_id(remote_data[0]);
467                 if (source == NULL){
468                     return BASS_ERROR_CODE_INVALID_SOURCE_ID;
469                 }
470                 reverse_128(&remote_data[1], broadcast_code);
471                 bass_emit_broadcast_code(con_handle, source->source_id, broadcast_code);
472                 break;
473 
474             case BASS_OPCODE_REMOVE_SOURCE:
475                 if (remote_data_size != 1){
476                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
477                 }
478                 source = bass_find_source_for_source_id(remote_data[0]);
479                 if (source == NULL){
480                     return BASS_ERROR_CODE_INVALID_SOURCE_ID;
481                 }
482 
483                 if (bass_pa_synchronized(source)){
484                     log_info("remove source %d rejected, PA synchronised", source->source_id);
485                     return 0;
486                 }
487 
488                 if (bass_bis_synchronized(source)){
489                     log_info("remove source %d rejected, BIS synchronised", source->source_id);
490                     return 0;
491                 }
492 
493                 bass_reset_source(source);
494                 broadcast_audio_scan_service_server_set_pa_sync_state(source->source_id, LE_AUDIO_PA_SYNC_STATE_NOT_SYNCHRONIZED_TO_PA);
495                 bass_emit_source_deleted(con_handle, source);
496                 break;
497 
498             default:
499                 bass_reset_client_long_write_buffer(client);
500                 return BASS_ERROR_CODE_OPCODE_NOT_SUPPORTED;
501         }
502         bass_reset_client_long_write_buffer(client);
503     }
504     return 0;
505 }
506 
507 static void broadcast_audio_scan_service_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
508     UNUSED(channel);
509     UNUSED(packet);
510     UNUSED(size);
511 
512     if (packet_type != HCI_EVENT_PACKET){
513         return;
514     }
515 
516     hci_con_handle_t con_handle;
517     bass_remote_client_t * client;
518 
519     switch (hci_event_packet_get_type(packet)) {
520         case HCI_EVENT_DISCONNECTION_COMPLETE:
521             con_handle = hci_event_disconnection_complete_get_connection_handle(packet);
522 
523             client = bass_find_client_for_con_handle(con_handle);
524             if (client == NULL){
525                 break;
526             }
527 
528             memset(client, 0, sizeof(bass_remote_client_t));
529             client->con_handle = HCI_CON_HANDLE_INVALID;
530             break;
531         default:
532             break;
533     }
534 }
535 
536 void broadcast_audio_scan_service_server_init(const uint8_t sources_num, bass_server_source_t * sources, const uint8_t clients_num, bass_remote_client_t * clients){
537     // get service handle range
538     btstack_assert(sources_num != 0);
539     btstack_assert(clients_num != 0);
540 
541     uint16_t start_handle = 0;
542     uint16_t end_handle   = 0xffff;
543     bool service_found = gatt_server_get_handle_range_for_service_with_uuid16(ORG_BLUETOOTH_SERVICE_BROADCAST_AUDIO_SCAN_SERVICE, &start_handle, &end_handle);
544     btstack_assert(service_found);
545 
546     UNUSED(service_found);
547 
548     bass_audio_scan_control_point_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BROADCAST_AUDIO_SCAN_CONTROL_POINT);
549     bass_sources_num = 0;
550     bass_logic_time = 0;
551     bass_sources = sources;
552 
553 #ifdef ENABLE_TESTING_SUPPORT
554     printf("BASS 0x%02x - 0x%02x \n", start_handle, end_handle);
555 #endif
556     uint16_t start_chr_handle = start_handle;
557     while ( (start_chr_handle < end_handle) && (bass_sources_num < sources_num )) {
558         uint16_t chr_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_chr_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BROADCAST_RECEIVE_STATE);
559         uint16_t chr_client_configuration_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(start_chr_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BROADCAST_RECEIVE_STATE);
560 
561         if (chr_value_handle == 0){
562             break;
563         }
564         bass_server_source_t * source = &bass_sources[bass_sources_num];
565         bass_reset_source(source);
566 
567         source->source_id = bass_sources_num;
568         source->update_counter = bass_get_next_update_counter();
569         source->bass_receive_state_client_configuration = 0;
570 
571         source->bass_receive_state_handle = chr_value_handle;
572         source->bass_receive_state_client_configuration_handle = chr_client_configuration_handle;
573 
574 #ifdef ENABLE_TESTING_SUPPORT
575     printf("    bass_receive_state_%d                 0x%02x \n", bass_sources_num, source->bass_receive_state_handle);
576     printf("    bass_receive_state_%d CCC             0x%02x \n", bass_sources_num, source->bass_receive_state_client_configuration_handle);
577 #endif
578 
579         start_chr_handle = chr_client_configuration_handle + 1;
580         bass_sources_num++;
581     }
582 
583     bass_clients_num = clients_num;
584     bass_clients = clients;
585     memset(bass_clients, 0, sizeof(bass_remote_client_t) * bass_clients_num);
586     uint8_t i;
587     for (i = 0; i < bass_clients_num; i++){
588         bass_clients[i].con_handle = HCI_CON_HANDLE_INVALID;
589     }
590 
591     log_info("Found BASS service 0x%02x-0x%02x (num sources %d)", start_handle, end_handle, bass_sources_num);
592 
593     // register service with ATT Server
594     broadcast_audio_scan_service.start_handle   = start_handle;
595     broadcast_audio_scan_service.end_handle     = end_handle;
596     broadcast_audio_scan_service.read_callback  = &broadcast_audio_scan_service_read_callback;
597     broadcast_audio_scan_service.write_callback = &broadcast_audio_scan_service_write_callback;
598     broadcast_audio_scan_service.packet_handler = broadcast_audio_scan_service_packet_handler;
599     att_server_register_service_handler(&broadcast_audio_scan_service);
600 }
601 
602 void broadcast_audio_scan_service_server_register_packet_handler(btstack_packet_handler_t callback){
603     btstack_assert(callback != NULL);
604     bass_event_callback = callback;
605 }
606 
607 static void bass_service_can_send_now(void * context){
608     bass_remote_client_t * client = (bass_remote_client_t *) context;
609     btstack_assert(client != NULL);
610 
611     uint8_t source_index;
612     for (source_index = 0; source_index < bass_sources_num; source_index++){
613         uint8_t task = (1 << source_index);
614         if ((client->sources_to_notify & task) != 0){
615             client->sources_to_notify &= ~task;
616             uint8_t  buffer[BASS_MAX_NOTIFY_BUFFER_SIZE];
617             uint16_t bytes_copied = bass_server_copy_source_to_buffer(&bass_sources[source_index], 0, buffer, sizeof(buffer));
618             att_server_notify(client->con_handle, bass_sources[source_index].bass_receive_state_handle, &buffer[0], bytes_copied);
619             return;
620         }
621     }
622 
623     uint8_t i;
624     for (i = 0; i < bass_clients_num; i++){
625         client = &bass_clients[i];
626 
627         if (client->sources_to_notify != 0){
628             scheduled_tasks_callback.callback = &bass_service_can_send_now;
629             scheduled_tasks_callback.context  = (void*) client;
630             att_server_register_can_send_now_callback(&scheduled_tasks_callback, client->con_handle);
631             return;
632         }
633     }
634 }
635 
636 static void bass_set_callback(uint8_t source_index){
637     // there is only one type of task: notify on source state change
638     // as task we register which source is changed, and the change will be propagated to all clients
639     uint8_t i;
640     uint8_t task = (1 << source_index);
641 
642     uint8_t scheduled_tasks = 0;
643 
644     for (i = 0; i < bass_clients_num; i++){
645         bass_remote_client_t * client = &bass_clients[i];
646 
647         if (client->con_handle == HCI_CON_HANDLE_INVALID){
648             client->sources_to_notify &= ~task;
649             return;
650         }
651 
652         scheduled_tasks |= client->sources_to_notify;
653         client->sources_to_notify |= task;
654 
655         if (scheduled_tasks == 0){
656             scheduled_tasks_callback.callback = &bass_service_can_send_now;
657             scheduled_tasks_callback.context  = (void*) client;
658             att_server_register_can_send_now_callback(&scheduled_tasks_callback, client->con_handle);
659         }
660     }
661 }
662 
663 void broadcast_audio_scan_service_server_set_pa_sync_state(uint8_t source_index, le_audio_pa_sync_state_t sync_state){
664     btstack_assert(source_index < bass_sources_num);
665 
666     bass_server_source_t * source = &bass_sources[source_index];
667     source->data.pa_sync_state = sync_state;
668 
669     if (source->bass_receive_state_client_configuration != 0){
670         bass_set_callback(source_index);
671     }
672 }
673 
674 void broadcast_audio_scan_service_server_add_source(bass_source_data_t source_data, uint8_t * source_index){
675     *source_index = bass_find_empty_or_last_used_source_index();
676     if (*source_index == BASS_INVALID_SOURCE_INDEX){
677         return;
678     }
679     bass_server_source_t * last_used_source = &bass_sources[*source_index];
680     last_used_source->update_counter = bass_get_next_update_counter();
681     last_used_source->in_use = true;
682     last_used_source->source_id = *source_index;
683     memcpy(&last_used_source->data, &source_data, sizeof(bass_source_data_t));
684 }
685 
686 void broadcast_audio_scan_service_server_deinit(void){
687 }
688