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 static const char * a2dp_source_default_service_name = "BTstack A2DP Source Service"; 69 static const char * a2dp_default_source_service_provider_name = "BTstack A2DP Source Service Provider"; 70 71 static uint8_t (*a2dp_source_media_config_validator)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size); 72 73 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){ 74 if (service_provider_name == NULL){ 75 service_provider_name = a2dp_default_source_service_provider_name; 76 } 77 if (service_name == NULL){ 78 service_name = a2dp_source_default_service_name; 79 } 80 a2dp_create_sdp_record(service, service_record_handle, BLUETOOTH_SERVICE_CLASS_AUDIO_SOURCE, 81 supported_features, service_name, service_provider_name); 82 } 83 84 static void a2dp_source_packet_handler_internal(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 85 UNUSED(channel); 86 UNUSED(size); 87 88 if (packet_type != HCI_EVENT_PACKET) return; 89 if (hci_event_packet_get_type(packet) != HCI_EVENT_AVDTP_META) return; 90 91 switch (hci_event_avdtp_meta_get_subevent_code(packet)){ 92 93 case AVDTP_SUBEVENT_SIGNALING_DELAY_REPORT: 94 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_SIGNALING_DELAY_REPORT); 95 break; 96 97 case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 98 a2dp_replace_subevent_id_and_emit_source(packet, size, A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW); 99 break; 100 101 default: 102 // forward events to config process 103 a2dp_config_process_avdtp_event_handler(AVDTP_ROLE_SOURCE, packet, size); 104 break; 105 } 106 } 107 void a2dp_source_register_packet_handler(btstack_packet_handler_t callback){ 108 btstack_assert(callback != NULL); 109 110 avdtp_source_register_packet_handler(&a2dp_source_packet_handler_internal); 111 a2dp_register_source_packet_handler(callback); 112 } 113 114 void a2dp_source_init(void){ 115 a2dp_init(); 116 avdtp_source_init(); 117 } 118 119 void a2dp_source_deinit(void){ 120 a2dp_deinit(); 121 avdtp_source_deinit(); 122 a2dp_source_media_config_validator = NULL; 123 } 124 125 avdtp_stream_endpoint_t * a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, 126 const uint8_t *codec_capabilities, uint16_t codec_capabilities_len, 127 uint8_t * codec_configuration, uint16_t codec_configuration_len){ 128 avdtp_stream_endpoint_t * stream_endpoint = avdtp_source_create_stream_endpoint(AVDTP_SOURCE, media_type); 129 if (!stream_endpoint){ 130 return NULL; 131 } 132 avdtp_source_register_media_transport_category(avdtp_stream_endpoint_seid(stream_endpoint)); 133 avdtp_source_register_media_codec_category(avdtp_stream_endpoint_seid(stream_endpoint), media_type, media_codec_type, 134 codec_capabilities, codec_capabilities_len); 135 avdtp_source_register_delay_reporting_category(avdtp_stream_endpoint_seid(stream_endpoint)); 136 137 // store user codec configuration buffer 138 stream_endpoint->media_codec_type = media_codec_type; 139 stream_endpoint->media_codec_configuration_info = codec_configuration; 140 stream_endpoint->media_codec_configuration_len = codec_configuration_len; 141 142 return stream_endpoint; 143 } 144 145 void a2dp_source_finalize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint){ 146 avdtp_source_finalize_stream_endpoint(stream_endpoint); 147 } 148 149 uint8_t a2dp_source_establish_stream(bd_addr_t remote_addr, uint16_t *avdtp_cid) { 150 151 uint16_t outgoing_cid; 152 153 avdtp_connection_t * connection = avdtp_get_connection_for_bd_addr(remote_addr); 154 if (connection == NULL){ 155 uint8_t status = avdtp_source_connect(remote_addr, &outgoing_cid); 156 if (status != ERROR_CODE_SUCCESS) { 157 // if there's already a connection for for remote addr, avdtp_source_connect fails, 158 // but the stream will get set-up nevertheless 159 return status; 160 } 161 connection = avdtp_get_connection_for_avdtp_cid(outgoing_cid); 162 btstack_assert(connection != NULL); 163 164 // setup state 165 connection->a2dp_source_config_process.outgoing_active = true; 166 connection->a2dp_source_config_process.state = A2DP_W4_CONNECTED; 167 *avdtp_cid = outgoing_cid; 168 169 } else { 170 if (connection->a2dp_source_config_process.outgoing_active || connection->a2dp_source_config_process.stream_endpoint_configured) { 171 return ERROR_CODE_COMMAND_DISALLOWED; 172 } 173 174 // check state 175 switch (connection->a2dp_source_config_process.state){ 176 case A2DP_IDLE: 177 case A2DP_CONNECTED: 178 // restart process e.g. if there no suitable stream endpoints or they had been in use 179 connection->a2dp_source_config_process.outgoing_active = true; 180 *avdtp_cid = connection->avdtp_cid; 181 a2dp_config_process_ready_for_sep_discovery(AVDTP_ROLE_SOURCE, connection); 182 break; 183 default: 184 return ERROR_CODE_COMMAND_DISALLOWED; 185 } 186 } 187 return ERROR_CODE_SUCCESS; 188 } 189 190 uint8_t a2dp_source_disconnect(uint16_t avdtp_cid){ 191 return avdtp_disconnect(avdtp_cid); 192 } 193 194 uint8_t a2dp_source_start_stream(uint16_t avdtp_cid, uint8_t local_seid){ 195 return avdtp_start_stream(avdtp_cid, local_seid); 196 } 197 198 uint8_t a2dp_source_pause_stream(uint16_t avdtp_cid, uint8_t local_seid){ 199 return avdtp_suspend_stream(avdtp_cid, local_seid); 200 } 201 202 void a2dp_source_stream_endpoint_request_can_send_now(uint16_t avdtp_cid, uint8_t local_seid){ 203 avdtp_source_stream_endpoint_request_can_send_now(avdtp_cid, local_seid); 204 } 205 206 int a2dp_max_media_payload_size(uint16_t avdtp_cid, uint8_t local_seid){ 207 return avdtp_max_media_payload_size(avdtp_cid, local_seid); 208 } 209 210 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){ 211 return avdtp_source_stream_send_media_payload(avdtp_cid, local_seid, storage, num_bytes_to_copy, num_frames, marker); 212 } 213 214 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){ 215 return avdtp_source_stream_send_media_payload_rtp(a2dp_cid, local_seid, marker, payload, payload_size); 216 } 217 218 uint8_t a2dp_source_stream_send_media_packet(uint16_t a2dp_cid, uint8_t local_seid, const uint8_t * packet, uint16_t size){ 219 return avdtp_source_stream_send_media_packet(a2dp_cid, local_seid, packet, size); 220 } 221 222 223 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){ 224 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 225 if (connection == NULL){ 226 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 227 } 228 229 uint8_t status = a2dp_config_process_config_init(AVDTP_ROLE_SOURCE, connection, local_seid, remote_seid, 230 AVDTP_CODEC_SBC); 231 if (status != 0) { 232 return status; 233 } 234 // set config in reserved buffer 235 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *) connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info; 236 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 4; 237 avdtp_config_sbc_store(connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 238 239 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 240 a2dp_config_process_set_config(AVDTP_ROLE_SOURCE, connection); 241 #endif 242 243 return ERROR_CODE_SUCCESS; 244 } 245 246 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){ 247 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 248 if (connection == NULL){ 249 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 250 } 251 252 uint8_t status = a2dp_config_process_config_init(AVDTP_ROLE_SOURCE, connection, local_seid, remote_seid, 253 AVDTP_CODEC_MPEG_1_2_AUDIO); 254 if (status != 0) { 255 return status; 256 } 257 258 // set config in reserved buffer 259 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *)connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info; 260 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 4; 261 avdtp_config_mpeg_audio_store(connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 262 263 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 264 a2dp_config_process_set_config(AVDTP_ROLE_SOURCE, connection); 265 #endif 266 267 return ERROR_CODE_SUCCESS; 268 } 269 270 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){ 271 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 272 if (connection == NULL){ 273 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 274 } 275 276 uint8_t status = a2dp_config_process_config_init(AVDTP_ROLE_SOURCE, connection, local_seid, remote_seid, 277 AVDTP_CODEC_MPEG_2_4_AAC); 278 if (status != 0) { 279 return status; 280 } 281 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *) connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info; 282 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 6; 283 avdtp_config_mpeg_aac_store(connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 284 285 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 286 a2dp_config_process_set_config(AVDTP_ROLE_SOURCE, connection); 287 #endif 288 289 return ERROR_CODE_SUCCESS; 290 } 291 292 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){ 293 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 294 if (connection == NULL){ 295 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 296 } 297 298 uint8_t status = a2dp_config_process_config_init(AVDTP_ROLE_SOURCE, connection, local_seid, remote_seid, 299 AVDTP_CODEC_ATRAC_FAMILY); 300 if (status != 0) { 301 return status; 302 } 303 304 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *) connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info; 305 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 7; 306 avdtp_config_atrac_store(connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 307 308 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 309 a2dp_config_process_set_config(AVDTP_ROLE_SOURCE, connection); 310 #endif 311 312 return ERROR_CODE_SUCCESS; 313 } 314 315 uint8_t a2dp_source_set_config_other(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, 316 const uint8_t * media_codec_information, uint8_t media_codec_information_len){ 317 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 318 if (connection == NULL){ 319 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 320 } 321 322 uint8_t status = a2dp_config_process_config_init(AVDTP_ROLE_SOURCE, connection, local_seid, remote_seid, 323 AVDTP_CODEC_NON_A2DP); 324 if (status != 0) { 325 return status; 326 } 327 328 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *) media_codec_information; 329 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = media_codec_information_len; 330 331 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 332 a2dp_config_process_set_config(AVDTP_ROLE_SOURCE, connection); 333 #endif 334 335 return status; 336 } 337 338 uint8_t a2dp_source_reconfigure_stream_sampling_frequency(uint16_t avdtp_cid, uint32_t sampling_frequency){ 339 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(avdtp_cid); 340 if (connection == NULL){ 341 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 342 } 343 344 if (connection->a2dp_source_config_process.state != A2DP_STREAMING_OPENED) { 345 return ERROR_CODE_COMMAND_DISALLOWED; 346 } 347 348 btstack_assert(connection->a2dp_source_config_process.local_stream_endpoint != NULL); 349 350 log_info("Reconfigure avdtp_cid 0x%02x", avdtp_cid); 351 352 avdtp_media_codec_type_t codec_type = connection->a2dp_source_config_process.local_stream_endpoint->sep.capabilities.media_codec.media_codec_type; 353 uint8_t codec_info_len; 354 switch (codec_type){ 355 case AVDTP_CODEC_SBC: 356 codec_info_len = 4; 357 (void)memcpy(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, connection->a2dp_source_config_process.local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information, codec_info_len); 358 avdtp_config_sbc_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 359 break; 360 case AVDTP_CODEC_MPEG_1_2_AUDIO: 361 codec_info_len = 4; 362 (void)memcpy(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, connection->a2dp_source_config_process.local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information, codec_info_len); 363 avdtp_config_mpeg_audio_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 364 break; 365 case AVDTP_CODEC_MPEG_2_4_AAC: 366 codec_info_len = 6; 367 (void)memcpy(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, connection->a2dp_source_config_process.local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information, codec_info_len); 368 avdtp_config_mpeg_aac_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 369 break; 370 case AVDTP_CODEC_ATRAC_FAMILY: 371 codec_info_len = 7; 372 (void)memcpy(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, connection->a2dp_source_config_process.local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information, codec_info_len); 373 avdtp_config_atrac_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 374 break; 375 default: 376 return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; 377 } 378 379 avdtp_capabilities_t new_configuration; 380 new_configuration.media_codec.media_type = AVDTP_AUDIO; 381 new_configuration.media_codec.media_codec_type = codec_type; 382 new_configuration.media_codec.media_codec_information_len = codec_info_len; 383 new_configuration.media_codec.media_codec_information = connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info; 384 385 // start reconfigure 386 connection->a2dp_source_config_process.state = A2DP_W2_RECONFIGURE_WITH_SEID; 387 388 return avdtp_source_reconfigure( 389 avdtp_cid, 390 avdtp_stream_endpoint_seid(connection->a2dp_source_config_process.local_stream_endpoint), 391 connection->a2dp_source_config_process.local_stream_endpoint->remote_sep.seid, 392 1 << AVDTP_MEDIA_CODEC, 393 new_configuration 394 ); 395 } 396 397 static uint8_t a2dp_source_media_config_validator_callback(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size){ 398 uint8_t error = 0; 399 if (a2dp_source_media_config_validator != NULL) { 400 // update subevent id and call validator 401 uint8_t avdtp_subevent_id = event[2]; 402 uint8_t a2dp_subevent_id = a2dp_subevent_id_for_avdtp_subevent_id(avdtp_subevent_id); 403 uint8_t * subevent_field = (uint8_t *) &event[2]; 404 *subevent_field = a2dp_subevent_id; 405 error = (*a2dp_source_media_config_validator)(stream_endpoint, event, size); 406 *subevent_field = avdtp_subevent_id; 407 } 408 return error; 409 } 410 411 void a2dp_source_register_media_config_validator(uint8_t (*callback)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size)){ 412 a2dp_source_media_config_validator = callback; 413 avdtp_source_register_media_config_validator(&a2dp_source_media_config_validator_callback); 414 } 415 416