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_source_config_process_avdtp_event_handler(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_source_ready_for_sep_discovery(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_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_SBC); 230 if (status != 0) { 231 return status; 232 } 233 // set config in reserved buffer 234 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; 235 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 4; 236 avdtp_config_sbc_store(connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 237 238 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 239 a2dp_source_set_config(connection); 240 #endif 241 242 return ERROR_CODE_SUCCESS; 243 } 244 245 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){ 246 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 247 if (connection == NULL){ 248 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 249 } 250 251 uint8_t status = a2dp_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_MPEG_1_2_AUDIO); 252 if (status != 0) { 253 return status; 254 } 255 256 // set config in reserved buffer 257 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; 258 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 4; 259 avdtp_config_mpeg_audio_store(connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 260 261 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 262 a2dp_source_set_config(connection); 263 #endif 264 265 return ERROR_CODE_SUCCESS; 266 } 267 268 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){ 269 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 270 if (connection == NULL){ 271 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 272 } 273 274 uint8_t status = a2dp_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_MPEG_2_4_AAC); 275 if (status != 0) { 276 return status; 277 } 278 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; 279 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 6; 280 avdtp_config_mpeg_aac_store(connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 281 282 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 283 a2dp_source_set_config(connection); 284 #endif 285 286 return ERROR_CODE_SUCCESS; 287 } 288 289 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){ 290 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 291 if (connection == NULL){ 292 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 293 } 294 295 uint8_t status = a2dp_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_ATRAC_FAMILY); 296 if (status != 0) { 297 return status; 298 } 299 300 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; 301 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 7; 302 avdtp_config_atrac_store(connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information, configuration); 303 304 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 305 a2dp_source_set_config(connection); 306 #endif 307 308 return ERROR_CODE_SUCCESS; 309 } 310 311 uint8_t a2dp_source_set_config_other(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, 312 const uint8_t * media_codec_information, uint8_t media_codec_information_len){ 313 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(a2dp_cid); 314 if (connection == NULL){ 315 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 316 } 317 318 uint8_t status = a2dp_source_config_init(connection, local_seid, remote_seid, AVDTP_CODEC_NON_A2DP); 319 if (status != 0) { 320 return status; 321 } 322 323 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information = (uint8_t *) media_codec_information; 324 connection->a2dp_source_config_process.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = media_codec_information_len; 325 326 #ifdef ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG 327 a2dp_source_set_config(connection); 328 #endif 329 330 return status; 331 } 332 333 uint8_t a2dp_source_reconfigure_stream_sampling_frequency(uint16_t avdtp_cid, uint32_t sampling_frequency){ 334 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(avdtp_cid); 335 if (connection == NULL){ 336 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 337 } 338 339 if (connection->a2dp_source_config_process.state != A2DP_STREAMING_OPENED) { 340 return ERROR_CODE_COMMAND_DISALLOWED; 341 } 342 343 btstack_assert(connection->a2dp_source_config_process.local_stream_endpoint != NULL); 344 345 log_info("Reconfigure avdtp_cid 0x%02x", avdtp_cid); 346 347 avdtp_media_codec_type_t codec_type = connection->a2dp_source_config_process.local_stream_endpoint->sep.capabilities.media_codec.media_codec_type; 348 uint8_t codec_info_len; 349 switch (codec_type){ 350 case AVDTP_CODEC_SBC: 351 codec_info_len = 4; 352 (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); 353 avdtp_config_sbc_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 354 break; 355 case AVDTP_CODEC_MPEG_1_2_AUDIO: 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_mpeg_audio_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 359 break; 360 case AVDTP_CODEC_MPEG_2_4_AAC: 361 codec_info_len = 6; 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_aac_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 364 break; 365 case AVDTP_CODEC_ATRAC_FAMILY: 366 codec_info_len = 7; 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_atrac_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 369 break; 370 default: 371 return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; 372 } 373 374 avdtp_capabilities_t new_configuration; 375 new_configuration.media_codec.media_type = AVDTP_AUDIO; 376 new_configuration.media_codec.media_codec_type = codec_type; 377 new_configuration.media_codec.media_codec_information_len = codec_info_len; 378 new_configuration.media_codec.media_codec_information = connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info; 379 380 // start reconfigure 381 connection->a2dp_source_config_process.state = A2DP_W2_RECONFIGURE_WITH_SEID; 382 383 return avdtp_source_reconfigure( 384 avdtp_cid, 385 avdtp_stream_endpoint_seid(connection->a2dp_source_config_process.local_stream_endpoint), 386 connection->a2dp_source_config_process.local_stream_endpoint->remote_sep.seid, 387 1 << AVDTP_MEDIA_CODEC, 388 new_configuration 389 ); 390 } 391 392 static uint8_t a2dp_source_media_config_validator_callback(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size){ 393 uint8_t error = 0; 394 if (a2dp_source_media_config_validator != NULL) { 395 // update subevent id and call validator 396 uint8_t avdtp_subevent_id = event[2]; 397 uint8_t a2dp_subevent_id = a2dp_subevent_id_for_avdtp_subevent_id(avdtp_subevent_id); 398 uint8_t * subevent_field = (uint8_t *) &event[2]; 399 *subevent_field = a2dp_subevent_id; 400 error = (*a2dp_source_media_config_validator)(stream_endpoint, event, size); 401 *subevent_field = avdtp_subevent_id; 402 } 403 return error; 404 } 405 406 void a2dp_source_register_media_config_validator(uint8_t (*callback)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size)){ 407 a2dp_source_media_config_validator = callback; 408 avdtp_source_register_media_config_validator(&a2dp_source_media_config_validator_callback); 409 } 410 411