a2dp sink: allow accept or reject of stream start on A2DP_SUBEVENT_START_STREAM_REQUESTED when ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION is defined

This commit is contained in:
Milanka Ringwald 2021-09-09 11:33:48 +02:00
parent 4c30d2d172
commit 48ce193c1b
12 changed files with 170 additions and 31 deletions

View File

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- A2DP: allow to register media codec validator for sink and source with:
- `a2dp_sink_register_media_config_validator`
- `a2dp_source_register_media_config_validator`
- A2DP Sink: allow accept or reject of stream start on A2DP_SUBEVENT_START_STREAM_REQUESTED when ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION is defined
- SM: Support Cross-Transport Key-Derivation (CTKD) of LE LTK from BR/EDR SC Link Key
### Fixed

View File

@ -112,6 +112,8 @@ ENABLE_EXPLICIT_CONNECTABLE_MODE_CONTROL | Disable calls to control Connectable
ENABLE_EXPLICIT_IO_CAPABILITIES_REPLY | Let application trigger sending IO Capabilities (Negative) Reply
ENABLE_CLASSIC_OOB_PAIRING | Enable support for classic Out-of-Band (OOB) pairing
ENABLE_A2DP_SOURCE_EXPLICIT_CONFIG | Let application configure stream endpoint (skip auto-config of SBC endpoint)
ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION | allow accept or reject of stream start on A2DP_SUBEVENT_START_STREAM_REQUESTED
Notes:

View File

