avdtp: remove list of remote seps, emit instead seps to the app, with event done to mark the end

This commit is contained in:
Milanka Ringwald 2018-04-17 15:27:08 +02:00
parent c0491de323
commit 485c0a4c68
10 changed files with 145 additions and 172 deletions

View File

@ -49,6 +49,7 @@
#include "classic/avdtp_source.h"
#include "classic/a2dp_source.h"
#define AVDTP_MAX_SEP_NUM 10
#define AVDTP_MEDIA_PAYLOAD_HEADER_SIZE 12
static const char * default_a2dp_source_service_name = "BTstack A2DP Source Service";
@ -57,6 +58,8 @@ static avdtp_context_t a2dp_source_context;
static a2dp_state_t app_state = A2DP_IDLE;
static avdtp_stream_endpoint_context_t sc;
static avdtp_sep_t remote_seps[AVDTP_MAX_SEP_NUM];
static int remote_seps_index = 0;
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
@ -227,12 +230,12 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
sc.active_remote_sep = NULL;
sc.active_remote_sep_index = 0;
app_state = A2DP_W2_DISCOVER_SEPS;
remote_seps_index = 0;
memset(remote_seps, 0, sizeof(avdtp_sep_t) * AVDTP_MAX_SEP_NUM);
a2dp_signaling_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, status);
avdtp_source_discover_stream_endpoints(cid);
break;
}
case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY:{
log_info("A2DP received SBC capability.");
@ -327,6 +330,21 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, address, local_seid, remote_seid, 0);
break;
case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:{
avdtp_sep_t sep;
sep.seid = avdtp_subevent_signaling_sep_found_get_remote_seid(packet);;
sep.in_use = avdtp_subevent_signaling_sep_found_get_in_use(packet);
sep.media_type = avdtp_subevent_signaling_sep_found_get_media_type(packet);
sep.type = avdtp_subevent_signaling_sep_found_get_sep_type(packet);
log_info("Found sep: seid %u, in_use %d, media type %d, sep type %d (1-SNK)", sep.seid, sep.in_use, sep.media_type, sep.type);
remote_seps[remote_seps_index++] = sep;
break;
}
case AVDTP_SUBEVENT_SIGNALING_SEP_DICOVERY_DONE:
app_state = A2DP_W2_GET_CAPABILITIES;
sc.active_remote_sep_index = 0;
break;
case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
// TODO check cid
signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
@ -334,17 +352,11 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
log_info("A2DP Accepted %d, state %d", signal_identifier, app_state);
switch (app_state){
case A2DP_W2_DISCOVER_SEPS:
case A2DP_W2_GET_CAPABILITIES:
case A2DP_W2_GET_ALL_CAPABILITIES:
app_state = A2DP_W2_GET_ALL_CAPABILITIES;
sc.active_remote_sep = avdtp_source_remote_sep(cid, sc.active_remote_sep_index++);
if (!sc.active_remote_sep) {
app_state = A2DP_IDLE;
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, 0, 0, AVDTP_SEID_DOES_NOT_EXIST);
break;
if (sc.active_remote_sep_index < remote_seps_index){
sc.active_remote_sep = &remote_seps[sc.active_remote_sep_index++];
avdtp_source_get_capabilities(cid, sc.active_remote_sep->seid);
}
avdtp_source_get_capabilities(cid, sc.active_remote_sep->seid);
break;
case A2DP_W2_SET_CONFIGURATION:{
if (!sc.local_stream_endpoint) return;

View File

@ -654,7 +654,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
connection = avdtp_connection_for_l2cap_signaling_cid(local_cid, context);
stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(local_cid, context);
log_info("Neceived L2CAP_EVENT_CHANNEL_CLOSED, cid 0x%2x, connection %p, stream_endpoint %p", local_cid, connection, stream_endpoint);
log_info("Received L2CAP_EVENT_CHANNEL_CLOSED, cid 0x%2x, connection %p, stream_endpoint %p", local_cid, connection, stream_endpoint);
if (stream_endpoint){
if (stream_endpoint->l2cap_media_cid == local_cid){
@ -662,11 +662,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
if (connection) {
avdtp_streaming_emit_connection_released(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint));
}
stream_endpoint->l2cap_media_cid = 0;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
stream_endpoint->remote_sep_index = 0;
avdtp_reset_stream_endpoint(stream_endpoint);
if (connection && connection->disconnect){
avdtp_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
}
@ -686,19 +682,17 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
}
if (connection){
btstack_run_loop_remove_timer(&connection->configuration_timer);
avdtp_signaling_emit_connection_released(context->avdtp_callback, connection->avdtp_cid);
btstack_linked_list_remove(avdtp_connections, (btstack_linked_item_t*) connection);
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, stream_endpoints);
while (btstack_linked_list_iterator_has_next(&it)){
avdtp_stream_endpoint_t * _stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it);
if (_stream_endpoint->connection == connection){
avdtp_initialize_stream_endpoint(_stream_endpoint);
avdtp_reset_stream_endpoint(_stream_endpoint);
}
}
btstack_run_loop_remove_timer(&connection->configuration_timer);
avdtp_signaling_emit_connection_released(context->avdtp_callback, connection->avdtp_cid);
btstack_linked_list_remove(avdtp_connections, (btstack_linked_item_t*) connection);
btstack_memory_avdtp_connection_free(connection);
break;
}
@ -749,10 +743,6 @@ uint8_t avdtp_open_stream(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote
log_error("avdtp_media_connect: no connection for signaling cid 0x%02x found", avdtp_cid);
return AVDTP_CONNECTION_DOES_NOT_EXIST;
}
if (avdtp_find_remote_sep(connection, remote_seid) == 0xFF){
log_error("avdtp_media_connect: no remote sep for seid %d found", remote_seid);
return AVDTP_SEID_DOES_NOT_EXIST;
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
log_error("avdtp_media_connect: wrong connection state %d", connection->state);
@ -764,10 +754,14 @@ uint8_t avdtp_open_stream(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote
log_error("avdtp_media_connect: no stream_endpoint with seid %d found", local_seid);
return AVDTP_SEID_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep.seid != remote_seid){
log_error("avdtp_media_connect: no remote sep with seid %d registered with the stream endpoint", remote_seid);
return AVDTP_SEID_DOES_NOT_EXIST;
}
if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED) return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE;
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return AVDTP_SEID_DOES_NOT_EXIST;
connection->initiator_transaction_label++;
connection->remote_seid = remote_seid;
connection->local_seid = local_seid;
@ -795,8 +789,9 @@ uint8_t avdtp_start_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context
return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX || stream_endpoint->start_stream){
return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE;
if (!is_avdtp_remote_seid_registered(stream_endpoint)){
log_error("avdtp_media_connect: no remote sep registered with the stream endpoint");
return AVDTP_SEID_DOES_NOT_EXIST;
}
stream_endpoint->start_stream = 1;
@ -822,8 +817,11 @@ uint8_t avdtp_stop_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_
log_error("avdtp_stop_stream: no media connection for stream_endpoint with seid %d found", local_seid);
return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->stop_stream) return ERROR_CODE_SUCCESS;
if (!is_avdtp_remote_seid_registered(stream_endpoint) || stream_endpoint->stop_stream){
return ERROR_CODE_SUCCESS;
}
stream_endpoint->stop_stream = 1;
connection->local_seid = local_seid;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
@ -847,7 +845,10 @@ uint8_t avdtp_abort_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context
log_error("avdtp_abort_stream: no media connection for stream_endpoint with seid %d found", local_seid);
return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->abort_stream) return ERROR_CODE_SUCCESS;
if (!is_avdtp_remote_seid_registered(stream_endpoint) || stream_endpoint->abort_stream){
return ERROR_CODE_SUCCESS;
}
stream_endpoint->abort_stream = 1;
connection->local_seid = local_seid;
@ -871,8 +872,11 @@ uint8_t avdtp_suspend_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_conte
log_error("avdtp_suspend_stream: no media connection for stream_endpoint with seid %d found", local_seid);
return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->suspend_stream) return ERROR_CODE_SUCCESS;
if (!is_avdtp_remote_seid_registered(stream_endpoint) || stream_endpoint->suspend_stream){
return ERROR_CODE_SUCCESS;
}
stream_endpoint->suspend_stream = 1;
connection->local_seid = local_seid;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
@ -956,6 +960,7 @@ uint8_t avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED ||
connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) {
log_error("connection in wrong state, %d, initiator state %d", connection->state, connection->initiator_connection_state);
return AVDTP_CONNECTION_IN_WRONG_STATE;
}
@ -965,7 +970,7 @@ uint8_t avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t
return AVDTP_STREAM_ENDPOINT_DOES_NOT_EXIST;
}
if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_CONFIGURED){
log_error("Ntream endpoint seid %d in wrong state", local_seid);
log_error("Stream endpoint seid %d in wrong state %d", local_seid, stream_endpoint->state);
return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE;
}
connection->active_stream_endpoint = (void*) stream_endpoint;
@ -1006,10 +1011,11 @@ uint8_t avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote
return AVDTP_STREAM_ENDPOINT_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF){
if (!is_avdtp_remote_seid_registered(stream_endpoint)){
log_error("avdtp_reconfigure: no associated remote sep");
return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE;
}
connection->initiator_transaction_label++;
connection->remote_seid = remote_seid;
connection->local_seid = local_seid;
@ -1019,26 +1025,6 @@ uint8_t avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote
return avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_suspend: no connection for AVDTP cid 0x%02x found", avdtp_cid);
return 0;
}
return connection->remote_seps_num;
}
avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_suspend: no connection for AVDTP cid 0x%02x found", avdtp_cid);
return NULL;
}
if (index == AVDTP_INVALID_SEP_INDEX) return NULL;
if (index >= connection->remote_seps_num || index >= AVDTP_MAX_NUM_SEPS) return NULL;
return &connection->remote_seps[index];
}
void avdtp_initialize_sbc_configuration_storage(avdtp_stream_endpoint_t * stream_endpoint, uint8_t * config_storage, uint16_t storage_size, uint8_t * packet, uint16_t packet_size){
UNUSED(packet_size);
if (storage_size < 4) {
@ -1161,3 +1147,10 @@ uint8_t avdtp_choose_sbc_min_bitpool_value(avdtp_stream_endpoint_t * stream_endp
uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
return btstack_max(media_codec[2], remote_min_bitpool_value);
}
uint8_t is_avdtp_remote_seid_registered(avdtp_stream_endpoint_t * stream_endpoint){
if (!stream_endpoint) return 0;
if (stream_endpoint->remote_sep.seid == 0) return 0;
if (stream_endpoint->remote_sep.seid > 0x3E) return 0;
return 1;
}

View File

@ -97,6 +97,9 @@ extern "C" {
// ACP to INT, Procedure Error Codes
#define BAD_STATE 0x31
#define AVDTP_INVALID_SEP_SEID 0xFF
// Signal Identifier fields
typedef enum {
AVDTP_SI_NONE = 0x00,
@ -412,8 +415,8 @@ typedef struct {
uint8_t error_code;
// store configurations with remote seps
avdtp_sep_t remote_seps[AVDTP_MAX_NUM_SEPS];
uint8_t remote_seps_num;
// avdtp_sep_t remote_seps[AVDTP_MAX_NUM_SEPS];
// uint8_t remote_seps_num;
// store current role
uint8_t is_initiator;
@ -445,6 +448,7 @@ typedef struct avdtp_stream_endpoint {
// original capabilities
avdtp_sep_t sep;
avdtp_sep_t remote_sep;
hci_con_handle_t media_con_handle;
uint16_t l2cap_media_cid;
uint16_t l2cap_reporting_cid;
@ -457,7 +461,7 @@ typedef struct avdtp_stream_endpoint {
// active connection
avdtp_connection_t * connection;
// currently active remote seid
uint8_t remote_sep_index;
// uint8_t remote_sep_index;
avdtp_capabilities_t remote_capabilities;
uint16_t remote_capabilities_bitmap;
@ -477,7 +481,6 @@ typedef struct avdtp_stream_endpoint {
uint8_t send_stream;
uint8_t abort_stream;
uint8_t suspend_stream;
uint16_t sequence_number;
} avdtp_stream_endpoint_t;
@ -553,8 +556,6 @@ uint8_t avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdt
uint8_t avdtp_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context);
uint8_t avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
uint8_t avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context);
avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context);
void avdtp_initialize_sbc_configuration_storage(avdtp_stream_endpoint_t * stream_endpoint, uint8_t * config_storage, uint16_t storage_size, uint8_t * packet, uint16_t packet_size);
uint8_t avdtp_choose_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_channel_mode_bitmap);
@ -571,6 +572,7 @@ void avdtp_configuration_timeout_handler(btstack_timer_source_t * timer);
void avdtp_configuration_timer_start(avdtp_connection_t * connection);
void avdtp_configuration_timer_stop(avdtp_connection_t * connection);
uint8_t is_avdtp_remote_seid_registered(avdtp_stream_endpoint_t * stream_endpoint);
#if defined __cplusplus
}
#endif

View File

@ -207,7 +207,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
log_info("acceptor SM received SET_CONFIGURATION cmd: change role to acceptor, is_initiator %d", connection->is_initiator);
}
log_info("ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION ");
log_info("ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION connection %p", connection);
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURATION_SUBSTATEMACHINE;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION;
connection->reject_service_category = 0;
@ -225,17 +225,11 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
}
// find or add sep
stream_endpoint->remote_sep_index = avdtp_find_remote_sep(stream_endpoint->connection, sep.seid);
log_info("ACP .. seid %d, index %d", sep.seid, stream_endpoint->remote_sep_index);
log_info("ACP .. seid %d, remote sep seid %d", sep.seid, stream_endpoint->remote_sep.seid);
if (stream_endpoint->remote_sep_index != AVDTP_INVALID_SEP_INDEX){
if (stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].in_use){
if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_OPENED){
stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
log_info("ACP: update seid %d, to %p", stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
break;
}
// reject if already configured
if (is_avdtp_remote_seid_registered(stream_endpoint)){
if (stream_endpoint->remote_sep.in_use){
log_info("reject as it is already in use");
connection->error_code = SEP_IN_USE;
// find first registered category and fire the error
connection->reject_service_category = 0;
@ -249,16 +243,14 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
} else {
stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
log_info("ACP: update seid %d, to %p", stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
stream_endpoint->remote_sep = sep;
log_info("ACP: update seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint);
}
} else {
// add new
log_info("ACP: seid %d not found in %p", sep.seid, stream_endpoint);
stream_endpoint->remote_sep_index = connection->remote_seps_num;
connection->remote_seps_num++;
connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
log_info("ACP: add seid %d, to %p", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
stream_endpoint->remote_sep = sep;
log_info("ACP: add seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint);
}
avdtp_emit_configuration(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), &sep.configuration, sep.configured_service_categories);
@ -281,16 +273,15 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
}
// find sep or raise error
stream_endpoint->remote_sep_index = avdtp_find_remote_sep(stream_endpoint->connection, sep.seid);
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX){
if (!is_avdtp_remote_seid_registered(stream_endpoint)){
log_info("ACP: REJECT AVDTP_SI_RECONFIGURE, BAD_ACP_SEID");
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
connection->error_code = BAD_ACP_SEID;
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
break;
}
stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
log_info("ACP: update seid %d, to %p", stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
stream_endpoint->remote_sep = sep;
log_info("ACP: update seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint);
avdtp_emit_configuration(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), &sep.configuration, sep.configured_service_categories);
avdtp_signaling_emit_accept(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), connection->signaling_packet.signal_identifier);
@ -534,7 +525,7 @@ void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avd
break;
case AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION:{
avdtp_sep_t sep = stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index];
avdtp_sep_t sep = stream_endpoint->remote_sep;
avdtp_prepare_capabilities(&connection->signaling_packet, trid, sep.configured_service_categories, sep.configuration, AVDTP_SI_GET_CONFIGURATION);
l2cap_reserve_packet_buffer();
out_buffer = l2cap_get_outgoing_buffer();

View File

@ -66,7 +66,6 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
// int status = 0;
avdtp_stream_endpoint_t * stream_endpoint = NULL;
uint8_t remote_sep_index;
avdtp_sep_t sep;
if (connection->initiator_connection_state == AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER) {
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE;
@ -97,7 +96,7 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
break;
}
int i;
int i;
for (i = offset; i < size; i += 2){
sep.seid = packet[i] >> 2;
offset++;
@ -109,12 +108,9 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
sep.in_use = (packet[i] >> 1) & 0x01;
sep.media_type = (avdtp_media_type_t)(packet[i+1] >> 4);
sep.type = (avdtp_sep_type_t)((packet[i+1] >> 3) & 0x01);
if (avdtp_find_remote_sep(connection, sep.seid) == 0xFF){
connection->remote_seps[connection->remote_seps_num++] = sep;
}
avdtp_signaling_emit_sep(context->avdtp_callback, connection->avdtp_cid, sep);
}
avdtp_signaling_emit_sep_done(context->avdtp_callback, connection->avdtp_cid);
break;
}
@ -147,12 +143,10 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+4, connection->signaling_packet.size-4);
// TODO check if configuration is supported
remote_sep_index = avdtp_find_remote_sep(connection, sep.seid);
if (remote_sep_index != 0xFF){
stream_endpoint->remote_sep_index = remote_sep_index;
connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
if (!is_avdtp_remote_seid_registered(stream_endpoint)){
stream_endpoint->remote_sep = sep;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED;
log_info("INT: update seid %d, to %p", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
log_info("INT: update seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint);
}
break;
@ -165,20 +159,13 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
sep.configured_service_categories = stream_endpoint->remote_configuration_bitmap;
sep.configuration = stream_endpoint->remote_configuration;
sep.in_use = 1;
// TODO check if configuration is supported
// find or add sep
remote_sep_index = avdtp_find_remote_sep(connection, sep.seid);
if (remote_sep_index != 0xFF){
stream_endpoint->remote_sep_index = remote_sep_index;
} else {
stream_endpoint->remote_sep_index = connection->remote_seps_num;
connection->remote_seps_num++;
}
connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
log_info("INT: configured remote seid %d, to %p", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED;
stream_endpoint->remote_sep = sep;
stream_endpoint->connection = connection;
log_info("INT: configured remote seid %d, to %p", stream_endpoint->remote_sep.seid, stream_endpoint);
switch (stream_endpoint->media_codec_type){
case AVDTP_CODEC_SBC:
avdtp_signaling_emit_media_codec_sbc_configuration(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->remote_seid,
@ -186,7 +173,7 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
break;
default:
// TODO: we don\t have codec info to emit config
// avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->remote_seid, sep.configuration.media_codec);
avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->remote_seid, sep.configuration.media_codec);
break;
}
@ -317,7 +304,7 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
stream_endpoint->start_stream = 0;
if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_OPENED){
connection->local_seid = stream_endpoint->sep.seid;
connection->remote_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid;
connection->remote_seid = stream_endpoint->remote_sep.seid;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_START, connection->initiator_transaction_label++, connection->remote_seid);
return;
}
@ -328,7 +315,7 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
stream_endpoint->stop_stream = 0;
if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_OPENED){
connection->local_seid = stream_endpoint->sep.seid;
connection->remote_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid;
connection->remote_seid = stream_endpoint->remote_sep.seid;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_CLOSE, connection->initiator_transaction_label++, connection->remote_seid);
return;
}
@ -342,7 +329,7 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
case AVDTP_STREAM_ENDPOINT_OPENED:
case AVDTP_STREAM_ENDPOINT_STREAMING:
connection->local_seid = stream_endpoint->sep.seid;
connection->remote_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid;
connection->remote_seid = stream_endpoint->remote_sep.seid;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_ABORT, connection->initiator_transaction_label++, connection->remote_seid);
return;

