xref: /btstack/src/le-audio/gatt-service/broadcast_audio_scan_service_server.c (revision e3ba22907f903f11cd12321c31e7936b8dd1157e)
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_source_data_header_virtual_memcpy(&source->data, &source_offset, buffer_offset, buffer,
258                                                                 buffer_size);
259 
260     field_data[0] = (uint8_t)source->data.pa_sync_state;
261     stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 1, source_offset, buffer, buffer_size,
262                                                         buffer_offset);
263     source_offset++;
264 
265     field_data[0] = (uint8_t)source->big_encryption;
266     stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 1, source_offset, buffer, buffer_size,
267                                                         buffer_offset);
268     source_offset++;
269 
270     if (source->big_encryption == LE_AUDIO_BIG_ENCRYPTION_BAD_CODE){
271         reverse_128(source->bad_code, &field_data[0]);
272         stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 16, source_offset, buffer, buffer_size,
273                                                             buffer_offset);
274         source_offset += 16;
275     }
276 
277     stored_bytes += bass_util_source_data_subgroups_virtual_memcpy(&source->data, true, &source_offset, buffer_offset,
278                                                                    buffer,
279                                                                    buffer_size);
280     return stored_bytes;
281 }
282 
283 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){
284     UNUSED(con_handle);
285 
286     bass_server_source_t * source;
287     source = bass_find_receive_state_for_value_handle(attribute_handle);
288     if (source){
289         return bass_server_copy_source_to_buffer(source, offset, buffer, buffer_size);
290     }
291 
292     source = bass_find_receive_state_for_client_configuration_handle(attribute_handle);
293     if (source){
294         return att_read_callback_handle_little_endian_16(source->bass_receive_state_client_configuration, offset, buffer, buffer_size);
295     }
296 
297     return 0;
298 }
299 
300 static bool bass_source_remote_modify_source_buffer_valid(uint8_t *buffer, uint16_t buffer_size){
301     if (buffer_size < 10){
302         log_info("Modify Source opcode, buffer too small");
303         return false;
304     }
305 
306     uint8_t pos = 1; // source_id
307     return bass_util_pa_sync_state_and_subgroups_in_valid_range(buffer+pos, buffer_size-pos);
308 }
309 
310 static void bass_server_add_source_from_buffer(uint8_t *buffer, uint16_t buffer_size, bass_server_source_t * source){
311     UNUSED(buffer_size);
312 
313     source->update_counter = bass_get_next_update_counter();
314     source->in_use = true;
315 
316     bass_util_source_data_parse(buffer, buffer_size, &source->data, false);
317 }
318 
319 static bool bass_pa_synchronized(bass_server_source_t * source){
320     return source->data.pa_sync_state == LE_AUDIO_PA_SYNC_STATE_SYNCHRONIZED_TO_PA;
321 }
322 
323 
324 static bool bass_bis_synchronized(bass_server_source_t * source){
325     uint8_t i;
326     for (i = 0; i < source->data.subgroups_num; i++){
327         if ((source->data.subgroups[i].bis_sync_state > 0) && (source->data.subgroups[i].bis_sync_state < 0xFFFFFFFF)){
328             return true;
329         }
330     }
331     return false;
332 }
333 
334 
335 static void bass_reset_source(bass_server_source_t * source){
336     source->in_use = false;
337     source->data.address_type = BD_ADDR_TYPE_LE_PUBLIC;
338     memset(source->data.address, 0, sizeof(source->data.address));
339     source->data.adv_sid = 0;
340     source->data.broadcast_id = 0;
341     source->data.pa_sync = LE_AUDIO_PA_SYNC_DO_NOT_SYNCHRONIZE_TO_PA;
342     source->data.pa_sync_state = LE_AUDIO_PA_SYNC_STATE_NOT_SYNCHRONIZED_TO_PA;
343     source->big_encryption = LE_AUDIO_BIG_ENCRYPTION_NOT_ENCRYPTED;
344     memset(source->bad_code, 0, sizeof(source->bad_code));
345     source->data.pa_interval = 0;
346     source->data.subgroups_num = 0;
347     memset(source->data.subgroups, 0, sizeof(source->data.subgroups));
348 }
349 
350 static void bass_reset_client_long_write_buffer(bass_remote_client_t * client){
351     memset(client->long_write_buffer, 0, sizeof(client->long_write_buffer));
352     client->long_write_value_size = 0;
353 }
354 
355 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){
356     // printf("broadcast_audio_scan_service_write_callback con_handle 0x%02x, attr_handle 0x%02x \n", con_handle, attribute_handle);
357     if (attribute_handle != 0 && attribute_handle != bass_audio_scan_control_point_handle){
358 
359         bass_server_source_t * source = bass_find_receive_state_for_client_configuration_handle(attribute_handle);
360         if (source){
361             source->bass_receive_state_client_configuration = little_endian_read_16(buffer, 0);
362             bass_register_con_handle(con_handle, source->bass_receive_state_client_configuration);
363         }
364         return 0;
365     }
366 
367 
368     bass_remote_client_t * client = bass_find_client_for_con_handle(con_handle);
369     if (client == NULL){
370         return ATT_ERROR_WRITE_REQUEST_REJECTED;
371     }
372 
373     uint16_t total_value_len = buffer_size + offset;
374 
375     switch (transaction_mode){
376         case ATT_TRANSACTION_MODE_NONE:
377             if (buffer_size > sizeof(client->long_write_buffer)){
378                 bass_reset_client_long_write_buffer(client);
379                 return ATT_ERROR_WRITE_REQUEST_REJECTED;
380             }
381             memcpy(&client->long_write_buffer[0], buffer, buffer_size);
382             client->long_write_value_size = total_value_len;
383             break;
384 
385         case ATT_TRANSACTION_MODE_ACTIVE:
386             if (total_value_len > sizeof(client->long_write_buffer)){
387                 bass_reset_client_long_write_buffer(client);
388                 return ATT_ERROR_WRITE_REQUEST_REJECTED;
389             }
390             // allow overlapped and/or mixed order chunks
391             client->long_write_attribute_handle = attribute_handle;
392 
393             memcpy(&client->long_write_buffer[offset], buffer, buffer_size);
394             if (total_value_len > client->long_write_value_size){
395                 client->long_write_value_size = total_value_len;
396             }
397             return 0;
398 
399         case ATT_TRANSACTION_MODE_VALIDATE:
400             return 0;
401 
402         case ATT_TRANSACTION_MODE_EXECUTE:
403             attribute_handle = client->long_write_attribute_handle;
404             break;
405 
406         default:
407             return 0;
408     }
409 
410     if (attribute_handle == bass_audio_scan_control_point_handle){
411         if (client->long_write_value_size < 2){
412             return ATT_ERROR_WRITE_REQUEST_REJECTED;
413         }
414 
415         bass_opcode_t opcode = (bass_opcode_t)client->long_write_buffer[0];
416         uint8_t  *remote_data = &client->long_write_buffer[1];
417         uint16_t remote_data_size = client->long_write_value_size - 1;
418 
419         bass_server_source_t * source;
420         uint8_t broadcast_code[16];
421         switch (opcode){
422             case BASS_OPCODE_REMOTE_SCAN_STOPPED:
423                 if (remote_data_size != 1){
424                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
425                 }
426                 bass_emit_remote_scan_stoped(con_handle);
427                 break;
428 
429             case BASS_OPCODE_REMOTE_SCAN_STARTED:
430                 if (remote_data_size != 1){
431                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
432                 }
433                 bass_emit_remote_scan_started(con_handle);
434                 break;
435 
436             case BASS_OPCODE_ADD_SOURCE:
437                 if (!bass_util_source_buffer_in_valid_range(remote_data, remote_data_size)){
438                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
439                 }
440                 source = bass_find_empty_or_last_used_source();
441                 btstack_assert(source != NULL);
442                 log_info("add source %d", source->source_id);
443                 bass_server_add_source_from_buffer(remote_data, remote_data_size, source);
444                 bass_emit_source_added(con_handle, source);
445                 // server needs to trigger notification
446                 break;
447 
448             case BASS_OPCODE_MODIFY_SOURCE:
449                 if (!bass_source_remote_modify_source_buffer_valid(remote_data, remote_data_size)){
450                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
451                 }
452 
453                 source = bass_find_source_for_source_id(remote_data[0]);
454                 if (source == NULL){
455                     return BASS_ERROR_CODE_INVALID_SOURCE_ID;
456                 }
457                 bass_util_pa_info_and_subgroups_parse(remote_data + 1, remote_data_size - 1, &source->data, false);
458                 bass_emit_source_modified(con_handle, source);
459                 // server needs to trigger notification
460                 break;
461 
462             case BASS_OPCODE_SET_BROADCAST_CODE:
463                 if (remote_data_size != 17){
464                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
465                 }
466 
467                 source = bass_find_source_for_source_id(remote_data[0]);
468                 if (source == NULL){
469                     return BASS_ERROR_CODE_INVALID_SOURCE_ID;
470                 }
471                 reverse_128(&remote_data[1], broadcast_code);
472                 bass_emit_broadcast_code(con_handle, source->source_id, broadcast_code);
473                 break;
474 
475             case BASS_OPCODE_REMOVE_SOURCE:
476                 if (remote_data_size != 1){
477                     return ATT_ERROR_WRITE_REQUEST_REJECTED;
478                 }
479                 source = bass_find_source_for_source_id(remote_data[0]);
480                 if (source == NULL){
481                     return BASS_ERROR_CODE_INVALID_SOURCE_ID;
482                 }
483 
484                 if (bass_pa_synchronized(source)){
485                     log_info("remove source %d rejected, PA synchronised", source->source_id);
486                     return 0;
487                 }
488 
489                 if (bass_bis_synchronized(source)){
490                     log_info("remove source %d rejected, BIS synchronised", source->source_id);
491                     return 0;
492                 }
493 
494                 bass_reset_source(source);
495                 broadcast_audio_scan_service_server_set_pa_sync_state(source->source_id, LE_AUDIO_PA_SYNC_STATE_NOT_SYNCHRONIZED_TO_PA);
496                 bass_emit_source_deleted(con_handle, source);
497                 break;
498 
499             default:
500                 bass_reset_client_long_write_buffer(client);
501                 return BASS_ERROR_CODE_OPCODE_NOT_SUPPORTED;
502         }
503         bass_reset_client_long_write_buffer(client);
504     }
505     return 0;
506 }
507 
508 static void broadcast_audio_scan_service_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
509     UNUSED(channel);
510     UNUSED(packet);
511     UNUSED(size);
512 
513     if (packet_type != HCI_EVENT_PACKET){
514         return;
515     }
516 
517     hci_con_handle_t con_handle;
518     bass_remote_client_t * client;
519 
520     switch (hci_event_packet_get_type(packet)) {
521         case HCI_EVENT_DISCONNECTION_COMPLETE:
522             con_handle = hci_event_disconnection_complete_get_connection_handle(packet);
523 
524             client = bass_find_client_for_con_handle(con_handle);
525             if (client == NULL){
526                 break;
527             }
528 
529             memset(client, 0, sizeof(bass_remote_client_t));
530             client->con_handle = HCI_CON_HANDLE_INVALID;
531             break;
532         default:
533             break;
534     }
535 }
536 
537 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){
538     // get service handle range
539     btstack_assert(sources_num != 0);
540     btstack_assert(clients_num != 0);
541 
542     uint16_t start_handle = 0;
543     uint16_t end_handle   = 0xffff;
544     bool service_found = gatt_server_get_handle_range_for_service_with_uuid16(ORG_BLUETOOTH_SERVICE_BROADCAST_AUDIO_SCAN_SERVICE, &start_handle, &end_handle);
545     btstack_assert(service_found);
546 
547     UNUSED(service_found);
548 
549     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);
550     bass_sources_num = 0;
551     bass_logic_time = 0;
552     bass_sources = sources;
553 
554 #ifdef ENABLE_TESTING_SUPPORT
555     printf("BASS 0x%02x - 0x%02x \n", start_handle, end_handle);
556 #endif
557     uint16_t start_chr_handle = start_handle;
558     while ( (start_chr_handle < end_handle) && (bass_sources_num < sources_num )) {
559         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);
560         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);
561 
562         if (chr_value_handle == 0){
563             break;
564         }
565         bass_server_source_t * source = &bass_sources[bass_sources_num];
566         bass_reset_source(source);
567 
568         source->source_id = bass_sources_num;
569         source->update_counter = bass_get_next_update_counter();
570         source->bass_receive_state_client_configuration = 0;
571 
572         source->bass_receive_state_handle = chr_value_handle;
573         source->bass_receive_state_client_configuration_handle = chr_client_configuration_handle;
574 
575 #ifdef ENABLE_TESTING_SUPPORT
576     printf("    bass_receive_state_%d                 0x%02x \n", bass_sources_num, source->bass_receive_state_handle);
577     printf("    bass_receive_state_%d CCC             0x%02x \n", bass_sources_num, source->bass_receive_state_client_configuration_handle);
578 #endif
579 
580         start_chr_handle = chr_client_configuration_handle + 1;
581         bass_sources_num++;
582     }
583 
584     bass_clients_num = clients_num;
585     bass_clients = clients;
586     memset(bass_clients, 0, sizeof(bass_remote_client_t) * bass_clients_num);
587     uint8_t i;
588     for (i = 0; i < bass_clients_num; i++){
589         bass_clients[i].con_handle = HCI_CON_HANDLE_INVALID;
590     }
591 
592     log_info("Found BASS service 0x%02x-0x%02x (num sources %d)", start_handle, end_handle, bass_sources_num);
593 
594     // register service with ATT Server
595     broadcast_audio_scan_service.start_handle   = start_handle;
596     broadcast_audio_scan_service.end_handle     = end_handle;
597     broadcast_audio_scan_service.read_callback  = &broadcast_audio_scan_service_read_callback;
598     broadcast_audio_scan_service.write_callback = &broadcast_audio_scan_service_write_callback;
599     broadcast_audio_scan_service.packet_handler = broadcast_audio_scan_service_packet_handler;
600     att_server_register_service_handler(&broadcast_audio_scan_service);
601 }
602 
603 void broadcast_audio_scan_service_server_register_packet_handler(btstack_packet_handler_t callback){
604     btstack_assert(callback != NULL);
605     bass_event_callback = callback;
606 }
607 
608 static void bass_service_can_send_now(void * context){
609     bass_remote_client_t * client = (bass_remote_client_t *) context;
610     btstack_assert(client != NULL);
611 
612     uint8_t source_index;
613     for (source_index = 0; source_index < bass_sources_num; source_index++){
614         uint8_t task = (1 << source_index);
615         if ((client->sources_to_notify & task) != 0){
616             client->sources_to_notify &= ~task;
617             uint8_t  buffer[BASS_MAX_NOTIFY_BUFFER_SIZE];
618             uint16_t bytes_copied = bass_server_copy_source_to_buffer(&bass_sources[source_index], 0, buffer, sizeof(buffer));
619             att_server_notify(client->con_handle, bass_sources[source_index].bass_receive_state_handle, &buffer[0], bytes_copied);
620             return;
621         }
622     }
623 
624     uint8_t i;
625     for (i = 0; i < bass_clients_num; i++){
626         client = &bass_clients[i];
627 
628         if (client->sources_to_notify != 0){
629             scheduled_tasks_callback.callback = &bass_service_can_send_now;
630             scheduled_tasks_callback.context  = (void*) client;
631             att_server_register_can_send_now_callback(&scheduled_tasks_callback, client->con_handle);
632             return;
633         }
634     }
635 }
636 
637 static void bass_set_callback(uint8_t source_index){
638     // there is only one type of task: notify on source state change
639     // as task we register which source is changed, and the change will be propagated to all clients
640     uint8_t i;
641     uint8_t task = (1 << source_index);
642 
643     uint8_t scheduled_tasks = 0;
644 
645     for (i = 0; i < bass_clients_num; i++){
646         bass_remote_client_t * client = &bass_clients[i];
647 
648         if (client->con_handle == HCI_CON_HANDLE_INVALID){
649             client->sources_to_notify &= ~task;
650             return;
651         }
652 
653         scheduled_tasks |= client->sources_to_notify;
654         client->sources_to_notify |= task;
655 
656         if (scheduled_tasks == 0){
657             scheduled_tasks_callback.callback = &bass_service_can_send_now;
658             scheduled_tasks_callback.context  = (void*) client;
659             att_server_register_can_send_now_callback(&scheduled_tasks_callback, client->con_handle);
660         }
661     }
662 }
663 
664 void broadcast_audio_scan_service_server_set_pa_sync_state(uint8_t source_index, le_audio_pa_sync_state_t sync_state){
665     btstack_assert(source_index < bass_sources_num);
666 
667     bass_server_source_t * source = &bass_sources[source_index];
668     source->data.pa_sync_state = sync_state;
669 
670     if (source->bass_receive_state_client_configuration != 0){
671         bass_set_callback(source_index);
672     }
673 }
674 
675 void broadcast_audio_scan_service_server_add_source(bass_source_data_t source_data, uint8_t * source_index){
676     *source_index = bass_find_empty_or_last_used_source_index();
677     if (*source_index == BASS_INVALID_SOURCE_INDEX){
678         return;
679     }
680     bass_server_source_t * last_used_source = &bass_sources[*source_index];
681     last_used_source->update_counter = bass_get_next_update_counter();
682     last_used_source->in_use = true;
683     last_used_source->source_id = *source_index;
684     memcpy(&last_used_source->data, &source_data, sizeof(bass_source_data_t));
685 }
686 
687 void broadcast_audio_scan_service_server_deinit(void){
688 }
689