@ -873,6 +873,12 @@ static void a2dp_sink_packet_handler(uint8_t packet_type, uint16_t channel, uint
#endif
break;
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
case A2DP_SUBEVENT_START_STREAM_REQUESTED:
printf("A2DP Sink : Explicit Accept to start stream, local_seid 0x%02x\n", a2dp_subevent_start_stream_requested_get_local_seid(packet));
a2dp_sink_start_stream_accept(a2dp_cid, a2dp_local_seid);
break;
#endif
case A2DP_SUBEVENT_STREAM_STARTED:
printf("A2DP Sink : Stream started\n");
// audio stream is started when buffer reaches minimal level

View File

@ -32,6 +32,7 @@
#define ENABLE_SCO_OVER_HCI
#define ENABLE_SDP_DES_DUMP
#define ENABLE_SOFTWARE_AES128
#define ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
// BTstack configuration. buffers, sizes, ...
#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)

View File

@ -2385,13 +2385,21 @@ typedef uint8_t sm_key_t[16];
*/
#define A2DP_SUBEVENT_STREAM_ESTABLISHED 0x07
/**
* @format 121 If ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION, user must explicitly accept stream start.
* @param subevent_code
* @param a2dp_cid
* @param local_seid
*/
#define A2DP_SUBEVENT_START_STREAM_REQUESTED 0x08
/**
* @format 121 Indicates that media transfer is started.
* @param subevent_code
* @param a2dp_cid
* @param local_seid
*/
#define A2DP_SUBEVENT_STREAM_STARTED 0x08
#define A2DP_SUBEVENT_STREAM_STARTED 0x09
/**
* @format 121 Stream is paused.
@ -2399,7 +2407,7 @@ typedef uint8_t sm_key_t[16];
* @param a2dp_cid
* @param local_seid
*/
#define A2DP_SUBEVENT_STREAM_SUSPENDED 0x09
#define A2DP_SUBEVENT_STREAM_SUSPENDED 0x0A
/**
* @format 121 Stream is stopped or aborted.
@ -2407,7 +2415,7 @@ typedef uint8_t sm_key_t[16];
* @param a2dp_cid
* @param local_seid
*/
#define A2DP_SUBEVENT_STREAM_STOPPED 0x0A
#define A2DP_SUBEVENT_STREAM_STOPPED 0x0B
/**
* @format 121 Stream is released.
@ -2415,7 +2423,7 @@ typedef uint8_t sm_key_t[16];
* @param a2dp_cid
* @param local_seid
*/
#define A2DP_SUBEVENT_STREAM_RELEASED 0x0B
#define A2DP_SUBEVENT_STREAM_RELEASED 0x0C
/**
* @format 1211
@ -2424,7 +2432,7 @@ typedef uint8_t sm_key_t[16];
* @param local_seid
* @param signal_identifier
*/
#define A2DP_SUBEVENT_COMMAND_ACCEPTED 0x0C
#define A2DP_SUBEVENT_COMMAND_ACCEPTED 0x0D
/**
* @format 12111
@ -2434,7 +2442,7 @@ typedef uint8_t sm_key_t[16];
* @param is_initiator
* @param signal_identifier
*/
#define A2DP_SUBEVENT_COMMAND_REJECTED 0x0D
#define A2DP_SUBEVENT_COMMAND_REJECTED 0x0E
/**
* @format 12B21
@ -2444,14 +2452,14 @@ typedef uint8_t sm_key_t[16];
* @param con_handle
* @param status 0 == OK
*/
#define A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED 0x0E
#define A2DP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED 0x0F
/**
* @format 12 Signaling channel is released.
* @param subevent_code
* @param a2dp_cid
*/
#define A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED 0x0F
#define A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED 0x10
/**
* @format 1211 Stream was reconfigured
@ -2460,7 +2468,7 @@ typedef uint8_t sm_key_t[16];
* @param local_seid
* @param status
*/
#define A2DP_SUBEVENT_STREAM_RECONFIGURED 0x10
#define A2DP_SUBEVENT_STREAM_RECONFIGURED 0x12
/**
* @format 12111111111
@ -2476,7 +2484,7 @@ typedef uint8_t sm_key_t[16];
* @param min_bitpool_value
* @param max_bitpool_value
*/
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY 0x11
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY 0x13
/**
* @format 12111111112
@ -2492,7 +2500,7 @@ typedef uint8_t sm_key_t[16];
* @param vbr
* @param bit_rate_index_bitmap
*/
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AUDIO_CAPABILITY 0x12
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AUDIO_CAPABILITY 0x14
/**
* @format 121112131
@ -2506,7 +2514,7 @@ typedef uint8_t sm_key_t[16];
* @param bit_rate
* @param vbr
*/
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AAC_CAPABILITY 0x13
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_MPEG_AAC_CAPABILITY 0x15
/**
* @format 1211111132
@ -2521,7 +2529,7 @@ typedef uint8_t sm_key_t[16];
* @param bit_rate_index_bitmap
* @param maximum_sul
*/
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_ATRAC_CAPABILITY 0x14
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_ATRAC_CAPABILITY 0x16
/**
* @format 12112LV
@ -2533,7 +2541,7 @@ typedef uint8_t sm_key_t[16];
* @param media_codec_information_len
* @param media_codec_information
*/
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY 0x15
#define A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY 0x17
/**
* @format 121
@ -2541,7 +2549,7 @@ typedef uint8_t sm_key_t[16];
* @param a2dp_cid
* @param remote_seid
*/
#define A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY 0x16
#define A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY 0x18
/**
@ -2551,7 +2559,7 @@ typedef uint8_t sm_key_t[16];
* @param local_seid
* @param delay_100us
*/
#define A2DP_SUBEVENT_SIGNALING_DELAY_REPORT 0x17
#define A2DP_SUBEVENT_SIGNALING_DELAY_REPORT 0x19
/**
* @format 121
@ -2559,14 +2567,14 @@ typedef uint8_t sm_key_t[16];
* @param a2dp_cid
* @param remote_seid
*/
#define A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE 0x18
#define A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE 0x1A
/**
* @format 12
* @param subevent_code
* @param a2dp_cid
*/
#define A2DP_SUBEVENT_SIGNALING_CAPABILITIES_COMPLETE 0x19
#define A2DP_SUBEVENT_SIGNALING_CAPABILITIES_COMPLETE 0x1B
/** AVRCP Subevent */

View File

@ -7185,6 +7185,25 @@ static inline uint8_t a2dp_subevent_stream_established_get_status(const uint8_t
return event[13];
}
/**
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_START_STREAM_REQUESTED
* @param event packet
* @return a2dp_cid
* @note: btstack_type 2
*/
static inline uint16_t a2dp_subevent_start_stream_requested_get_a2dp_cid(const uint8_t * event){
return little_endian_read_16(event, 3);
}
/**
* @brief Get field local_seid from event A2DP_SUBEVENT_START_STREAM_REQUESTED
* @param event packet
* @return local_seid
* @note: btstack_type 1
*/
static inline uint8_t a2dp_subevent_start_stream_requested_get_local_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_STARTED
* @param event packet

View File

@ -207,6 +207,16 @@ uint8_t a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid, uint16
return avdtp_sink_connect(bd_addr, avdtp_cid);
}
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
uint8_t a2dp_sink_start_stream_accept(uint16_t a2dp_cid, uint8_t local_seid){
return avdtp_start_stream_accept(a2dp_cid, local_seid);
}
uint8_t a2dp_sink_start_stream_reject(uint16_t a2dp_cid, uint8_t local_seid){
return avdtp_start_stream_reject(a2dp_cid, local_seid);
}
#endif
void a2dp_sink_disconnect(uint16_t a2dp_cid){
avdtp_disconnect(a2dp_cid);
}
@ -294,6 +304,11 @@ static void a2dp_sink_packet_handler_internal(uint8_t packet_type, uint16_t chan
case AVDTP_SI_CLOSE:
a2dp_emit_stream_event(a2dp_sink_packet_handler_user, a2dp_sink_cid, local_seid, A2DP_SUBEVENT_STREAM_STOPPED);
break;
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
case AVDTP_SI_ACCEPT_START:
a2dp_emit_stream_event(a2dp_sink_packet_handler_user, a2dp_sink_cid, local_seid, A2DP_SUBEVENT_START_STREAM_REQUESTED);
break;
#endif
default:
break;
}