View File

@ -175,10 +175,3 @@ void avdtp_source_init(avdtp_context_t * avdtp_context){
l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0);
}
uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid){
return avdtp_remote_seps_num(avdtp_cid, avdtp_source_context);
}
avdtp_sep_t * avdtp_source_remote_sep(uint16_t avdtp_cid, uint8_t index){
return avdtp_remote_sep(avdtp_cid, index, avdtp_source_context);
}

View File

@ -152,8 +152,6 @@ uint8_t avdtp_source_suspend(uint16_t avdtp_cid, uint8_t local_seid);
avdtp_stream_endpoint_t * avdtp_source_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type);
uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid);
avdtp_sep_t * avdtp_source_remote_sep(uint16_t avdtp_cid, uint8_t index);
/* API_END */
#if defined __cplusplus

View File

@ -70,15 +70,33 @@ const char * avdtp_si2str(uint16_t index){
return avdtp_si_name[index];
}
void avdtp_initialize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint){
void avdtp_reset_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint){
stream_endpoint->media_con_handle = 0;
stream_endpoint->l2cap_media_cid = 0;
stream_endpoint->l2cap_reporting_cid = 0;
stream_endpoint->l2cap_recovery_cid = 0;
stream_endpoint->connection = NULL;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
stream_endpoint->remote_sep_index = AVDTP_INVALID_SEP_INDEX;
stream_endpoint->media_disconnect = 0;
stream_endpoint->sep.in_use = 0;
stream_endpoint->remote_sep_index = 0;
memset(&stream_endpoint->remote_sep, 0, sizeof(avdtp_sep_t));
memset(&stream_endpoint->remote_capabilities, 0, sizeof(avdtp_capabilities_t));
memset(&stream_endpoint->remote_configuration, 0, sizeof(avdtp_capabilities_t));
stream_endpoint->remote_capabilities_bitmap = 0;
stream_endpoint->remote_configuration_bitmap = 0;
stream_endpoint->media_disconnect = 0;
stream_endpoint->media_connect = 0;
stream_endpoint->start_stream = 0;
stream_endpoint->stop_stream = 0;
stream_endpoint->send_stream = 0;
stream_endpoint->abort_stream = 0;
stream_endpoint->suspend_stream = 0;
stream_endpoint->sequence_number = 0;
}
avdtp_stream_endpoint_t * avdtp_stream_endpoint_for_seid(uint16_t seid, avdtp_context_t * context){
@ -175,12 +193,8 @@ avdtp_stream_endpoint_t * avdtp_stream_endpoint_associated_with_acp_seid(uint16_
btstack_linked_list_iterator_init(&it, &context->stream_endpoints);
while (btstack_linked_list_iterator_has_next(&it)){
avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it);
if (stream_endpoint->remote_sep_index != AVDTP_INVALID_SEP_INDEX){
if (!stream_endpoint->connection) continue;
if (stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid == acp_seid){
return stream_endpoint;
}
if (stream_endpoint->remote_sep.seid == acp_seid){
return stream_endpoint;
}
}
return NULL;
@ -619,6 +633,19 @@ void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t avdtp_
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_sep_done(btstack_packet_handler_t callback, uint16_t avdtp_cid){
if (!callback) return;
uint8_t event[5];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_SEP_DICOVERY_DONE;
little_endian_store_16(event, pos, avdtp_cid);
pos += 2;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, avdtp_signal_identifier_t identifier){
if (!callback) return;
uint8_t event[7];
@ -1024,32 +1051,6 @@ uint8_t avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_
return ERROR_CODE_SUCCESS;
}
uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t seid){
if (!stream_endpoint->connection) return AVDTP_INVALID_SEP_INDEX;
if (stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid == seid){
return stream_endpoint->remote_sep_index;
}
int i;
for (i=0; i < stream_endpoint->connection->remote_seps_num; i++){
if (stream_endpoint->connection->remote_seps[i].seid == seid){
return i;
}
}
return AVDTP_INVALID_SEP_INDEX;
}
uint8_t avdtp_find_remote_sep(avdtp_connection_t * connection, uint8_t remote_seid){
if (!connection) return AVDTP_INVALID_SEP_INDEX;
int i;
for (i = 0; i < connection->remote_seps_num; i++){
if (connection->remote_seps[i].seid == remote_seid){
return i;
}
}
return AVDTP_INVALID_SEP_INDEX;
}
uint8_t avdtp_local_seid(avdtp_stream_endpoint_t * stream_endpoint){
if (!stream_endpoint) return 0;
return stream_endpoint->sep.seid;
@ -1057,9 +1058,8 @@ uint8_t avdtp_local_seid(avdtp_stream_endpoint_t * stream_endpoint){
}
uint8_t avdtp_remote_seid(avdtp_stream_endpoint_t * stream_endpoint){
if (!stream_endpoint) return 0;
if (!stream_endpoint->connection) return 0;
return stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid;
if (!stream_endpoint) return AVDTP_INVALID_SEP_SEID;
return stream_endpoint->remote_sep.seid;
}
void a2dp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t cid, bd_addr_t addr, uint8_t local_seid, uint8_t remote_seid, uint8_t status){

View File

@ -52,8 +52,6 @@
extern "C" {
#endif
#define AVDTP_INVALID_SEP_INDEX 0xff
avdtp_connection_t * avdtp_connection_for_bd_addr(bd_addr_t addr, avdtp_context_t * context);
avdtp_connection_t * avdtp_connection_for_avdtp_cid(uint16_t l2cap_cid, avdtp_context_t * context);
avdtp_connection_t * avdtp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid, avdtp_context_t * context);
@ -85,6 +83,8 @@ void avdtp_signaling_emit_connection_released(btstack_packet_handler_t callback,
void avdtp_streaming_emit_connection_released(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid);
void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t avdtp_cid, avdtp_sep_t sep);
void avdtp_signaling_emit_sep_done(btstack_packet_handler_t callback, uint16_t avdtp_cid);
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t seid, avdtp_signal_identifier_t identifier);
void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier);
void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier);
@ -102,10 +102,7 @@ uint8_t avdtp_request_can_send_now_acceptor(avdtp_connection_t * connection, uin
uint8_t avdtp_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid);
uint8_t avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l2cap_cid);
uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t acp_seid);
void avdtp_initialize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint);
uint8_t avdtp_find_remote_sep(avdtp_connection_t * connection, uint8_t remote_seid);
void avdtp_reset_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint);
// uint16_t avdtp_cid(avdtp_stream_endpoint_t * stream_endpoint);
uint8_t avdtp_local_seid(avdtp_stream_endpoint_t * stream_endpoint);

