15c0702eaSMatthias Ringwald /*
25c0702eaSMatthias Ringwald * Copyright (C) 2022 BlueKitchen GmbH
35c0702eaSMatthias Ringwald *
45c0702eaSMatthias Ringwald * Redistribution and use in source and binary forms, with or without
55c0702eaSMatthias Ringwald * modification, are permitted provided that the following conditions
65c0702eaSMatthias Ringwald * are met:
75c0702eaSMatthias Ringwald *
85c0702eaSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright
95c0702eaSMatthias Ringwald * notice, this list of conditions and the following disclaimer.
105c0702eaSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright
115c0702eaSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the
125c0702eaSMatthias Ringwald * documentation and/or other materials provided with the distribution.
135c0702eaSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of
145c0702eaSMatthias Ringwald * contributors may be used to endorse or promote products derived
155c0702eaSMatthias Ringwald * from this software without specific prior written permission.
165c0702eaSMatthias Ringwald *
175c0702eaSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
185c0702eaSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
195c0702eaSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
205c0702eaSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
215c0702eaSMatthias Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
225c0702eaSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
235c0702eaSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
245c0702eaSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
255c0702eaSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
265c0702eaSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
275c0702eaSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
285c0702eaSMatthias Ringwald * SUCH DAMAGE.
295c0702eaSMatthias Ringwald *
305c0702eaSMatthias Ringwald */
315c0702eaSMatthias Ringwald
32*0f7e8caeSMatthias Ringwald #define BTSTACK_FILE__ "le_audio_base_builder.c"
335c0702eaSMatthias Ringwald
345c0702eaSMatthias Ringwald /**
355c0702eaSMatthias Ringwald * @title Broadcast Audio Source Endpoint AD Builder
365c0702eaSMatthias Ringwald */
375c0702eaSMatthias Ringwald
385c0702eaSMatthias Ringwald #include <string.h>
395c0702eaSMatthias Ringwald
405c0702eaSMatthias Ringwald #include "bluetooth.h"
415c0702eaSMatthias Ringwald #include "bluetooth_data_types.h"
425c0702eaSMatthias Ringwald #include "bluetooth_gatt.h"
435c0702eaSMatthias Ringwald #include "btstack_util.h"
445c0702eaSMatthias Ringwald #include "btstack_debug.h"
455c0702eaSMatthias Ringwald #include "le-audio/le_audio_base_builder.h"
465c0702eaSMatthias Ringwald
le_audio_base_builder_init(le_audio_base_builder_t * builder,uint8_t * buffer,uint16_t size,uint32_t presentation_delay_us)47*0f7e8caeSMatthias Ringwald void le_audio_base_builder_init(le_audio_base_builder_t * builder, uint8_t * buffer, uint16_t size, uint32_t presentation_delay_us){
485c0702eaSMatthias Ringwald btstack_assert(size >= 8);
495c0702eaSMatthias Ringwald // default init
50*0f7e8caeSMatthias Ringwald memset(builder, 0, sizeof(le_audio_base_builder_t));
515c0702eaSMatthias Ringwald builder->buffer = buffer;
525c0702eaSMatthias Ringwald builder->size = size;
535c0702eaSMatthias Ringwald builder->len = 0;
545c0702eaSMatthias Ringwald builder->buffer[builder->len++] = 7;
555c0702eaSMatthias Ringwald builder->buffer[builder->len++] = BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID;
565c0702eaSMatthias Ringwald little_endian_store_16(builder->buffer, 2, ORG_BLUETOOTH_SERVICE_BASIC_AUDIO_ANNOUNCEMENT_SERVICE);
575c0702eaSMatthias Ringwald builder->len += 2;
585c0702eaSMatthias Ringwald little_endian_store_24(builder->buffer, 4, presentation_delay_us);
595c0702eaSMatthias Ringwald builder->len += 3;
605c0702eaSMatthias Ringwald builder->buffer[builder->len++] = 0;
615c0702eaSMatthias Ringwald builder->subgroup_offset = builder->len;
625c0702eaSMatthias Ringwald }
635c0702eaSMatthias Ringwald
le_audio_base_builder_add_subgroup(le_audio_base_builder_t * builder,const uint8_t * codec_id,uint8_t codec_specific_configuration_length,const uint8_t * codec_specific_configuration,uint8_t metadata_length,const uint8_t * metadata)64*0f7e8caeSMatthias Ringwald void le_audio_base_builder_add_subgroup(le_audio_base_builder_t * builder,
655c0702eaSMatthias Ringwald const uint8_t * codec_id,
665c0702eaSMatthias Ringwald uint8_t codec_specific_configuration_length, const uint8_t * codec_specific_configuration,
675c0702eaSMatthias Ringwald uint8_t metadata_length, const uint8_t * metadata){
685c0702eaSMatthias Ringwald // check len
695c0702eaSMatthias Ringwald uint16_t additional_len = 1 + 5 + 1 + codec_specific_configuration_length + 1 + metadata_length;
705c0702eaSMatthias Ringwald btstack_assert((builder->len + additional_len) <= builder->size);
715c0702eaSMatthias Ringwald
725c0702eaSMatthias Ringwald builder->buffer[builder->len++] = 0;
735c0702eaSMatthias Ringwald memcpy(&builder->buffer[builder->len], codec_id, 5);
745c0702eaSMatthias Ringwald builder->len += 5;
755c0702eaSMatthias Ringwald builder->buffer[builder->len++] = codec_specific_configuration_length;
765c0702eaSMatthias Ringwald memcpy(&builder->buffer[builder->len], codec_specific_configuration, codec_specific_configuration_length);
775c0702eaSMatthias Ringwald builder->len += codec_specific_configuration_length;
785c0702eaSMatthias Ringwald builder->buffer[builder->len++] = metadata_length;
795c0702eaSMatthias Ringwald memcpy(&builder->buffer[builder->len], metadata, metadata_length);
805c0702eaSMatthias Ringwald builder->len += metadata_length;
815c0702eaSMatthias Ringwald builder->bis_offset = builder->len;
825c0702eaSMatthias Ringwald
835c0702eaSMatthias Ringwald // update num subgroups
845c0702eaSMatthias Ringwald builder->buffer[7]++;
855c0702eaSMatthias Ringwald
865c0702eaSMatthias Ringwald // update total len
875c0702eaSMatthias Ringwald builder->buffer[0] = builder->len - 1;
885c0702eaSMatthias Ringwald }
895c0702eaSMatthias Ringwald
905c0702eaSMatthias Ringwald /**
915c0702eaSMatthias Ringwald * Add BIS to current BASE
925c0702eaSMatthias Ringwald * @param builder
935c0702eaSMatthias Ringwald * @param bis_index
945c0702eaSMatthias Ringwald * @param codec_specific_configuration_length
955c0702eaSMatthias Ringwald * @param codec_specific_configuration
965c0702eaSMatthias Ringwald */
le_audio_base_builder_add_bis(le_audio_base_builder_t * builder,uint8_t bis_index,uint8_t codec_specific_configuration_length,const uint8_t * codec_specific_configuration)97*0f7e8caeSMatthias Ringwald void le_audio_base_builder_add_bis(le_audio_base_builder_t * builder,
985c0702eaSMatthias Ringwald uint8_t bis_index,
995c0702eaSMatthias Ringwald uint8_t codec_specific_configuration_length,
1005c0702eaSMatthias Ringwald const uint8_t * codec_specific_configuration){
1015c0702eaSMatthias Ringwald // check len
1025c0702eaSMatthias Ringwald uint16_t additional_len = 1 + 1 + codec_specific_configuration_length;
1035c0702eaSMatthias Ringwald btstack_assert((builder->len + additional_len) <= builder->size);
1045c0702eaSMatthias Ringwald
1055c0702eaSMatthias Ringwald // append data
1065c0702eaSMatthias Ringwald builder->buffer[builder->len++] = bis_index;
1075c0702eaSMatthias Ringwald builder->buffer[builder->len++] = codec_specific_configuration_length;
1085c0702eaSMatthias Ringwald memcpy(&builder->buffer[builder->len], codec_specific_configuration, codec_specific_configuration_length);
1095c0702eaSMatthias Ringwald builder->len += codec_specific_configuration_length;
1105c0702eaSMatthias Ringwald
1115c0702eaSMatthias Ringwald // update num bis
1125c0702eaSMatthias Ringwald builder->buffer[builder->subgroup_offset]++;
1135c0702eaSMatthias Ringwald
1145c0702eaSMatthias Ringwald // update total len
1155c0702eaSMatthias Ringwald builder->buffer[0] = builder->len - 1;
1165c0702eaSMatthias Ringwald }
1175c0702eaSMatthias Ringwald
le_audio_base_builder_get_ad_data_size(const le_audio_base_builder_t * builder)118*0f7e8caeSMatthias Ringwald uint16_t le_audio_base_builder_get_ad_data_size(const le_audio_base_builder_t * builder){
1195c0702eaSMatthias Ringwald return builder->len;
1205c0702eaSMatthias Ringwald }
121