View File

@ -117,13 +117,29 @@ void a2dp_sink_register_media_handler(void (*callback)(uint8_t local_seid, uint8
* @brief Establish stream.
* @param remote
* @param local_seid ID of a local stream endpoint.
* @param out_a2dp_cid Assigned A2DP channel identifyer used for furhter A2DP commands.
* @param out_a2dp_cid Assigned A2DP channel identifier used for furhter A2DP commands.
*/
uint8_t a2dp_sink_establish_stream(bd_addr_t remote, uint8_t local_seid, uint16_t * out_a2dp_cid);
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
/**
* @brief Accept starting the stream on A2DP_SUBEVENT_START_STREAM_REQUESTED event.
* @param a2dp_cid A2DP channel identifier.
* @param local_seid ID of a local stream endpoint.
*/
uint8_t a2dp_sink_start_stream_accept(uint16_t a2dp_cid, uint8_t local_seid);
/**
* @brief Reject starting the stream on A2DP_SUBEVENT_START_STREAM_REQUESTED event.
* @param a2dp_cid A2DP channel identifier.
* @param local_seid ID of a local stream endpoint.
*/
uint8_t a2dp_sink_start_stream_reject(uint16_t a2dp_cid, uint8_t local_seid);
#endif
/**
* @brief Release stream and disconnect from remote.
* @param a2dp_cid A2DP channel identifyer.
* @param a2dp_cid A2DP channel identifier.
*/
void a2dp_sink_disconnect(uint16_t a2dp_cid);

View File

@ -1084,6 +1084,48 @@ uint8_t avdtp_disconnect(uint16_t avdtp_cid){
return ERROR_CODE_SUCCESS;
}
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
static uint8_t avdtp_handle_explicit_start_stream_confirmation(uint16_t avdtp_cid, uint8_t local_seid, bool accept_stream_requested){
avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(avdtp_cid);
if (!connection){
log_error("avdtp_media_connect: no connection for signaling cid 0x%02x found", avdtp_cid);
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
log_error("avdtp_media_connect: wrong connection state %d", connection->state);
return ERROR_CODE_COMMAND_DISALLOWED;
}
avdtp_stream_endpoint_t * stream_endpoint = avdtp_get_stream_endpoint_for_seid(local_seid);
if (!stream_endpoint) {
log_error("avdtp_media_connect: no stream_endpoint with seid %d found", local_seid);
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
}
if (stream_endpoint->acceptor_config_state != AVDTP_ACCEPTOR_W4_USER_CONFIRM_START_STREAM){
return ERROR_CODE_COMMAND_DISALLOWED;
}
if (accept_stream_requested){
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ACCEPT_START_STREAM;
} else {
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_START_STREAM;
}
avdtp_request_can_send_now_acceptor(connection);
return ERROR_CODE_SUCCESS;
}
uint8_t avdtp_start_stream_accept(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_handle_explicit_start_stream_confirmation(avdtp_cid, local_seid, true);
}
uint8_t avdtp_start_stream_reject(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_handle_explicit_start_stream_confirmation(avdtp_cid, local_seid, false);
}
#endif
uint8_t avdtp_open_stream(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid){
avdtp_connection_t * connection = avdtp_get_connection_for_avdtp_cid(avdtp_cid);
if (!connection){

View File

@ -115,7 +115,10 @@ typedef enum {
AVDTP_SI_ABORT, //10
AVDTP_SI_SECURITY_CONTROL,
AVDTP_SI_GET_ALL_CAPABILITIES, //12
AVDTP_SI_DELAYREPORT
AVDTP_SI_DELAYREPORT,
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
AVDTP_SI_ACCEPT_START
#endif
} avdtp_signal_identifier_t;
typedef enum {
@ -381,7 +384,11 @@ typedef enum {
AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE,
AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION,
AVDTP_ACCEPTOR_W2_ANSWER_OPEN_STREAM,
AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM,
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
AVDTP_ACCEPTOR_W4_USER_CONFIRM_START_STREAM,
AVDTP_ACCEPTOR_W2_REJECT_START_STREAM,
#endif
AVDTP_ACCEPTOR_W2_ACCEPT_START_STREAM,
AVDTP_ACCEPTOR_W2_ANSWER_CLOSE_STREAM,
AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM,
AVDTP_ACCEPTOR_W2_SUSPEND_STREAM_WITH_SEID,
@ -671,6 +678,11 @@ uint8_t is_avdtp_remote_seid_registered(avdtp_stream_endpoint_t * stream_endpoin
uint16_t avdtp_get_next_transaction_label(void);
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
uint8_t avdtp_start_stream_accept(uint16_t avdtp_cid, uint8_t local_seid);
uint8_t avdtp_start_stream_reject(uint16_t avdtp_cid, uint8_t local_seid);
#endif
#if defined __cplusplus
}
#endif

View File

@ -385,8 +385,13 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t *connection, uint8_t
connection->reject_signal_identifier = connection->acceptor_signaling_packet.signal_identifier;
break;
}
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
log_info("W2_ACCEPT_START_STREAM");
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W4_USER_CONFIRM_START_STREAM;
#else
log_info("W2_ANSWER_START_STREAM");
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ACCEPT_START_STREAM;
#endif
break;
case AVDTP_SI_CLOSE:
switch (stream_endpoint->state){
@ -626,7 +631,21 @@ void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t *connection) {
avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_OPEN);
emit_accept = true;
break;
case AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM:
#ifdef ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
case AVDTP_ACCEPTOR_W4_USER_CONFIRM_START_STREAM:
// keep state until user calls API to confirm or reject starting the stream
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W4_USER_CONFIRM_START_STREAM;
avdtp_signaling_emit_accept(connection->avdtp_cid, avdtp_local_seid(stream_endpoint), AVDTP_SI_ACCEPT_START, false);
break;
case AVDTP_ACCEPTOR_W2_REJECT_START_STREAM:
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
connection->acceptor_signaling_packet.signal_identifier = AVDTP_SI_START;
emit_reject = true;
avdtp_acceptor_send_response_reject(cid, AVDTP_SI_START, trid);
break;
#endif
case AVDTP_ACCEPTOR_W2_ACCEPT_START_STREAM:
log_info("DONE ");
log_info(" -> AVDTP_STREAM_ENDPOINT_STREAMING ");
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;

View File

@ -238,7 +238,7 @@ void avdtp_source_finalize_stream_endpoint(avdtp_stream_endpoint_t * stream_endp
/**
* @brief Send media packet
* @param avdtp_cid AVDTP channel identifyer.
* @param avdtp_cid AVDTP channel identifier.
* @param local_seid ID of a local stream endpoint.
* @param packet
* @param size
@ -248,7 +248,7 @@ uint8_t avdtp_source_stream_send_media_packet(uint16_t avdtp_cid, uint8_t local_
/**
* @brief Send media payload including RTP header
* @param avdtp_cid AVDTP channel identifyer.
* @param avdtp_cid AVDTP channel identifier.
* @param local_seid ID of a local stream endpoint.
* @param marker
* @param payload
@ -260,7 +260,7 @@ uint8_t avdtp_source_stream_send_media_payload_rtp(uint16_t avdtp_cid, uint8_t l
/**
* @brief Send media payload including RTP header and the SBC media header
* @deprecated Please use avdtp_source_stream_send_media_payload_rtp
* @param avdtp_cid AVDTP channel identifyer.
* @param avdtp_cid AVDTP channel identifier.
* @param local_seid ID of a local stream endpoint.
* @param storage
* @param num_bytes_to_copy
@ -270,18 +270,16 @@ uint8_t avdtp_source_stream_send_media_payload_rtp(uint16_t avdtp_cid, uint8_t l
*/
int avdtp_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);
/**
* @brief Request to send a media packet. Packet can be then sent on reception of AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW event.
* @param avdtp_cid AVDTP channel identifyer.
* @param avdtp_cid AVDTP channel identifier.
* @param local_seid ID of a local stream endpoint.
*/
void avdtp_source_stream_endpoint_request_can_send_now(uint16_t avddp_cid, uint8_t local_seid);
/**
* @brief Return maximal media payload size, does not include media header.
* @param avdtp_cid AVDTP channel identifyer.
* @param avdtp_cid AVDTP channel identifier.
* @param local_seid ID of a local stream endpoint.
*/
int avdtp_max_media_payload_size(uint16_t avdtp_cid, uint8_t local_seid);