View File

@ -43,6 +43,7 @@
#include <string.h>
#include "btstack.h"
#include "btstack_stdin_pts.h"
#define AVRCP_BROWSING_ENABLED 1
#define AVRCP_BROWSING_MAX_PLAYERS 10
@ -106,6 +107,7 @@ typedef struct {
uint8_t num_attributes;
} avrcp_browsable_media_element_item_t;
void btstack_stdin_pts_setup(void (*stdin_handler)(char * c, int size));
static uint8_t parent_folder_set = 0;
static uint8_t parent_folder_uid[8];
@ -248,9 +250,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
memcpy(media_element_items[index].uid, packet+pos, 8);
printf("Received media element item UID (index %d): ", index);
uint32_t media_uid_high = big_endian_read_32(packet, pos);
// uint32_t media_uid_high = big_endian_read_32(packet, pos);
pos += 4;
uint32_t media_uid_low = big_endian_read_32(packet, pos+4);
// uint32_t media_uid_low = big_endian_read_32(packet, pos+4);
pos += 4;
avrcp_browsing_media_type_t media_type = packet[pos++];
@ -292,9 +294,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
uint32_t attr_id = avrcp_media_item_iterator_get_attr_id(&media_item_context);
uint16_t attr_charset = avrcp_media_item_iterator_get_attr_charset(&media_item_context);
uint16_t attr_value_length = avrcp_media_item_iterator_get_attr_value_len(&media_item_context);
uint8_t * attr_value = avrcp_media_item_iterator_get_attr_value(&media_item_context);
attr_value[attr_value_length] = 0;
const uint8_t * attr_value = avrcp_media_item_iterator_get_attr_value(&media_item_context);
printf(" - attr ID 0x%08" PRIx32 ", charset 0x%02x, actual len %d, name %s\n", attr_id, attr_charset, attr_value_length, attr_value);
}
}
@ -321,7 +321,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
printf("AVDTP connection released: avdtp_cid 0x%02x.\n", avdtp_cid);
break;
default:
printf("AVDTP event not parsed.\n");
// printf("AVDTP event not parsed.\n");
break;
}
break;
@ -985,7 +985,7 @@ static void stdin_process(char * cmd, int size){
status = avrcp_controller_play_item_for_scope(avrcp_cid, media_element_items[0].uid, media_element_item_index, AVRCP_BROWSING_NOW_PLAYING);
break;
case '53':
case '5':
printf("Add to now playing: first media item from virtual file system\n");
if (media_element_item_index < 0){
printf("AVRCP Browsing: no media items found\n");