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_util.h"
51 #include "le-audio/le_audio.h"
52 #include "le-audio/le_audio_util.h"
53
54 #ifdef ENABLE_TESTING_SUPPORT
55 #include <stdio.h>
56 #endif
57
58 // offset gives position into fully serialized bass record
bass_util_source_data_header_virtual_memcpy(const bass_source_data_t * data,uint16_t * source_offset,uint16_t buffer_offset,uint8_t * buffer,uint16_t buffer_size)59 uint16_t bass_util_source_data_header_virtual_memcpy(const bass_source_data_t * data, uint16_t *source_offset, uint16_t buffer_offset, uint8_t * buffer, uint16_t buffer_size){
60 uint16_t stored_bytes = 0;
61 uint8_t field_data[16];
62
63 field_data[0] = (uint8_t)data->address_type;
64 stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 1, *source_offset, buffer, buffer_size,
65 buffer_offset);
66 (*source_offset)++;
67
68 reverse_bd_addr(data->address, &field_data[0]);
69 stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 6, *source_offset, buffer, buffer_size,
70 buffer_offset);
71 (*source_offset) += 6;
72
73 field_data[0] = data->adv_sid;
74 stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 1, *source_offset, buffer, buffer_size,
75 buffer_offset);
76 (*source_offset)++;
77
78 little_endian_store_24(field_data, 0, data->broadcast_id);
79 stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 3, *source_offset, buffer, buffer_size,
80 buffer_offset);
81 (*source_offset) += 3;
82
83 return stored_bytes;
84 }
85
86 // offset gives position into fully serialized bass record
87 uint16_t
bass_util_source_data_subgroups_virtual_memcpy(const bass_source_data_t * data,bool use_state_fields,uint16_t * source_offset,uint16_t buffer_offset,uint8_t * buffer,uint16_t buffer_size)88 bass_util_source_data_subgroups_virtual_memcpy(const bass_source_data_t *data, bool use_state_fields, uint16_t *source_offset,
89 uint16_t buffer_offset, uint8_t *buffer, uint16_t buffer_size) {
90 uint16_t stored_bytes = 0;
91 uint8_t field_data[16];
92
93 field_data[0] = (uint8_t)data->subgroups_num;
94 stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 1, *source_offset, buffer, buffer_size,
95 buffer_offset);
96 (*source_offset)++;
97
98 uint8_t i;
99 for (i = 0; i < data->subgroups_num; i++){
100 bass_subgroup_t subgroup = data->subgroups[i];
101
102 if (use_state_fields) {
103 little_endian_store_32(field_data, 0, subgroup.bis_sync_state);
104 } else {
105 little_endian_store_32(field_data, 0, subgroup.bis_sync);
106 }
107 stored_bytes += le_audio_util_virtual_memcpy_helper(field_data, 4, *source_offset, buffer, buffer_size,
108 buffer_offset);
109 (*source_offset) += 4;
110 stored_bytes += le_audio_util_metadata_virtual_memcpy(&subgroup.metadata, subgroup.metadata_length,
111 source_offset, buffer, buffer_size, buffer_offset);
112 }
113 return stored_bytes;
114 }
115
bass_util_pa_sync_state_and_subgroups_in_valid_range(const uint8_t * buffer,uint16_t buffer_size)116 bool bass_util_pa_sync_state_and_subgroups_in_valid_range(const uint8_t *buffer, uint16_t buffer_size){
117 uint8_t pos = 0;
118 // pa_sync_state
119 uint8_t pa_sync_state = buffer[pos++];
120 if (pa_sync_state >= (uint8_t)LE_AUDIO_PA_SYNC_STATE_RFU){
121 log_info("Unexpected pa_sync_state 0x%02X", pa_sync_state);
122 return false;
123 }
124
125 // pa_interval
126 pos += 2;
127 uint8_t num_subgroups = buffer[pos++];
128 if (num_subgroups > BASS_SUBGROUPS_MAX_NUM){
129 log_info("Number of subgroups %u exceedes maximum %u", num_subgroups, BASS_SUBGROUPS_MAX_NUM);
130 return false;
131 }
132
133 // If a BIS_Sync parameter value is not 0xFFFFFFFF for a subgroup,
134 // and if a BIS_index value written by a client is set to a value of 0b1 in more than one subgroup,
135 // the server shall ignore the operation.
136 uint8_t i;
137 uint32_t mask_total = 0;
138 for (i = 0; i < num_subgroups; i++){
139 // bis_sync
140 uint32_t bis_sync = little_endian_read_32(buffer, pos);
141 pos += 4;
142
143 if (bis_sync != 0xFFFFFFFF){
144 uint32_t mask_add = mask_total + ~bis_sync;
145 uint32_t mask_or = mask_total | ~bis_sync;
146 if (mask_add != mask_or){
147 // not disjunct
148 return false;
149 }
150 mask_total = mask_add;
151 }
152
153 // check if we can read metadata_length
154 if (pos >= buffer_size){
155 log_info("Metadata length not specified, subgroup %u", i);
156 return false;
157 }
158
159 uint8_t metadata_length = buffer[pos++];
160
161 if ((buffer_size - pos) < metadata_length){
162 log_info("Metadata length %u exceedes remaining buffer %u", metadata_length, buffer_size - pos);
163 return false;
164 }
165 // metadata
166 pos += metadata_length;
167 }
168
169 return (pos == buffer_size);
170 }
171
bass_util_source_buffer_in_valid_range(const uint8_t * buffer,uint16_t buffer_size)172 bool bass_util_source_buffer_in_valid_range(const uint8_t *buffer, uint16_t buffer_size){
173 if (buffer_size < 15){
174 log_info("Add Source opcode, buffer too small");
175 return false;
176 }
177
178 uint8_t pos = 0;
179 // addr type
180 uint8_t adv_type = buffer[pos++];
181 if (adv_type > (uint8_t)BD_ADDR_TYPE_LE_RANDOM){
182 log_info("Unexpected adv_type 0x%02X", adv_type);
183 return false;
184 }
185
186 // address
187 pos += 6;
188
189 // advertising_sid Range: 0x00-0x0F
190 uint8_t advertising_sid = buffer[pos++];
191 if (advertising_sid > 0x0F){
192 log_info("Advertising sid out of range 0x%02X", advertising_sid);
193 return false;
194 }
195
196 // broadcast_id
197 pos += 3;
198 return bass_util_pa_sync_state_and_subgroups_in_valid_range(buffer+pos, buffer_size-pos);
199 }
200
201 void
bass_util_pa_info_and_subgroups_parse(const uint8_t * buffer,uint16_t buffer_size,bass_source_data_t * source_data,bool is_broadcast_receive_state)202 bass_util_pa_info_and_subgroups_parse(const uint8_t *buffer, uint16_t buffer_size, bass_source_data_t *source_data,
203 bool is_broadcast_receive_state) {
204 UNUSED(buffer_size);
205 uint8_t pos = 0;
206 // for Broadcast Receive state, we have BIG_Encryption + Bad_Code, while for Add/Modify we have PA_Interval
207 if (is_broadcast_receive_state){
208 source_data->pa_sync_state = (le_audio_pa_sync_state_t)buffer[pos++];
209 source_data->big_encryption = (le_audio_big_encryption_t) buffer[pos++];
210 if (source_data->big_encryption == LE_AUDIO_BIG_ENCRYPTION_BAD_CODE){
211 memcpy(source_data->bad_code, &buffer[pos], 16);
212 pos += 16;
213 } else {
214 memset(source_data->bad_code, 0, 16);
215 }
216 } else {
217 source_data->pa_sync = (le_audio_pa_sync_t)buffer[pos++];
218 source_data->pa_interval = little_endian_read_16(buffer, pos);
219 pos += 2;
220 }
221
222 source_data->subgroups_num = buffer[pos++];
223 uint8_t i;
224 for (i = 0; i < source_data->subgroups_num; i++){
225 // bis_sync / state
226 if (is_broadcast_receive_state){
227 source_data->subgroups[i].bis_sync_state = little_endian_read_32(buffer, pos);
228 } else {
229 source_data->subgroups[i].bis_sync = little_endian_read_32(buffer, pos);
230 }
231 pos += 4;
232
233 uint8_t metadata_bytes_read = le_audio_util_metadata_parse(&buffer[pos], buffer_size - pos,
234 &source_data->subgroups[i].metadata);
235 source_data->subgroups[i].metadata_length = metadata_bytes_read - 1;
236 pos += metadata_bytes_read;
237 }
238 }
239
bass_util_source_data_parse(const uint8_t * buffer,uint16_t buffer_size,bass_source_data_t * source_data,bool is_broadcast_receive_state)240 void bass_util_source_data_parse(const uint8_t *buffer, uint16_t buffer_size, bass_source_data_t *source_data,
241 bool is_broadcast_receive_state) {
242 UNUSED(buffer_size);
243 uint8_t pos = 0;
244
245 source_data->address_type = (bd_addr_type_t)buffer[pos++];
246
247 reverse_bd_addr(&buffer[pos], source_data->address);
248 pos += 6;
249
250 source_data->adv_sid = buffer[pos++];
251
252 source_data->broadcast_id = little_endian_read_24(buffer, pos);
253 pos += 3;
254
255 bass_util_pa_info_and_subgroups_parse(buffer + pos, buffer_size - pos, source_data, is_broadcast_receive_state);
256 }