mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-03 16:14:11 +00:00
a2dp source: fix crash on outgoing connection after previous incoming one
The pointer to the user media codec configuration buffer was stored in stream_endpoint.remote_configuration, which was set to zero in avdtp_reset_stream_endpoint. The user buffer is now stored separately and it is updateds when the configuration gets set/updated. The field media_codec_sbc_info is used by a2dp configure and reconfigure.
This commit is contained in:
parent
44e638f3c1
commit
8276777316
@ -56,8 +56,6 @@ static bool outgoing_active = false;
|
||||
static uint16_t a2dp_sink_cid;
|
||||
static bool stream_endpoint_configured = false;
|
||||
|
||||
static avdtp_stream_endpoint_context_t sc;
|
||||
|
||||
static btstack_packet_handler_t a2dp_sink_packet_handler_user;
|
||||
|
||||
static void a2dp_sink_packet_handler_internal(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
@ -164,9 +162,9 @@ void a2dp_sink_init(void){
|
||||
avdtp_sink_init();
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * a2dp_sink_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
|
||||
uint8_t * codec_capabilities, uint16_t codec_capabilities_len,
|
||||
uint8_t * media_codec_info, uint16_t media_codec_info_len){
|
||||
avdtp_stream_endpoint_t * a2dp_sink_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
|
||||
uint8_t * codec_capabilities, uint16_t codec_capabilities_len,
|
||||
uint8_t * codec_configuration, uint16_t codec_configuration_len){
|
||||
avdtp_stream_endpoint_t * local_stream_endpoint = avdtp_sink_create_stream_endpoint(AVDTP_SINK, media_type);
|
||||
if (!local_stream_endpoint){
|
||||
return NULL;
|
||||
@ -174,9 +172,12 @@ avdtp_stream_endpoint_t * a2dp_sink_create_stream_endpoint(avdtp_media_type_t me
|
||||
avdtp_sink_register_media_transport_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
|
||||
avdtp_sink_register_media_codec_category(avdtp_stream_endpoint_seid(local_stream_endpoint), media_type, media_codec_type,
|
||||
codec_capabilities, codec_capabilities_len);
|
||||
local_stream_endpoint->remote_configuration.media_codec.media_codec_information = media_codec_info;
|
||||
local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = media_codec_info_len;
|
||||
avdtp_sink_register_delay_reporting_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
|
||||
avdtp_sink_register_delay_reporting_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
|
||||
|
||||
// store user codec configuration buffer
|
||||
local_stream_endpoint->media_codec_configuration_info = codec_configuration;
|
||||
local_stream_endpoint->media_codec_configuration_len = codec_configuration_len;
|
||||
|
||||
return local_stream_endpoint;
|
||||
}
|
||||
|
||||
@ -185,8 +186,8 @@ void a2dp_sink_finalize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoin
|
||||
}
|
||||
|
||||
uint8_t a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid, uint16_t * avdtp_cid){
|
||||
sc.local_stream_endpoint = avdtp_get_stream_endpoint_for_seid(local_seid);
|
||||
if (!sc.local_stream_endpoint){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_get_stream_endpoint_for_seid(local_seid);
|
||||
if (stream_endpoint == NULL){
|
||||
log_info("No local_stream_endpoint for seid %d", local_seid);
|
||||
return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
}
|
||||
|
@ -373,6 +373,7 @@ static void a2dp_source_packet_handler_internal(uint8_t packet_type, uint16_t ch
|
||||
connection = avdtp_get_connection_for_avdtp_cid(cid);
|
||||
btstack_assert(connection != NULL);
|
||||
|
||||
// choose SBC config params
|
||||
uint8_t sampling_frequency = avdtp_choose_sbc_sampling_frequency(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet));
|
||||
uint8_t channel_mode = avdtp_choose_sbc_channel_mode(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet));
|
||||
uint8_t block_length = avdtp_choose_sbc_block_length(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet));
|
||||
@ -382,16 +383,21 @@ static void a2dp_source_packet_handler_internal(uint8_t packet_type, uint16_t ch
|
||||
uint8_t max_bitpool_value = avdtp_choose_sbc_max_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet));
|
||||
uint8_t min_bitpool_value = avdtp_choose_sbc_min_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet));
|
||||
|
||||
// set media configuration
|
||||
sc.local_stream_endpoint->remote_configuration_bitmap = store_bit16(sc.local_stream_endpoint->remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_type = AVDTP_AUDIO;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
|
||||
|
||||
// select reserved SBC config buffer
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information = sc.local_stream_endpoint->media_codec_sbc_info;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = 4;
|
||||
|
||||
// store SBC configuration in reserved field
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[0] = (sampling_frequency << 4) | channel_mode;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[1] = (block_length << 4) | (subbands << 2) | allocation_method;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[2] = min_bitpool_value;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[3] = max_bitpool_value;
|
||||
|
||||
sc.local_stream_endpoint->remote_configuration_bitmap = store_bit16(sc.local_stream_endpoint->remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_type = AVDTP_AUDIO;
|
||||
sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
|
||||
|
||||
// suitable Sink SEP found, configure SEP
|
||||
sep_found_w2_set_configuration = true;
|
||||
connection->supported_codecs_bitmap |= (1 << AVDTP_CODEC_SBC);
|
||||
@ -635,9 +641,9 @@ void a2dp_source_init(void){
|
||||
avdtp_source_init();
|
||||
}
|
||||
|
||||
avdtp_stream_endpoint_t * a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
|
||||
uint8_t * codec_capabilities, uint16_t codec_capabilities_len,
|
||||
uint8_t * media_codec_info, uint16_t media_codec_info_len){
|
||||
avdtp_stream_endpoint_t * a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
|
||||
uint8_t * codec_capabilities, uint16_t codec_capabilities_len,
|
||||
uint8_t * codec_configuration, uint16_t codec_configuration_len){
|
||||
avdtp_stream_endpoint_t * local_stream_endpoint = avdtp_source_create_stream_endpoint(AVDTP_SOURCE, media_type);
|
||||
if (!local_stream_endpoint){
|
||||
return NULL;
|
||||
@ -645,11 +651,13 @@ avdtp_stream_endpoint_t * a2dp_source_create_stream_endpoint(avdtp_media_type_t
|
||||
avdtp_source_register_media_transport_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
|
||||
avdtp_source_register_media_codec_category(avdtp_stream_endpoint_seid(local_stream_endpoint), media_type, media_codec_type,
|
||||
codec_capabilities, codec_capabilities_len);
|
||||
|
||||
local_stream_endpoint->remote_configuration.media_codec.media_codec_information = media_codec_info;
|
||||
local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = media_codec_info_len;
|
||||
sc.local_stream_endpoint = local_stream_endpoint;
|
||||
avdtp_source_register_delay_reporting_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
|
||||
avdtp_source_register_delay_reporting_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
|
||||
|
||||
// store user codec configuration buffer
|
||||
local_stream_endpoint->media_codec_configuration_info = codec_configuration;
|
||||
local_stream_endpoint->media_codec_configuration_len = codec_configuration_len;
|
||||
|
||||
sc.local_stream_endpoint = local_stream_endpoint;
|
||||
return local_stream_endpoint;
|
||||
}
|
||||
|
||||
@ -717,12 +725,12 @@ uint8_t a2dp_source_reconfigure_stream_sampling_frequency(uint16_t avdtp_cid, ui
|
||||
|
||||
log_info("Reconfigure avdtp_cid 0x%02x", avdtp_cid);
|
||||
|
||||
(void)memcpy(sc.local_stream_endpoint->reconfigure_media_codec_sbc_info,
|
||||
(void)memcpy(sc.local_stream_endpoint->media_codec_sbc_info,
|
||||
sc.local_stream_endpoint->remote_sep.configuration.media_codec.media_codec_information,
|
||||
4);
|
||||
|
||||
// update sampling frequency
|
||||
uint8_t config = sc.local_stream_endpoint->reconfigure_media_codec_sbc_info[0] & 0x0f;
|
||||
uint8_t config = sc.local_stream_endpoint->media_codec_sbc_info[0] & 0x0f;
|
||||
switch (sampling_frequency){
|
||||
case 48000:
|
||||
config |= (AVDTP_SBC_48000 << 4);
|
||||
@ -740,13 +748,13 @@ uint8_t a2dp_source_reconfigure_stream_sampling_frequency(uint16_t avdtp_cid, ui
|
||||
log_error("Unsupported sampling frequency %u", sampling_frequency);
|
||||
return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
|
||||
}
|
||||
sc.local_stream_endpoint->reconfigure_media_codec_sbc_info[0] = config;
|
||||
sc.local_stream_endpoint->media_codec_sbc_info[0] = config;
|
||||
|
||||
avdtp_capabilities_t new_configuration;
|
||||
new_configuration.media_codec.media_type = AVDTP_AUDIO;
|
||||
new_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
|
||||
new_configuration.media_codec.media_codec_information_len = 4;
|
||||
new_configuration.media_codec.media_codec_information = sc.local_stream_endpoint->reconfigure_media_codec_sbc_info;
|
||||
new_configuration.media_codec.media_codec_information = sc.local_stream_endpoint->media_codec_sbc_info;
|
||||
|
||||
// start reconfigure
|
||||
a2dp_source_state = A2DP_W2_RECONFIGURE_WITH_SEID;
|
||||
|
@ -1299,13 +1299,6 @@ uint8_t avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t
|
||||
|
||||
log_debug("SE %p, initiator_config_state: 0x%02x", stream_endpoint, stream_endpoint->initiator_config_state);
|
||||
|
||||
// cache media codec information for SBC
|
||||
stream_endpoint->media_codec_type = configuration.media_codec.media_codec_type;
|
||||
if (configuration.media_codec.media_codec_type == AVDTP_CODEC_SBC){
|
||||
stream_endpoint->media_type = configuration.media_codec.media_type;
|
||||
(void)memcpy(stream_endpoint->media_codec_sbc_info,
|
||||
configuration.media_codec.media_codec_information, 4);
|
||||
}
|
||||
return avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
|
@ -486,8 +486,13 @@ typedef struct {
|
||||
typedef struct avdtp_stream_endpoint {
|
||||
btstack_linked_item_t item;
|
||||
|
||||
// original capabilities
|
||||
// original capabilities configured via avdtp_register_x_category
|
||||
avdtp_sep_t sep;
|
||||
|
||||
// media codec configuration
|
||||
uint16_t media_codec_configuration_len;
|
||||
uint8_t * media_codec_configuration_info;
|
||||
|
||||
avdtp_sep_t remote_sep;
|
||||
hci_con_handle_t media_con_handle;
|
||||
uint16_t l2cap_media_cid;
|
||||
@ -508,14 +513,11 @@ typedef struct avdtp_stream_endpoint {
|
||||
uint16_t remote_configuration_bitmap;
|
||||
avdtp_capabilities_t remote_configuration;
|
||||
|
||||
// temporary SBC config
|
||||
// temporary SBC config used by A2DP Source
|
||||
avdtp_media_codec_type_t media_codec_type;
|
||||
avdtp_media_type_t media_type;
|
||||
uint8_t media_codec_sbc_info[4];
|
||||
|
||||
// temporary reconfigure SBC config used by A2DP
|
||||
uint8_t reconfigure_media_codec_sbc_info[4];
|
||||
|
||||
// preferred sampling frequency
|
||||
uint32_t preferred_sampling_frequency;
|
||||
|
||||
|
@ -132,8 +132,14 @@ avdtp_acceptor_handle_configuration_command(avdtp_connection_t *connection, int
|
||||
log_info("add remote seid %d", stream_endpoint->remote_sep.seid);
|
||||
}
|
||||
|
||||
avdtp_signaling_emit_configuration(stream_endpoint, connection->avdtp_cid, &sep.configuration,
|
||||
sep.configured_service_categories);
|
||||
// if media codec configuration set, copy configuration and emit event
|
||||
if ((sep.configured_service_categories & (1 << AVDTP_MEDIA_CODEC)) != 0){
|
||||
if (stream_endpoint->media_codec_configuration_len == sep.configuration.media_codec.media_codec_information_len){
|
||||
(void) memcpy(stream_endpoint->media_codec_configuration_info, sep.configuration.media_codec.media_codec_information, stream_endpoint->media_codec_configuration_len);
|
||||
}
|
||||
avdtp_signaling_emit_configuration(stream_endpoint, connection->avdtp_cid, &sep.configuration, sep.configured_service_categories);
|
||||
}
|
||||
|
||||
avdtp_signaling_emit_accept(connection->avdtp_cid, avdtp_local_seid(stream_endpoint),
|
||||
connection->acceptor_signaling_packet.signal_identifier, false);
|
||||
}
|
||||
@ -314,8 +320,13 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t *connection, uint8_t
|
||||
|
||||
log_info("update active remote seid %d", stream_endpoint->remote_sep.seid);
|
||||
|
||||
avdtp_signaling_emit_configuration(stream_endpoint, connection->avdtp_cid, &sep.configuration,
|
||||
sep.configured_service_categories);
|
||||
// if media codec configuration updated, copy configuration and emit event
|
||||
if ((sep.configured_service_categories & (1 << AVDTP_MEDIA_CODEC)) != 0){
|
||||
if (stream_endpoint->media_codec_configuration_len == sep.configuration.media_codec.media_codec_information_len){
|
||||
(void) memcpy(stream_endpoint->media_codec_configuration_info, sep.configuration.media_codec.media_codec_information, stream_endpoint->media_codec_configuration_len);
|
||||
}
|
||||
avdtp_signaling_emit_configuration(stream_endpoint, connection->avdtp_cid, &sep.configuration, sep.configured_service_categories);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -152,17 +152,18 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t *connection, uint8_t
|
||||
break;
|
||||
}
|
||||
stream_endpoint_for_event = stream_endpoint;
|
||||
// copy sbc media codec info
|
||||
stream_endpoint->remote_sep.configured_service_categories |= stream_endpoint->remote_configuration_bitmap;
|
||||
stream_endpoint->remote_sep.configuration = stream_endpoint->remote_configuration;
|
||||
(void)memcpy(stream_endpoint->media_codec_sbc_info,
|
||||
stream_endpoint->remote_configuration.media_codec.media_codec_information,
|
||||
4);
|
||||
stream_endpoint->remote_sep.configuration.media_codec.media_codec_information = stream_endpoint->media_codec_sbc_info;
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
|
||||
|
||||
// copy media codec configuration if reconfigured
|
||||
if ((stream_endpoint->remote_configuration_bitmap & (1 << AVDTP_MEDIA_CODEC)) != 0){
|
||||
btstack_assert(stream_endpoint->remote_configuration.media_codec.media_codec_information_len == stream_endpoint->media_codec_configuration_len);
|
||||
(void)memcpy(stream_endpoint->media_codec_configuration_info, stream_endpoint->remote_configuration.media_codec.media_codec_information, stream_endpoint->media_codec_configuration_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case AVDTP_SI_SET_CONFIGURATION:{
|
||||
case AVDTP_SI_SET_CONFIGURATION:
|
||||
if (!stream_endpoint){
|
||||
log_error("AVDTP_SI_SET_CONFIGURATION: stream endpoint is null");
|
||||
break;
|
||||
@ -181,24 +182,32 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t *connection, uint8_t
|
||||
|
||||
log_info("configured remote seid %d", stream_endpoint->remote_sep.seid);
|
||||
|
||||
switch (stream_endpoint->media_codec_type){
|
||||
case AVDTP_CODEC_SBC:
|
||||
avdtp_signaling_emit_media_codec_sbc_configuration(
|
||||
stream_endpoint,
|
||||
connection->avdtp_cid,
|
||||
stream_endpoint->media_type,
|
||||
stream_endpoint->media_codec_sbc_info);
|
||||
break;
|
||||
default:
|
||||
// TODO: we don\t have codec info to emit config
|
||||
avdtp_signaling_emit_media_codec_other_configuration(stream_endpoint,
|
||||
connection->avdtp_cid,
|
||||
&sep.configuration.media_codec);
|
||||
break;
|
||||
}
|
||||
// copy media codec configuration if configured
|
||||
if ((stream_endpoint->remote_configuration_bitmap & (1 << AVDTP_MEDIA_CODEC)) != 0) {
|
||||
btstack_assert(stream_endpoint->remote_configuration.media_codec.media_codec_information_len ==
|
||||
stream_endpoint->media_codec_configuration_len);
|
||||
(void) memcpy(stream_endpoint->media_codec_configuration_info,
|
||||
stream_endpoint->remote_configuration.media_codec.media_codec_information,
|
||||
stream_endpoint->media_codec_configuration_len);
|
||||
|
||||
switch (stream_endpoint->media_codec_type) {
|
||||
case AVDTP_CODEC_SBC:
|
||||
avdtp_signaling_emit_media_codec_sbc_configuration(
|
||||
stream_endpoint,
|
||||
connection->avdtp_cid,
|
||||
stream_endpoint->media_type,
|
||||
stream_endpoint->media_codec_configuration_info);
|
||||
break;
|
||||
default:
|
||||
// TODO: we don't have codec info to emit config
|
||||
avdtp_signaling_emit_media_codec_other_configuration(stream_endpoint,
|
||||
connection->avdtp_cid,
|
||||
&sep.configuration.media_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case AVDTP_SI_OPEN:
|
||||
if (!stream_endpoint){
|
||||
log_error("AVDTP_SI_OPEN: stream endpoint is null");
|
||||
|
@ -124,8 +124,8 @@ void avdtp_reset_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint){
|
||||
stream_endpoint->remote_configuration_bitmap = 0;
|
||||
memset(&stream_endpoint->remote_configuration, 0, sizeof(avdtp_capabilities_t));
|
||||
|
||||
// temporary reconfigure SBC config used by A2DP
|
||||
memset(stream_endpoint->reconfigure_media_codec_sbc_info, 0, 4);
|
||||
// temporary SBC config used by A2DP Source
|
||||
memset(stream_endpoint->media_codec_sbc_info, 0, 4);
|
||||
|
||||
stream_endpoint->media_disconnect = 0;
|
||||
stream_endpoint->media_connect = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user