1 2 /* 3 * Copyright (C) 2016 BlueKitchen GmbH 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 4. Any redistribution, use, or modification is done solely for 18 * personal benefit and not for any commercial purpose or for 19 * monetary gain. 20 * 21 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 25 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 31 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * Please inquire about commercial licensing options at 35 * [email protected] 36 * 37 */ 38 39 /** 40 * Supported use cases: 41 * - single incoming connection: sep discovery starts and stream will get setup if remote sink sep with SBC is found 42 * - single outgoing connection: see above 43 * - outgoing and incoming connection to same device: 44 * - if outgoing is triggered first, incoming will get ignored. 45 * - if incoming starts first, start ougoing will fail, but incoming will succeed. 46 * - outgoing and incoming connections to different devices: 47 * - if outgoing is first, incoming gets ignored. 48 * - if incoming starts first SEP discovery will get stopped and outgoing will succeed. 49 */ 50 51 #define BTSTACK_FILE__ "a2dp_source.c" 52 53 #include <stdint.h> 54 #include <string.h> 55 56 #include "bluetooth_psm.h" 57 #include "bluetooth_sdp.h" 58 #include "btstack_debug.h" 59 #include "btstack_event.h" 60 #include "classic/a2dp.h" 61 #include "classic/a2dp_source.h" 62 #include "classic/avdtp_source.h" 63 #include "classic/avdtp_util.h" 64 #include "classic/sdp_util.h" 65 #include "l2cap.h" 66 #include "a2dp.h" 67 68 #define AVDTP_MAX_SEP_NUM 10 69 #define A2DP_SET_CONFIG_DELAY_MS 200 70 71 static const char * a2dp_default_source_service_name = "BTstack A2DP Source Service"; 72 static const char * a2dp_default_source_service_provider_name = "BTstack A2DP Source Service Provider"; 73 74 static uint8_t (*a2dp_source_media_config_validator)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size); 75 76 // config process - singletons using sep_discovery_cid is used as mutex 77 static uint16_t a2dp_source_sep_discovery_cid; 78 static uint16_t a2dp_source_sep_discovery_count; 79 static uint16_t a2dp_source_sep_discovery_index; 80 static avdtp_sep_t a2dp_source_sep_discovery_seps[AVDTP_MAX_SEP_NUM]; 81 static btstack_timer_source_t a2dp_source_set_config_timer; 82 static bool a2dp_source_set_config_timer_active; 83 84 static void a2dp_source_packet_handler_internal(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 85 static void a2dp_discover_seps_with_next_waiting_connection(void); 86 87 void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){ 88 uint8_t* attribute; 89 de_create_sequence(service); 90 91 // 0x0000 "Service Record Handle" 92 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE); 93 de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle); 94 95 // 0x0001 "Service Class ID List" 96 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST); 97 attribute = de_push_sequence(service); 98 { 99 de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AUDIO_SOURCE); 100 } 101 de_pop_sequence(service, attribute); 102 103 // 0x0004 "Protocol Descriptor List" 104 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST); 105 attribute = de_push_sequence(service); 106 { 107 uint8_t* l2cpProtocol = de_push_sequence(attribute); 108 { 109 de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP); 110 de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, BLUETOOTH_PSM_AVDTP); 111 } 112 de_pop_sequence(attribute, l2cpProtocol); 113 114 uint8_t* avProtocol = de_push_sequence(attribute); 115 { 116 de_add_number(avProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVDTP); // avProtocol_service 117 de_add_number(avProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version 118 } 119 de_pop_sequence(attribute, avProtocol); 120 } 121 de_pop_sequence(service, attribute); 122 123 // 0x0005 "Public Browse Group" 124 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group 125 attribute = de_push_sequence(service); 126 { 127 de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT); 128 } 129 de_pop_sequence(service, attribute); 130 131 // 0x0009 "Bluetooth Profile Descriptor List" 132 de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST); 133 attribute = de_push_sequence(service); 134 { 135 uint8_t *a2dProfile = de_push_sequence(attribute); 136 { 137 de_add_number(a2dProfile, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION); 138 de_add_number(a2dProfile, DE_UINT, DE_SIZE_16, 0x0103); 139 } 140 de_pop_sequence(attribute, a2dProfile); 141 } 142 de_pop_sequence(service, attribute); 143 144 145 // 0x0100 "Service Name" 146 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); 147 if (service_name){ 148 de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name); 149 } else { 150 de_add_data(service, DE_STRING, strlen(a2dp_default_source_service_name), (uint8_t *) a2dp_default_source_service_name); 151 } 152 153 // 0x0100 "Provider Name" 154 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102); 155 if (service_provider_name){ 156 de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name); 157 } else { 158 de_add_data(service, DE_STRING, strlen(a2dp_default_source_service_provider_name), (uint8_t *) a2dp_default_source_service_provider_name); 159 } 160 161 // 0x0311 "Supported Features" 162 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311); 163 de_add_number(service, DE_UINT, DE_SIZE_16, supported_features); 164 } 165 166 static void a2dp_signaling_emit_reconfigured(uint16_t cid, uint8_t local_seid, uint8_t status){ 167 uint8_t event[7]; 168 int pos = 0; 169 event[pos++] = HCI_EVENT_A2DP_META; 170 event[pos++] = sizeof(event) - 2; 171 event[pos++] = A2DP_SUBEVENT_STREAM_RECONFIGURED; 172 little_endian_store_16(event, pos, cid); 173 pos += 2; 174 event[pos++] = local_seid; 175 event[pos++] = status; 176 a2dp_emit_source(event, sizeof(event)); 177 } 178 179 static void a2dp_source_set_config_timer_handler(btstack_timer_source_t * timer){ 180 uint16_t avdtp_cid = (uint16_t)(uintptr_t) btstack_run_loop_get_timer_context(timer); 181 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(avdtp_cid); 182 btstack_run_loop_set_timer_context(&a2dp_source_set_config_timer, NULL); 183 a2dp_source_set_config_timer_active = false; 184 185 log_info("Set Config timer fired, avdtp_cid 0x%02x", avdtp_cid); 186 187 if (connection == NULL) { 188 a2dp_discover_seps_with_next_waiting_connection(); 189 return; 190 } 191 192 if (connection->a2dp_source_stream_endpoint_configured) return; 193 avdtp_source_discover_stream_endpoints(avdtp_cid); 194 } 195 196 static void a2dp_source_set_config_timer_start(uint16_t avdtp_cid){ 197 log_info("Set Config timer start for cid 0%02x", avdtp_cid); 198 a2dp_source_set_config_timer_active = true; 199 btstack_run_loop_remove_timer(&a2dp_source_set_config_timer); 200 btstack_run_loop_set_timer_handler(&a2dp_source_set_config_timer,a2dp_source_set_config_timer_handler); 201 btstack_run_loop_set_timer(&a2dp_source_set_config_timer, A2DP_SET_CONFIG_DELAY_MS); 202 btstack_run_loop_set_timer_context(&a2dp_source_set_config_timer, (void *)(uintptr_t)avdtp_cid); 203 btstack_run_loop_add_timer(&a2dp_source_set_config_timer); 204 } 205 206 static void a2dp_source_set_config_timer_restart(void){ 207 log_info("Set Config timer restart"); 208 btstack_run_loop_remove_timer(&a2dp_source_set_config_timer); 209 btstack_run_loop_set_timer(&a2dp_source_set_config_timer, A2DP_SET_CONFIG_DELAY_MS); 210 btstack_run_loop_add_timer(&a2dp_source_set_config_timer); 211 } 212 213 static void a2dp_source_set_config_timer_stop(void){ 214 if (a2dp_source_set_config_timer_active == false) return; 215 log_info("Set Config timer stop"); 216 btstack_run_loop_remove_timer(&a2dp_source_set_config_timer); 217 btstack_run_loop_set_timer_context(&a2dp_source_set_config_timer, NULL); 218 a2dp_source_set_config_timer_active = false; 219 } 220 221 // Discover seps, both incoming and outgoing 222 static void a2dp_start_discovering_seps(avdtp_connection_t * connection){ 223 connection->a2dp_source_state = A2DP_DISCOVER_SEPS; 224 connection->a2dp_source_discover_seps = false; 225 226 a2dp_source_sep_discovery_index = 0; 227 a2dp_source_sep_discovery_count = 0; 228 memset(a2dp_source_sep_discovery_seps, 0, sizeof(avdtp_sep_t) * AVDTP_MAX_SEP_NUM); 229 a2dp_source_sep_discovery_cid = connection->avdtp_cid; 230 231 // if we initiated the connection, start config right away, else wait a bit to give remote a chance to do it first 232 if (connection->a2dp_source_outgoing_active){ 233 log_info("discover seps"); 234 avdtp_source_discover_stream_endpoints(connection->avdtp_cid); 235 } else { 236 log_info("wait a bit, then discover seps"); 237 a2dp_source_set_config_timer_start(connection->avdtp_cid); 238 } 239 } 240 241 static void a2dp_discover_seps_with_next_waiting_connection(void){ 242 btstack_assert(a2dp_source_sep_discovery_cid == 0); 243 btstack_linked_list_iterator_t it; 244 btstack_linked_list_iterator_init(&it, avdtp_get_connections()); 245 while (btstack_linked_list_iterator_has_next(&it)){ 246 avdtp_connection_t * next_connection = (avdtp_connection_t *)btstack_linked_list_iterator_next(&it); 247 if (!next_connection->a2dp_source_discover_seps) continue; 248 a2dp_start_discovering_seps(next_connection); 249 } 250 } 251 252 static void a2dp_source_ready_for_sep_discovery(avdtp_connection_t * connection){ 253 // start discover seps now if: 254 // - outgoing active: signaling for outgoing connection 255 // - outgoing not active: incoming connection and no sep discover ongoing 256 257 // sep discovery active? 258 if (a2dp_source_sep_discovery_cid == 0){ 259 a2dp_start_discovering_seps(connection); 260 } else { 261 // post-pone sep discovery 262 connection->a2dp_source_discover_seps = true; 263 } 264 } 265 266 static void a2dp_handle_received_configuration(const uint8_t *packet, uint8_t local_seid) { 267 uint16_t cid = avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(packet); 268 avdtp_connection_t *avdtp_connection = avdtp_get_connection_for_avdtp_cid(cid); 269 btstack_assert(avdtp_connection != NULL); 270 avdtp_connection->a2dp_source_local_stream_endpoint = avdtp_get_stream_endpoint_for_seid(local_seid); 271 // bail out if local seid invalid 272 if (!avdtp_connection->a2dp_source_local_stream_endpoint) return; 273 274 // stop timer 275 if (a2dp_source_sep_discovery_cid == cid) { 276 a2dp_source_set_config_timer_stop(); 277 a2dp_source_sep_discovery_cid = 0; 278 } 279 280 avdtp_connection->a2dp_source_stream_endpoint_configured = true; 281 282 switch (avdtp_connection->a2dp_source_state) { 283 case A2DP_W4_SET_CONFIGURATION: 284 // outgoing: discovery and config of remote sink sep successful, trigger stream open 285 avdtp_connection->a2dp_source_state = A2DP_W2_OPEN_STREAM_WITH_SEID; 286 break; 287 case A2DP_DISCOVER_SEPS: 288 case A2DP_GET_CAPABILITIES: 289 case A2DP_W2_GET_ALL_CAPABILITIES: 290 case A2DP_DISCOVERY_DONE: 291 case A2DP_W4_GET_CONFIGURATION: 292 // incoming: wait for stream open 293 avdtp_connection->a2dp_source_state = A2DP_W4_OPEN_STREAM_WITH_SEID; 294 break; 295 default: 296 // wait for configuration after sending reconfigure - keep state 297 break; 298 } 299 } 300 301 static void a2dp_source_set_config(avdtp_connection_t * connection){ 302 uint8_t remote_seid = connection->a2dp_source_local_stream_endpoint->set_config_remote_seid; 303 log_info("A2DP initiate set configuration locally and wait for response ... local seid 0x%02x, remote seid 0x%02x", avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), remote_seid); 304 connection->a2dp_source_state = A2DP_W4_SET_CONFIGURATION; 305 avdtp_source_set_configuration(connection->avdtp_cid, avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), remote_seid, connection->a2dp_source_local_stream_endpoint->remote_configuration_bitmap, connection->a2dp_source_local_stream_endpoint->remote_configuration); 306 } 307 308 static void a2dp_source_packet_handler_internal(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 309 UNUSED(channel); 310 UNUSED(size); 311 312 uint16_t cid; 313 avdtp_connection_t * connection; 314 315 uint8_t signal_identifier; 316 uint8_t status; 317 uint8_t local_seid; 318 uint8_t remote_seid; 319 320 if (packet_type != HCI_EVENT_PACKET) return; 321 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVDTP_META) return; 322 323 switch (packet[2]){ 324 case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: 325 cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet); 326 connection = avdtp_get_connection_for_avdtp_cid(cid); 327 btstack_assert(connection != NULL); 328 329 status = avdtp_subevent_signaling_connection_established_get_status(packet); 330 if (status != ERROR_CODE_SUCCESS){ 331 // notify about connection error only if we're initiator 332 if (connection->a2dp_source_outgoing_active){ 333 log_info("A2DP source signaling connection failed status 0x%02x", status); 334 connection->a2dp_source_outgoing_active = false; 335 a2dp_replace_subevent_id_and_emit_source(packet, size, 336 A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED); 337 } 338 break; 339 } 340 log_info("A2DP source signaling connection established avdtp_cid 0x%02x", cid); 341 connection->a2dp_source_state = A2DP_CONNECTED; 342 343 // notify app 344 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED); 345 346 // Windows 10 as Source starts SEP discovery after 1500 ms, but only if it did not get a Discover command 347 // If BTstack is configured for both roles, we need to avoid sending Discover command in Source Role for outgoing Sink connections 348 349 // For this, we trigger SDP query only if: 350 // a) this is an outgoing source connection 351 // b) this connection wasn't caused by an outgoing sink request 352 if (connection->a2dp_source_outgoing_active || !connection->a2dp_sink_outgoing_active){ 353 a2dp_source_ready_for_sep_discovery(connection); 354 } 355 break; 356 357 case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND: 358 cid = avdtp_subevent_signaling_sep_found_get_avdtp_cid(packet); 359 connection = avdtp_get_connection_for_avdtp_cid(cid); 360 btstack_assert(connection != NULL); 361 362 if (connection->a2dp_source_state == A2DP_DISCOVER_SEPS) { 363 avdtp_sep_t sep; 364 memset(&sep, 0, sizeof(avdtp_sep_t)); 365 sep.seid = avdtp_subevent_signaling_sep_found_get_remote_seid(packet);; 366 sep.in_use = avdtp_subevent_signaling_sep_found_get_in_use(packet); 367 sep.media_type = (avdtp_media_type_t) avdtp_subevent_signaling_sep_found_get_media_type(packet); 368 sep.type = (avdtp_sep_type_t) avdtp_subevent_signaling_sep_found_get_sep_type(packet); 369 log_info("A2DP Found sep: remote seid 0x%02x, in_use %d, media type %d, sep type %s, index %d", 370 sep.seid, sep.in_use, sep.media_type, sep.type == AVDTP_SOURCE ? "source" : "sink", 371 a2dp_source_sep_discovery_count); 372 if ((sep.type == AVDTP_SINK) && (sep.in_use == false)) { 373 a2dp_source_sep_discovery_seps[a2dp_source_sep_discovery_count++] = sep; 374 } 375 } 376 break; 377 378 case AVDTP_SUBEVENT_SIGNALING_SEP_DICOVERY_DONE: 379 cid = avdtp_subevent_signaling_sep_dicovery_done_get_avdtp_cid(packet); 380 connection = avdtp_get_connection_for_avdtp_cid(cid); 381 btstack_assert(connection != NULL); 382 383 if (connection->a2dp_source_state != A2DP_DISCOVER_SEPS) break; 384 385 if (a2dp_source_sep_discovery_count > 0){ 386 connection->a2dp_source_state = A2DP_GET_CAPABILITIES; 387 a2dp_source_sep_discovery_index = 0; 388 connection->a2dp_source_have_config = false; 389 } else { 390 if (connection->a2dp_source_outgoing_active){ 391 connection->a2dp_source_outgoing_active = false; 392 connection = avdtp_get_connection_for_avdtp_cid(cid); 393 btstack_assert(connection != NULL); 394 a2dp_emit_source_streaming_connection_failed(connection, 395 ERROR_CODE_CONNECTION_REJECTED_DUE_TO_NO_SUITABLE_CHANNEL_FOUND); 396 } 397 398 // continue 399 connection->a2dp_source_state = A2DP_CONNECTED; 400 a2dp_source_sep_discovery_cid = 0; 401 a2dp_discover_seps_with_next_waiting_connection(); 402 } 403 break; 404 405 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY: 406 cid = avdtp_subevent_signaling_media_codec_sbc_capability_get_avdtp_cid(packet); 407 connection = avdtp_get_connection_for_avdtp_cid(cid); 408 btstack_assert(connection != NULL); 409 410 if (connection->a2dp_source_state != A2DP_GET_CAPABILITIES) break; 411 412 // forward codec capability 413 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY); 414 415 #ifndef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 416 // select SEP if none configured yet 417 if (connection->a2dp_source_have_config == false){ 418 // find SBC stream endpoint 419 avdtp_stream_endpoint_t * stream_endpoint = avdtp_get_source_stream_endpoint_for_media_codec(AVDTP_CODEC_SBC); 420 if (stream_endpoint != NULL){ 421 // choose SBC config params 422 avdtp_configuration_sbc_t configuration; 423 configuration.sampling_frequency = avdtp_choose_sbc_sampling_frequency(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet)); 424 configuration.channel_mode = avdtp_choose_sbc_channel_mode(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet)); 425 configuration.block_length = avdtp_choose_sbc_block_length(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet)); 426 configuration.subbands = avdtp_choose_sbc_subbands(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet)); 427 configuration.allocation_method = avdtp_choose_sbc_allocation_method(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet)); 428 configuration.max_bitpool_value = avdtp_choose_sbc_max_bitpool_value(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet)); 429 configuration.min_bitpool_value = avdtp_choose_sbc_min_bitpool_value(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet)); 430 431 // and pre-select this endpoint 432 local_seid = avdtp_stream_endpoint_seid(stream_endpoint); 433 remote_seid = avdtp_subevent_signaling_media_codec_sbc_capability_get_remote_seid(packet); 434 a2dp_source_set_config_sbc(cid, local_seid, remote_seid, &configuration); 435 } 436 } 437 #endif 438 break; 439 440 // forward codec capability 441 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AUDIO_CAPABILITY: 442 cid = avdtp_subevent_signaling_media_codec_mpeg_audio_capability_get_avdtp_cid(packet); 443 connection = avdtp_get_connection_for_avdtp_cid(cid); 444 btstack_assert(connection != NULL); 445 446 if (connection->a2dp_source_state != A2DP_GET_CAPABILITIES) break; 447 a2dp_replace_subevent_id_and_emit_source(packet, size, 448 A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AUDIO_CAPABILITY); 449 break; 450 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AAC_CAPABILITY: 451 cid = avdtp_subevent_signaling_media_codec_mpeg_aac_capability_get_avdtp_cid(packet); 452 connection = avdtp_get_connection_for_avdtp_cid(cid); 453 btstack_assert(connection != NULL); 454 455 if (connection->a2dp_source_state != A2DP_GET_CAPABILITIES) break; 456 a2dp_replace_subevent_id_and_emit_source(packet, size, 457 A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AAC_CAPABILITY); 458 break; 459 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_ATRAC_CAPABILITY: 460 cid = avdtp_subevent_signaling_media_codec_atrac_capability_get_avdtp_cid(packet); 461 connection = avdtp_get_connection_for_avdtp_cid(cid); 462 btstack_assert(connection != NULL); 463 464 if (connection->a2dp_source_state != A2DP_GET_CAPABILITIES) break; 465 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_ATRAC_CAPABILITY); 466 break; 467 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY: 468 cid = avdtp_subevent_signaling_media_codec_other_capability_get_avdtp_cid(packet); 469 connection = avdtp_get_connection_for_avdtp_cid(cid); 470 btstack_assert(connection != NULL); 471 472 if (connection->a2dp_source_state != A2DP_GET_CAPABILITIES) break; 473 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY); 474 break; 475 476 // not forwarded 477 case AVDTP_SUBEVENT_SIGNALING_MEDIA_TRANSPORT_CAPABILITY: 478 case AVDTP_SUBEVENT_SIGNALING_REPORTING_CAPABILITY: 479 case AVDTP_SUBEVENT_SIGNALING_RECOVERY_CAPABILITY: 480 case AVDTP_SUBEVENT_SIGNALING_CONTENT_PROTECTION_CAPABILITY: 481 case AVDTP_SUBEVENT_SIGNALING_HEADER_COMPRESSION_CAPABILITY: 482 case AVDTP_SUBEVENT_SIGNALING_MULTIPLEXING_CAPABILITY: 483 break; 484 485 case AVDTP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY: 486 cid = avdtp_subevent_signaling_delay_reporting_capability_get_avdtp_cid(packet); 487 connection = avdtp_get_connection_for_avdtp_cid(cid); 488 btstack_assert(connection != NULL); 489 log_info("received AVDTP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY, cid 0x%02x, state %d", cid, connection->a2dp_source_state); 490 491 if (connection->a2dp_source_state != A2DP_GET_CAPABILITIES) break; 492 493 // store delay reporting capability 494 a2dp_source_sep_discovery_seps[a2dp_source_sep_discovery_index].registered_service_categories |= 1 << AVDTP_DELAY_REPORTING; 495 496 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY); 497 break; 498 499 case AVDTP_SUBEVENT_SIGNALING_CAPABILITIES_DONE: 500 cid = avdtp_subevent_signaling_capabilities_done_get_avdtp_cid(packet); 501 connection = avdtp_get_connection_for_avdtp_cid(cid); 502 btstack_assert(connection != NULL); 503 504 if (connection->a2dp_source_state != A2DP_GET_CAPABILITIES) break; 505 506 // forward capabilities done for endpoint 507 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE); 508 509 // endpoint was not suitable, check next one 510 a2dp_source_sep_discovery_index++; 511 if (a2dp_source_sep_discovery_index >= a2dp_source_sep_discovery_count){ 512 513 // emit 'all capabilities for all seps reported' 514 uint8_t event[6]; 515 uint8_t pos = 0; 516 event[pos++] = HCI_EVENT_A2DP_META; 517 event[pos++] = sizeof(event) - 2; 518 event[pos++] = A2DP_SUBEVENT_SIGNALING_CAPABILITIES_COMPLETE; 519 little_endian_store_16(event, pos, cid); 520 a2dp_emit_source(event, sizeof(event)); 521 522 // do we have a valid config? 523 if (connection->a2dp_source_have_config){ 524 connection->a2dp_source_state = A2DP_SET_CONFIGURATION; 525 connection->a2dp_source_have_config = false; 526 break; 527 } 528 529 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 530 connection->a2dp_source_state = A2DP_DISCOVERY_DONE; 531 // TODO call a2dp_discover_seps_with_next_waiting_connection? 532 break; 533 #else 534 // we didn't find a suitable SBC stream endpoint, sorry. 535 if (connection->a2dp_source_outgoing_active){ 536 connection->a2dp_source_outgoing_active = false; 537 connection = avdtp_get_connection_for_avdtp_cid(cid); 538 btstack_assert(connection != NULL); 539 a2dp_emit_source_streaming_connection_failed(connection, 540 ERROR_CODE_CONNECTION_REJECTED_DUE_TO_NO_SUITABLE_CHANNEL_FOUND); 541 } 542 connection->a2dp_source_state = A2DP_CONNECTED; 543 a2dp_source_sep_discovery_cid = 0; 544 a2dp_discover_seps_with_next_waiting_connection(); 545 #endif 546 } 547 break; 548 549 case AVDTP_SUBEVENT_SIGNALING_DELAY_REPORT: 550 cid = avdtp_subevent_signaling_delay_report_get_avdtp_cid(packet); 551 connection = avdtp_get_connection_for_avdtp_cid(cid); 552 btstack_assert(connection != NULL); 553 554 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_SIGNALING_DELAY_REPORT); 555 break; 556 557 // forward codec configuration 558 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION: 559 local_seid = avdtp_subevent_signaling_media_codec_sbc_configuration_get_local_seid(packet); 560 a2dp_handle_received_configuration(packet, local_seid); 561 a2dp_replace_subevent_id_and_emit_source(packet, size, 562 A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION); 563 break; 564 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AUDIO_CONFIGURATION: 565 local_seid = avdtp_subevent_signaling_media_codec_mpeg_audio_configuration_get_local_seid(packet); 566 a2dp_handle_received_configuration(packet, local_seid); 567 a2dp_replace_subevent_id_and_emit_source(packet, size, 568 A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AUDIO_CONFIGURATION); 569 break; 570 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AAC_CONFIGURATION: 571 local_seid = avdtp_subevent_signaling_media_codec_mpeg_aac_configuration_get_local_seid(packet); 572 a2dp_handle_received_configuration(packet, local_seid); 573 a2dp_replace_subevent_id_and_emit_source(packet, size, 574 A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AAC_CONFIGURATION); 575 break; 576 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_ATRAC_CONFIGURATION: 577 local_seid = avdtp_subevent_signaling_media_codec_atrac_configuration_get_local_seid(packet); 578 a2dp_handle_received_configuration(packet, local_seid); 579 a2dp_replace_subevent_id_and_emit_source(packet, size, 580 A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_ATRAC_CONFIGURATION); 581 break; 582 case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION: 583 local_seid = avdtp_subevent_signaling_media_codec_sbc_configuration_get_local_seid(packet); 584 a2dp_handle_received_configuration(packet, local_seid); 585 a2dp_replace_subevent_id_and_emit_source(packet, size, 586 A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION); 587 break; 588 589 case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 590 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW); 591 break; 592 593 case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED: 594 cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet); 595 connection = avdtp_get_connection_for_avdtp_cid(cid); 596 btstack_assert(connection != NULL); 597 598 if (connection->a2dp_source_state != A2DP_W4_OPEN_STREAM_WITH_SEID) break; 599 600 connection->a2dp_source_outgoing_active = false; 601 status = avdtp_subevent_streaming_connection_established_get_status(packet); 602 if (status != ERROR_CODE_SUCCESS){ 603 log_info("A2DP source streaming connection could not be established, avdtp_cid 0x%02x, status 0x%02x ---", cid, status); 604 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_STREAM_ESTABLISHED); 605 break; 606 } 607 608 log_info("A2DP source streaming connection established --- avdtp_cid 0x%02x, local seid 0x%02x, remote seid 0x%02x", cid, 609 avdtp_subevent_streaming_connection_established_get_local_seid(packet), 610 avdtp_subevent_streaming_connection_established_get_remote_seid(packet)); 611 connection->a2dp_source_state = A2DP_STREAMING_OPENED; 612 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_STREAM_ESTABLISHED); 613 break; 614 615 case AVDTP_SUBEVENT_SIGNALING_ACCEPT: 616 cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet); 617 connection = avdtp_get_connection_for_avdtp_cid(cid); 618 btstack_assert(connection != NULL); 619 620 // restart set config timer while remote is active for current cid 621 if (a2dp_source_set_config_timer_active && 622 (avdtp_subevent_signaling_accept_get_is_initiator(packet) == 0) && 623 (cid == a2dp_source_sep_discovery_cid)){ 624 625 a2dp_source_set_config_timer_restart(); 626 break; 627 } 628 629 signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet); 630 631 log_info("A2DP cmd %s accepted, global state %d, cid 0x%02x", avdtp_si2str(signal_identifier), connection->a2dp_source_state, cid); 632 633 switch (connection->a2dp_source_state){ 634 case A2DP_GET_CAPABILITIES: 635 remote_seid = a2dp_source_sep_discovery_seps[a2dp_source_sep_discovery_index].seid; 636 log_info("A2DP get capabilities for remote seid 0x%02x", remote_seid); 637 avdtp_source_get_all_capabilities(cid, remote_seid); 638 return; 639 640 case A2DP_SET_CONFIGURATION: 641 a2dp_source_set_config(connection); 642 return; 643 644 case A2DP_W2_OPEN_STREAM_WITH_SEID: 645 log_info("A2DP open stream ... local seid 0x%02x, active remote seid 0x%02x", avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), connection->a2dp_source_local_stream_endpoint->remote_sep.seid); 646 connection->a2dp_source_state = A2DP_W4_OPEN_STREAM_WITH_SEID; 647 avdtp_source_open_stream(cid, avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), connection->a2dp_source_local_stream_endpoint->remote_sep.seid); 648 break; 649 650 case A2DP_W2_RECONFIGURE_WITH_SEID: 651 log_info("A2DP reconfigured ... local seid 0x%02x, active remote seid 0x%02x", avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), connection->a2dp_source_local_stream_endpoint->remote_sep.seid); 652 a2dp_signaling_emit_reconfigured(cid, avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), ERROR_CODE_SUCCESS); 653 connection->a2dp_source_state = A2DP_STREAMING_OPENED; 654 break; 655 656 case A2DP_STREAMING_OPENED: 657 switch (signal_identifier){ 658 case AVDTP_SI_START: 659 a2dp_emit_source_stream_event(cid, avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), A2DP_SUBEVENT_STREAM_STARTED); 660 break; 661 case AVDTP_SI_SUSPEND: 662 a2dp_emit_source_stream_event(cid, avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), A2DP_SUBEVENT_STREAM_SUSPENDED); 663 break; 664 case AVDTP_SI_ABORT: 665 case AVDTP_SI_CLOSE: 666 a2dp_emit_source_stream_event(cid, avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), A2DP_SUBEVENT_STREAM_STOPPED); 667 break; 668 default: 669 break; 670 } 671 break; 672 673 default: 674 break; 675 } 676 break; 677 678 case AVDTP_SUBEVENT_SIGNALING_REJECT: 679 cid = avdtp_subevent_signaling_reject_get_avdtp_cid(packet); 680 connection = avdtp_get_connection_for_avdtp_cid(cid); 681 btstack_assert(connection != NULL); 682 683 if (avdtp_subevent_signaling_reject_get_is_initiator(packet) == 0) break; 684 685 switch (connection->a2dp_source_state) { 686 case A2DP_W2_RECONFIGURE_WITH_SEID: 687 log_info("A2DP reconfigure failed ... local seid 0x%02x, active remote seid 0x%02x", avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), connection->a2dp_source_local_stream_endpoint->remote_sep.seid); 688 a2dp_signaling_emit_reconfigured(cid, avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), ERROR_CODE_UNSPECIFIED_ERROR); 689 connection->a2dp_source_state = A2DP_STREAMING_OPENED; 690 break; 691 default: 692 connection->a2dp_source_state = A2DP_CONNECTED; 693 break; 694 } 695 696 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_COMMAND_REJECTED); 697 break; 698 699 case AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT: 700 cid = avdtp_subevent_signaling_general_reject_get_avdtp_cid(packet); 701 connection = avdtp_get_connection_for_avdtp_cid(cid); 702 btstack_assert(connection != NULL); 703 704 if (avdtp_subevent_signaling_general_reject_get_is_initiator(packet) == 0) break; 705 706 connection->a2dp_source_state = A2DP_CONNECTED; 707 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_COMMAND_REJECTED); 708 break; 709 710 case AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED: 711 cid = avdtp_subevent_streaming_connection_released_get_avdtp_cid(packet); 712 connection = avdtp_get_connection_for_avdtp_cid(cid); 713 btstack_assert(connection != NULL); 714 715 connection->a2dp_source_state = A2DP_CONFIGURED; 716 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_STREAM_RELEASED); 717 break; 718 719 case AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: 720 cid = avdtp_subevent_signaling_connection_released_get_avdtp_cid(packet); 721 connection = avdtp_get_connection_for_avdtp_cid(cid); 722 btstack_assert(connection != NULL); 723 724 // connect/release are passed on to app 725 if (a2dp_source_sep_discovery_cid == cid){ 726 a2dp_source_set_config_timer_stop(); 727 connection->a2dp_source_stream_endpoint_configured = false; 728 connection->a2dp_source_local_stream_endpoint = NULL; 729 730 connection->a2dp_source_state = A2DP_IDLE; 731 a2dp_source_sep_discovery_cid = 0; 732 } 733 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED); 734 break; 735 736 default: 737 break; 738 } 739 } 740 void a2dp_source_register_packet_handler(btstack_packet_handler_t callback){ 741 btstack_assert(callback != NULL); 742 743 avdtp_source_register_packet_handler(&a2dp_source_packet_handler_internal); 744 a2dp_register_source_packet_handler(callback); 745 } 746 747 void a2dp_source_init(void){ 748 a2dp_init(); 749 avdtp_source_init(); 750 } 751 752 void a2dp_source_deinit(void){ 753 a2dp_deinit(); 754 avdtp_source_deinit(); 755 a2dp_source_media_config_validator = NULL; 756 a2dp_source_sep_discovery_cid = 0; 757 } 758 759 avdtp_stream_endpoint_t * a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, 760 const uint8_t *codec_capabilities, uint16_t codec_capabilities_len, 761 uint8_t * codec_configuration, uint16_t codec_configuration_len){ 762 avdtp_stream_endpoint_t * stream_endpoint = avdtp_source_create_stream_endpoint(AVDTP_SOURCE, media_type); 763 if (!stream_endpoint){ 764 return NULL; 765 } 766 avdtp_source_register_media_transport_category(avdtp_stream_endpoint_seid(stream_endpoint)); 767 avdtp_source_register_media_codec_category(avdtp_stream_endpoint_seid(stream_endpoint), media_type, media_codec_type, 768 codec_capabilities, codec_capabilities_len); 769 avdtp_source_register_delay_reporting_category(avdtp_stream_endpoint_seid(stream_endpoint)); 770 771 // store user codec configuration buffer 772 stream_endpoint->media_codec_type = media_codec_type; 773 stream_endpoint->media_codec_configuration_info = codec_configuration; 774 stream_endpoint->media_codec_configuration_len = codec_configuration_len; 775 776 return stream_endpoint; 777 } 778 779 void a2dp_source_finalize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint){ 780 avdtp_source_finalize_stream_endpoint(stream_endpoint); 781 } 782 783 uint8_t a2dp_source_establish_stream(bd_addr_t remote_addr, uint16_t *avdtp_cid) { 784 785 uint16_t outgoing_cid; 786 787 avdtp_connection_t * connection = avdtp_get_connection_for_bd_addr(remote_addr); 788 if (connection == NULL){ 789 uint8_t status = avdtp_source_connect(remote_addr, &outgoing_cid); 790 if (status != ERROR_CODE_SUCCESS) { 791 // if there's already a connection for for remote addr, avdtp_source_connect fails, 792 // but the stream will get set-up nevertheless 793 return status; 794 } 795 connection = avdtp_get_connection_for_avdtp_cid(outgoing_cid); 796 btstack_assert(connection != NULL); 797 798 // setup state 799 connection->a2dp_source_outgoing_active = true; 800 connection->a2dp_source_state = A2DP_W4_CONNECTED; 801 *avdtp_cid = outgoing_cid; 802 803 } else { 804 if (connection->a2dp_source_outgoing_active || connection->a2dp_source_stream_endpoint_configured) { 805 return ERROR_CODE_COMMAND_DISALLOWED; 806 } 807 808 // check state 809 switch (connection->a2dp_source_state){ 810 case A2DP_IDLE: 811 case A2DP_CONNECTED: 812 // restart process e.g. if there no suitable stream endpoints or they had been in use 813 connection->a2dp_source_outgoing_active = true; 814 *avdtp_cid = connection->avdtp_cid; 815 a2dp_source_ready_for_sep_discovery(connection); 816 break; 817 default: 818 return ERROR_CODE_COMMAND_DISALLOWED; 819 } 820 } 821 return ERROR_CODE_SUCCESS; 822 } 823 824 uint8_t a2dp_source_disconnect(uint16_t avdtp_cid){ 825 return avdtp_disconnect(avdtp_cid); 826 } 827 828 829 uint8_t a2dp_source_start_stream(uint16_t avdtp_cid, uint8_t local_seid){ 830 return avdtp_start_stream(avdtp_cid, local_seid); 831 } 832 833 uint8_t a2dp_source_pause_stream(uint16_t avdtp_cid, uint8_t local_seid){ 834 return avdtp_suspend_stream(avdtp_cid, local_seid); 835 } 836 837 void a2dp_source_stream_endpoint_request_can_send_now(uint16_t avdtp_cid, uint8_t local_seid){ 838 avdtp_source_stream_endpoint_request_can_send_now(avdtp_cid, local_seid); 839 } 840 841 int a2dp_max_media_payload_size(uint16_t avdtp_cid, uint8_t local_seid){ 842 return avdtp_max_media_payload_size(avdtp_cid, local_seid); 843 } 844 845 int a2dp_source_stream_send_media_payload(uint16_t avdtp_cid, uint8_t local_seid, uint8_t * storage, int num_bytes_to_copy, uint8_t num_frames, uint8_t marker){ 846 return avdtp_source_stream_send_media_payload(avdtp_cid, local_seid, storage, num_bytes_to_copy, num_frames, marker); 847 } 848 849 uint8_t a2dp_source_stream_send_media_payload_rtp(uint16_t a2dp_cid, uint8_t local_seid, uint8_t marker, uint8_t * payload, uint16_t payload_size){ 850 return avdtp_source_stream_send_media_payload_rtp(a2dp_cid, local_seid, marker, payload, payload_size); 851 } 852 853 uint8_t a2dp_source_stream_send_media_packet(uint16_t a2dp_cid, uint8_t local_seid, const uint8_t * packet, uint16_t size){ 854 return avdtp_source_stream_send_media_packet(a2dp_cid, local_seid, packet, size); 855 } 856 857 static uint8_t a2dp_source_config_init(avdtp_connection_t *connection, uint8_t local_seid, uint8_t remote_seid, 858 avdtp_media_codec_type_t codec_type) { 859 860 // check state 861 switch (connection->a2dp_source_state){ 862 case A2DP_DISCOVERY_DONE: 863 case A2DP_GET_CAPABILITIES: 864 break; 865 default: 866 return ERROR_CODE_COMMAND_DISALLOWED; 867 } 868 869 // lookup local stream endpoint 870 avdtp_stream_endpoint_t * stream_endpoint = avdtp_get_stream_endpoint_for_seid(local_seid); 871 if (stream_endpoint == NULL){ 872 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 873 } 874 875 // lookup remote stream endpoint 876 avdtp_sep_t * remote_sep = NULL; 877 uint8_t i; 878 for (i=0; i < a2dp_source_sep_discovery_count; i++){ 879 if (a2dp_source_sep_discovery_seps[i].seid == remote_seid){ 880 remote_sep = &a2dp_source_sep_discovery_seps[i]; 881 } 882 } 883 if (remote_sep == NULL){ 884 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 885 } 886 887 // set media configuration 888 stream_endpoint->remote_configuration_bitmap = store_bit16(stream_endpoint->remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1); 889 stream_endpoint->remote_configuration.media_codec.media_type = AVDTP_AUDIO; 890 stream_endpoint->remote_configuration.media_codec.media_codec_type = codec_type; 891 // remote seid to use 892 stream_endpoint->set_config_remote_seid = remote_seid; 893 // enable delay reporting if supported 894 if (remote_sep->registered_service_categories & (1<<AVDTP_DELAY_REPORTING)){ 895 stream_endpoint->remote_configuration_bitmap = store_bit16(stream_endpoint->remote_configuration_bitmap, AVDTP_DELAY_REPORTING, 1); 896 } 897 898 // suitable Sink stream endpoint found, configure it 899 connection->a2dp_source_local_stream_endpoint = stream_endpoint; 900 connection->a2dp_source_have_config = true; 901 902 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 903 // continue outgoing configuration 904 if (connection->a2dp_source_state == A2DP_DISCOVERY_DONE){ 905 connection->a2dp_source_state = A2DP_SET_CONFIGURATION; 906 } 907 #endif 908 909 return ERROR_CODE_SUCCESS; 910 } 911 912 uint8_t a2dp_source_set_config_sbc(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, const avdtp_configuration_sbc_t * configuration){ 913 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 914 if (connection == NULL){ 915 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 916 } 917 918 uint8_t status = a2dp_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_SBC); 919 if (status != 0) { 920 return status; 921 } 922 // set config in reserved buffer 923 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *) connection->a2dp_source_local_stream_endpoint->media_codec_info; 924 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 4; 925 avdtp_config_sbc_store(connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 926 927 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 928 a2dp_source_set_config(connection); 929 #endif 930 931 return ERROR_CODE_SUCCESS; 932 } 933 934 uint8_t a2dp_source_set_config_mpeg_audio(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, const avdtp_configuration_mpeg_audio_t * configuration){ 935 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 936 if (connection == NULL){ 937 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 938 } 939 940 uint8_t status = a2dp_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_MPEG_1_2_AUDIO); 941 if (status != 0) { 942 return status; 943 } 944 945 // set config in reserved buffer 946 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *)connection->a2dp_source_local_stream_endpoint->media_codec_info; 947 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 4; 948 avdtp_config_mpeg_audio_store( connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 949 950 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 951 a2dp_source_set_config(connection); 952 #endif 953 954 return ERROR_CODE_SUCCESS; 955 } 956 957 uint8_t a2dp_source_set_config_mpeg_aac(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, const avdtp_configuration_mpeg_aac_t * configuration){ 958 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 959 if (connection == NULL){ 960 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 961 } 962 963 uint8_t status = a2dp_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_MPEG_2_4_AAC); 964 if (status != 0) { 965 return status; 966 } 967 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *) connection->a2dp_source_local_stream_endpoint->media_codec_info; 968 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 6; 969 avdtp_config_mpeg_aac_store( connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 970 971 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 972 a2dp_source_set_config(connection); 973 #endif 974 975 return ERROR_CODE_SUCCESS; 976 } 977 978 uint8_t a2dp_source_set_config_atrac(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, const avdtp_configuration_atrac_t * configuration){ 979 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 980 if (connection == NULL){ 981 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 982 } 983 984 uint8_t status = a2dp_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_ATRAC_FAMILY); 985 if (status != 0) { 986 return status; 987 } 988 989 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *) connection->a2dp_source_local_stream_endpoint->media_codec_info; 990 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 7; 991 avdtp_config_atrac_store( connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 992 993 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 994 a2dp_source_set_config(connection); 995 #endif 996 997 return ERROR_CODE_SUCCESS; 998 } 999 1000 uint8_t a2dp_source_set_config_other(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, 1001 const uint8_t * media_codec_information, uint8_t media_codec_information_len){ 1002 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 1003 if (connection == NULL){ 1004 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 1005 } 1006 1007 uint8_t status = a2dp_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_NON_A2DP); 1008 if (status != 0) { 1009 return status; 1010 } 1011 1012 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *) media_codec_information; 1013 connection->a2dp_source_local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = media_codec_information_len; 1014 1015 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 1016 a2dp_source_set_config(connection); 1017 #endif 1018 1019 return status; 1020 } 1021 1022 uint8_t a2dp_source_reconfigure_stream_sampling_frequency(uint16_t avdtp_cid, uint32_t sampling_frequency){ 1023 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(avdtp_cid); 1024 if (connection == NULL){ 1025 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 1026 } 1027 1028 if (connection->a2dp_source_state != A2DP_STREAMING_OPENED) { 1029 return ERROR_CODE_COMMAND_DISALLOWED; 1030 } 1031 1032 btstack_assert(connection->a2dp_source_local_stream_endpoint != NULL); 1033 1034 log_info("Reconfigure avdtp_cid 0x%02x", avdtp_cid); 1035 1036 avdtp_media_codec_type_t codec_type = connection->a2dp_source_local_stream_endpoint->sep.capabilities.media_codec.media_codec_type; 1037 uint8_t codec_info_len; 1038 switch (codec_type){ 1039 case AVDTP_CODEC_SBC: 1040 codec_info_len = 4; 1041 (void)memcpy(connection->a2dp_source_local_stream_endpoint->media_codec_info, connection->a2dp_source_local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information, codec_info_len); 1042 avdtp_config_sbc_set_sampling_frequency(connection->a2dp_source_local_stream_endpoint->media_codec_info, sampling_frequency); 1043 break; 1044 case AVDTP_CODEC_MPEG_1_2_AUDIO: 1045 codec_info_len = 4; 1046 (void)memcpy(connection->a2dp_source_local_stream_endpoint->media_codec_info, connection->a2dp_source_local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information, codec_info_len); 1047 avdtp_config_mpeg_audio_set_sampling_frequency(connection->a2dp_source_local_stream_endpoint->media_codec_info, sampling_frequency); 1048 break; 1049 case AVDTP_CODEC_MPEG_2_4_AAC: 1050 codec_info_len = 6; 1051 (void)memcpy(connection->a2dp_source_local_stream_endpoint->media_codec_info, connection->a2dp_source_local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information, codec_info_len); 1052 avdtp_config_mpeg_aac_set_sampling_frequency(connection->a2dp_source_local_stream_endpoint->media_codec_info, sampling_frequency); 1053 break; 1054 case AVDTP_CODEC_ATRAC_FAMILY: 1055 codec_info_len = 7; 1056 (void)memcpy(connection->a2dp_source_local_stream_endpoint->media_codec_info, connection->a2dp_source_local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information, codec_info_len); 1057 avdtp_config_atrac_set_sampling_frequency(connection->a2dp_source_local_stream_endpoint->media_codec_info, sampling_frequency); 1058 break; 1059 default: 1060 return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; 1061 } 1062 1063 avdtp_capabilities_t new_configuration; 1064 new_configuration.media_codec.media_type = AVDTP_AUDIO; 1065 new_configuration.media_codec.media_codec_type = codec_type; 1066 new_configuration.media_codec.media_codec_information_len = codec_info_len; 1067 new_configuration.media_codec.media_codec_information = connection->a2dp_source_local_stream_endpoint->media_codec_info; 1068 1069 // start reconfigure 1070 connection->a2dp_source_state = A2DP_W2_RECONFIGURE_WITH_SEID; 1071 1072 return avdtp_source_reconfigure( 1073 avdtp_cid, 1074 avdtp_stream_endpoint_seid(connection->a2dp_source_local_stream_endpoint), 1075 connection->a2dp_source_local_stream_endpoint->remote_sep.seid, 1076 1 << AVDTP_MEDIA_CODEC, 1077 new_configuration 1078 ); 1079 } 1080 1081 static uint8_t a2dp_source_media_config_validator_callback(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size){ 1082 uint8_t error = 0; 1083 if (a2dp_source_media_config_validator != NULL) { 1084 // update subevent id and call validator 1085 uint8_t avdtp_subevent_id = event[2]; 1086 uint8_t a2dp_subevent_id = a2dp_subevent_id_for_avdtp_subevent_id(avdtp_subevent_id); 1087 uint8_t * subevent_field = (uint8_t *) &event[2]; 1088 *subevent_field = a2dp_subevent_id; 1089 error = (*a2dp_source_media_config_validator)(stream_endpoint, event, size); 1090 *subevent_field = avdtp_subevent_id; 1091 } 1092 return error; 1093 } 1094 1095 void a2dp_source_register_media_config_validator(uint8_t (*callback)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size)){ 1096 a2dp_source_media_config_validator = callback; 1097 avdtp_source_register_media_config_validator(&a2dp_source_media_config_validator_callback); 1098 } 1099 1100