a2dp: allow to register media codec validator for sink and source

This commit is contained in:
Matthias Ringwald 2021-07-16 15:23:12 +02:00
parent 98137b165c
commit a95794cee1
5 changed files with 61 additions and 0 deletions

View File

@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- hci_cmd: support variable length fields and arrayed parameters
- POSIX: btstack_signal allows to register for callback on signal, e.g. ctrl-c
- Windows: btstack_stdin_window_register_ctrl_c_callback allows to register for ctrl-c
- A2DP: allow to register media codec validator for sink and source with:
- `a2dp_sink_register_media_config_validator`
- `a2dp_source_register_media_config_validator`
### Fixed
- A2DP Source: fix reconfigure

View File

@ -57,6 +57,7 @@ static uint16_t a2dp_sink_cid;
static bool stream_endpoint_configured = false;
static btstack_packet_handler_t a2dp_sink_packet_handler_user;
static uint8_t (*a2dp_sink_media_config_validator)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size);
static void a2dp_sink_packet_handler_internal(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
@ -333,3 +334,21 @@ static void a2dp_sink_packet_handler_internal(uint8_t packet_type, uint16_t chan
}
static uint8_t a2dp_sink_media_config_validator_callback(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size){
uint8_t error = 0;
if (a2dp_sink_media_config_validator == NULL) {
// update subevent id and call validator
uint8_t avdtp_subevent_id = event[2];
uint8_t a2dp_subevent_id = a2dp_subevent_id_for_avdtp_subevent_id(avdtp_subevent_id);
uint8_t * subevent_field = (uint8_t *) &event[2];
*subevent_field = a2dp_subevent_id;
error = (*a2dp_sink_media_config_validator)(stream_endpoint, event, size);
*subevent_field = avdtp_subevent_id;
}
return error;
}
void a2dp_sink_register_media_config_validator(uint8_t (*callback)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size)){
a2dp_sink_media_config_validator = callback;
avdtp_sink_register_media_config_validator(&a2dp_sink_media_config_validator_callback);
}

View File

@ -127,6 +127,15 @@ uint8_t a2dp_sink_establish_stream(bd_addr_t remote, uint8_t local_seid, uint16_
*/
void a2dp_sink_disconnect(uint16_t a2dp_cid);
/**
* @brief Register media configuration validator. Can reject insuitable configuration or report stream endpoint as currently busy
* @note validator has to return AVDTP error codes like: AVDTP_ERROR_CODE_SEP_IN_USE or AVDTP_ERROR_CODE_UNSUPPORTED_CONFIGURATION
* the callback receives the media configuration in the same format as the existing A2dP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* and similar
* @param callback
*/
void a2dp_sink_register_media_config_validator(uint8_t (*callback)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size));
/**
* @brief De-Init A2DP Sink device.
*/

View File

@ -70,6 +70,7 @@ static const char * default_a2dp_source_service_name = "BTstack A2DP Source Serv
static const char * default_a2dp_source_service_provider_name = "BTstack A2DP Source Service Provider";
static btstack_packet_handler_t a2dp_source_packet_handler_user;
static uint8_t (*a2dp_source_media_config_validator)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size);
// config process - singletons using sep_discovery_cid is used as mutex
static uint16_t sep_discovery_cid;
@ -1057,3 +1058,23 @@ uint8_t a2dp_source_reconfigure_stream_sampling_frequency(uint16_t avdtp_cid, ui
new_configuration
);
}
static uint8_t a2dp_source_media_config_validator_callback(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size){
uint8_t error = 0;
if (a2dp_source_media_config_validator == NULL) {
// update subevent id and call validator
uint8_t avdtp_subevent_id = event[2];
uint8_t a2dp_subevent_id = a2dp_subevent_id_for_avdtp_subevent_id(avdtp_subevent_id);
uint8_t * subevent_field = (uint8_t *) &event[2];
*subevent_field = a2dp_subevent_id;
error = (*a2dp_source_media_config_validator)(stream_endpoint, event, size);
*subevent_field = avdtp_subevent_id;
}
return error;
}
void a2dp_sink_register_media_config_validator(uint8_t (*callback)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size)){
a2dp_source_media_config_validator = callback;
avdtp_source_register_media_config_validator(&a2dp_source_media_config_validator_callback);
}

View File

@ -245,6 +245,15 @@ uint8_t a2dp_source_set_config_atrac(uint16_t a2dp_cid, uint8_t local_seid, uin
*/
uint8_t a2dp_source_set_config_other(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, const uint8_t * media_codec_information, uint8_t media_codec_information_len);
/**
* @brief Register media configuration validator. Can reject insuitable configuration or report stream endpoint as currently busy
* @note validator has to return AVDTP error codes like: AVDTP_ERROR_CODE_SEP_IN_USE or AVDTP_ERROR_CODE_UNSUPPORTED_CONFIGURATION
* the callback receives the media configuration in the same format as the existing A2dP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* and similar
* @param callback
*/
void a2dp_source_register_media_config_validator(uint8_t (*callback)(const avdtp_stream_endpoint_t * stream_endpoint, const uint8_t * event, uint16_t size));
/**
* @brief De-Init A2DP Source device.
*/