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 uint8_t 211 a2dp_source_stream_send_media_payload_rtp(uint16_t a2dp_cid, uint8_t local_seid, uint8_t marker, uint32_t timestamp, 212 uint8_t *payload, uint16_t payload_size) { 213 return avdtp_source_stream_send_media_payload_rtp(a2dp_cid, local_seid, marker, timestamp, payload, payload_size); 214 } 215 216 uint8_t a2dp_source_stream_send_media_packet(uint16_t a2dp_cid, uint8_t local_seid, const uint8_t * packet, uint16_t size){ 217 return avdtp_source_stream_send_media_packet(a2dp_cid, local_seid, packet, size); 218 } 219 220 221 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){ 222 return a2dp_config_process_set_sbc(AVDTP_ROLE_SOURCE, a2dp_cid, local_seid, remote_seid, configuration); 223 } 224 225 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){ 226 return a2dp_config_process_set_mpeg_audio(AVDTP_ROLE_SOURCE, a2dp_cid, local_seid, remote_seid, configuration); 227 } 228 229 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){ 230 return a2dp_config_process_set_mpeg_aac(AVDTP_ROLE_SOURCE, a2dp_cid, local_seid, remote_seid, configuration); 231 } 232 233 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){ 234 return a2dp_config_process_set_atrac(AVDTP_ROLE_SOURCE, a2dp_cid, local_seid, remote_seid, configuration); 235 } 236 237 uint8_t a2dp_source_set_config_other(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, 238 const uint8_t * media_codec_information, uint8_t media_codec_information_len){ 239 return a2dp_config_process_set_other(AVDTP_ROLE_SOURCE, a2dp_cid, local_seid, remote_seid, media_codec_information, media_codec_information_len); 240 } 241 242 uint8_t a2dp_source_reconfigure_stream_sampling_frequency(uint16_t avdtp_cid, uint32_t sampling_frequency){ 243 avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(avdtp_cid); 244 if (connection == NULL){ 245 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 246 } 247 248 if (connection->a2dp_source_config_process.state != A2DP_STREAMING_OPENED) { 249 return ERROR_CODE_COMMAND_DISALLOWED; 250 } 251 252 btstack_assert(connection->a2dp_source_config_process.local_stream_endpoint != NULL); 253 254 log_info("Reconfigure avdtp_cid 0x%02x", avdtp_cid); 255 256 avdtp_media_codec_type_t codec_type = connection->a2dp_source_config_process.local_stream_endpoint->sep.capabilities.media_codec.media_codec_type; 257 uint8_t codec_info_len; 258 switch (codec_type){ 259 case AVDTP_CODEC_SBC: 260 codec_info_len = 4; 261 (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); 262 avdtp_config_sbc_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 263 break; 264 case AVDTP_CODEC_MPEG_1_2_AUDIO: 265 codec_info_len = 4; 266 (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); 267 avdtp_config_mpeg_audio_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 268 break; 269 case AVDTP_CODEC_MPEG_2_4_AAC: 270 codec_info_len = 6; 271 (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); 272 avdtp_config_mpeg_aac_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 273 break; 274 case AVDTP_CODEC_ATRAC_FAMILY: 275 codec_info_len = 7; 276 (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); 277 avdtp_config_atrac_set_sampling_frequency(connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info, sampling_frequency); 278 break; 279 default: 280 return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; 281 } 282 283 avdtp_capabilities_t new_configuration; 284 new_configuration.media_codec.media_type = AVDTP_AUDIO; 285 new_configuration.media_codec.media_codec_type = codec_type; 286 new_configuration.media_codec.media_codec_information_len = codec_info_len; 287 new_configuration.media_codec.media_codec_information = connection->a2dp_source_config_process.local_stream_endpoint->media_codec_info; 288 289 // start reconfigure 290 connection->a2dp_source_config_process.state = A2DP_W2_RECONFIGURE_WITH_SEID; 291 292 return avdtp_source_reconfigure( 293 avdtp_cid, 294 avdtp_stream_endpoint_seid(connection->a2dp_source_config_process.local_stream_endpoint), 295 connection->a2dp_source_config_process.local_stream_endpoint->remote_sep.seid, 296 1 << AVDTP_MEDIA_CODEC, 297 new_configuration 298 ); 299 } 300 301 static uint8_t a2dp_source_media_config_validator_callback(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size){ 302 uint8_t error = 0; 303 if (a2dp_source_media_config_validator != NULL) { 304 // update subevent id and call validator 305 uint8_t avdtp_subevent_id = event[2]; 306 uint8_t a2dp_subevent_id = a2dp_subevent_id_for_avdtp_subevent_id(avdtp_subevent_id); 307 uint8_t * subevent_field = (uint8_t *) &event[2]; 308 *subevent_field = a2dp_subevent_id; 309 error = (*a2dp_source_media_config_validator)(stream_endpoint, event, size); 310 *subevent_field = avdtp_subevent_id; 311 } 312 return error; 313 } 314 315 void a2dp_source_register_media_config_validator(uint8_t (*callback)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size)){ 316 a2dp_source_media_config_validator = callback; 317 avdtp_source_register_media_config_validator(&a2dp_source_media_config_validator_callback); 318 } 319 320