Merge branch 'develop' of https://github.com/bluekitchen/btstack into develop

This commit is contained in:
Matthias Ringwald 2017-01-30 15:12:19 +01:00
commit a981107707
9 changed files with 341 additions and 344 deletions

View File

@ -297,13 +297,15 @@ typedef enum {
typedef enum {
AVDTP_INITIATOR_STREAM_CONFIG_IDLE,
AVDTP_INITIATOR_W2_GET_CONFIGURATION,
AVDTP_INITIATOR_W4_CONFIGURATION_RECEIVED,
AVDTP_INITIATOR_STREAM_CONFIGURED,
AVDTP_INITIATOR_W2_SUSPEND_STREAM,
AVDTP_INITIATOR_W2_REJECT_WITH_ERROR_CODE,
AVDTP_INITIATOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE,
AVDTP_INITIATOR_W2_REJECT_UNKNOWN_CMD
AVDTP_INITIATOR_W2_SET_CONFIGURATION,
AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID,
AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID,
AVDTP_INITIATOR_W2_MEDIA_CONNECT,
AVDTP_INITIATOR_W2_STREAMING_START,
AVDTP_INITIATOR_W2_STREAMING_STOP,
AVDTP_INITIATOR_W2_STREAMING_ABORT,
AVDTP_INITIATOR_FRAGMENTATED_COMMAND,
AVDTP_INITIATOR_W4_ANSWER
} avdtp_initiator_stream_endpoint_state_t;
typedef enum {
@ -360,34 +362,10 @@ typedef enum {
typedef enum {
AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SEPS_DISCOVERED,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_CAPABILITIES,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ALL_CAPABILITIES,
// TODO move to initiator code
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SET_CONFIGURATION,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SET_CONFIGURATION,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_GET_CONFIGURATION,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SUSPEND_STREAM_WITH_SEID,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_RECONFIGURE_STREAM_WITH_SEID,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_MEDIA_CONNECTED,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_MEDIA_CONNECTED,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_STARTED,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_STREAMING_STARTED,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_STOPED,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_STREAMING_STOPED,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_ABORTED,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_STREAMING_ABORTED,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_REJECT_WITH_ERROR_CODE,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE,
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GENERAL_REJECT_WITH_ERROR_CODE
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER
} avdtp_initiator_connection_state_t;
typedef struct {
@ -424,6 +402,7 @@ typedef struct {
uint8_t acceptor_transaction_label;
uint8_t query_seid;
uint8_t int_seid;
uint8_t acp_seid;
avdtp_capabilities_t remote_capabilities;
uint16_t remote_capabilities_bitmap;

View File

@ -61,18 +61,6 @@ static int avdtp_acceptor_process_chunk(avdtp_signaling_packet_t * signaling_pac
return signaling_packet->packet_type == AVDTP_SINGLE_PACKET || signaling_packet->packet_type == AVDTP_END_PACKET;
}
static avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_for_active_seid(uint8_t seid){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &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->sep.seid == seid){
return stream_endpoint;
}
}
return NULL;
}
static int avdtp_acceptor_validate_msg_length(avdtp_signal_identifier_t signal_identifier, uint16_t msg_size){
int minimal_msg_lenght = 2;
switch (signal_identifier){
@ -122,7 +110,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
case AVDTP_SI_OPEN:
case AVDTP_SI_RECONFIGURE:
connection->query_seid = packet[offset++] >> 2;
stream_endpoint = get_avdtp_stream_endpoint_for_active_seid(connection->query_seid);
stream_endpoint = get_avdtp_stream_endpoint_with_seid(connection->query_seid);
if (!stream_endpoint){
printf(" ACP: cmd %d - RESPONSE REJECT\n", connection->signaling_packet.signal_identifier);
connection->error_code = BAD_ACP_SEID;
@ -164,7 +152,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
}
// deal with first susspended seid
connection->query_seid = connection->suspended_seids[0];
stream_endpoint = get_avdtp_stream_endpoint_for_active_seid(connection->query_seid);
stream_endpoint = get_avdtp_stream_endpoint_with_seid(connection->query_seid);
if (!stream_endpoint){
printf(" ACP: stream_endpoint not found, CATEGORY RESPONSE REJECT BAD_ACP_SEID\n");
connection->error_code = BAD_ACP_SEID;

View File

@ -47,27 +47,7 @@
#include "avdtp_util.h"
#include "avdtp_initiator.h"
static avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_associated_with_acp_seid(uint16_t acp_seid){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &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 >= 0 && stream_endpoint->remote_sep_index < MAX_NUM_SEPS){
if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid == acp_seid){
return stream_endpoint;
}
}
// int i;
// for (i=0; i<stream_endpoint->remote_seps_num; i++){
// if (stream_endpoint->remote_seps[i].seid == acp_seid){
// return stream_endpoint;
// }
// }
}
return NULL;
}
static int avdtp_initiator_send_signaling_cmd(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t transaction_label){
uint8_t command[2];
command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_CMD_MSG);
@ -83,15 +63,55 @@ static int avdtp_initiator_send_signaling_cmd_with_seid(uint16_t cid, avdtp_sign
return l2cap_send(cid, command, sizeof(command));
}
void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_t *packet, uint16_t size, int offset){
avdtp_stream_endpoint_t * stream_endpoint = NULL;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE;
int status = 0;
static void avdtp_signaling_emit_media_codec_capability(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){
if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){
switch (sep.capabilities.media_codec.media_codec_type){
case AVDTP_CODEC_SBC:
avdtp_signaling_emit_media_codec_sbc_capability(callback, con_handle, sep.capabilities.media_codec);
break;
default:
avdtp_signaling_emit_media_codec_other_capability(callback, con_handle, sep.capabilities.media_codec);
break;
}
}
}
static void avdtp_signaling_emit_media_codec_configuration(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){
if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){
switch (sep.capabilities.media_codec.media_codec_type){
case AVDTP_CODEC_SBC:
avdtp_signaling_emit_media_codec_sbc_configuration(callback, con_handle, sep.capabilities.media_codec);
break;
default:
avdtp_signaling_emit_media_codec_other_configuration(callback, con_handle, sep.capabilities.media_codec);
break;
}
}
}
void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_t *packet, uint16_t size, int offset){
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;
} else {
stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(connection->acp_seid);
if (!stream_endpoint){
stream_endpoint = get_avdtp_stream_endpoint_with_seid(connection->int_seid);
}
if (!stream_endpoint) return;
sep.seid = connection->acp_seid;
printf("avdtp_initiator_stream_config_subsm int seid %d, acp seid %d, ident %d \n", connection->int_seid, connection->acp_seid, connection->signaling_packet.signal_identifier);
if (stream_endpoint->initiator_config_state != AVDTP_INITIATOR_W4_ANSWER) return;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
}
switch (connection->signaling_packet.message_type){
case AVDTP_RESPONSE_ACCEPT_MSG:
printf(" INT: AVDTP_RESPONSE_ACCEPT_MSG: ");
switch (connection->signaling_packet.signal_identifier){
case AVDTP_SI_DISCOVER:{
printf("AVDTP_SI_DISCOVER\n");
@ -107,7 +127,6 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
break;
}
avdtp_sep_t sep;
int i;
for (i = offset; i < size; i += 2){
sep.seid = packet[i] >> 2;
@ -122,157 +141,76 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
sep.type = (avdtp_sep_type_t)((packet[i+1] >> 3) & 0x01);
avdtp_signaling_emit_sep(avdtp_sink_callback, connection->con_handle, sep);
}
connection->initiator_transaction_label++;
break;
}
case AVDTP_SI_GET_CAPABILITIES:
case AVDTP_SI_GET_ALL_CAPABILITIES:{
case AVDTP_SI_GET_ALL_CAPABILITIES:
printf("AVDTP_SI_GET(_ALL)_CAPABILITIES\n");
avdtp_sep_t sep;
sep.seid = connection->query_seid;
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, packet+offset, size-offset);
// printf_hexdump(packet, size);
if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){
switch (sep.capabilities.media_codec.media_codec_type){
case AVDTP_CODEC_SBC:
avdtp_signaling_emit_media_codec_sbc_capability(avdtp_sink_callback, connection->con_handle, sep.capabilities.media_codec);
break;
default:
avdtp_signaling_emit_media_codec_other_capability(avdtp_sink_callback, connection->con_handle, sep.capabilities.media_codec);
break;
}
}
avdtp_signaling_emit_media_codec_capability(avdtp_sink_callback, connection->con_handle, sep);
break;
}
case AVDTP_SI_GET_CONFIGURATION:{
printf("AVDTP_SI_GET_CONFIGURATION\n");
avdtp_sep_t sep;
sep.seid = connection->query_seid;
sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, packet+offset, size-offset);
printf(" INT .. seid %d, configured services 0%02x\n", sep.seid, sep.configured_service_categories);
if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){
printf(" AVDTP_SI_GET_CONFIGURATION 1 %d\n", sep.capabilities.media_codec.media_codec_type);
switch (sep.capabilities.media_codec.media_codec_type){
case AVDTP_CODEC_SBC:
avdtp_signaling_emit_media_codec_sbc_configuration(avdtp_sink_callback, connection->con_handle, sep.capabilities.media_codec);
break;
default:
avdtp_signaling_emit_media_codec_other_configuration(avdtp_sink_callback, connection->con_handle, sep.capabilities.media_codec);
break;
}
break;
}
break;
}
case AVDTP_SI_SET_CONFIGURATION:{
printf("AVDTP_SI_SET_CONFIGURATION\n");
stream_endpoint = get_avdtp_stream_endpoint_for_seid(connection->int_seid);
avdtp_sep_t sep;
sep.seid = connection->query_seid;
sep.configured_service_categories = connection->remote_capabilities_bitmap;
sep.configuration = connection->remote_capabilities;
sep.in_use = 1;
// find or add sep
int i;
stream_endpoint->remote_sep_index = 0xFF;
for (i=0; i < stream_endpoint->remote_seps_num; i++){
if (stream_endpoint->remote_seps[i].seid == sep.seid){
stream_endpoint->remote_sep_index = i;
break;
}
}
if (stream_endpoint->remote_sep_index != 0xFF){
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
printf(" INT: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
} else {
// add new
printf(" INT: seid %d not found in %p\n", sep.seid, stream_endpoint);
stream_endpoint->remote_sep_index = stream_endpoint->remote_seps_num;
stream_endpoint->remote_seps_num++;
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
printf(" INT: add seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
}
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED;
case AVDTP_SI_GET_CONFIGURATION:
printf("AVDTP_SI_GET_CONFIGURATION\n");
sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, packet+offset, size-offset);
avdtp_signaling_emit_media_codec_configuration(avdtp_sink_callback, connection->con_handle, sep);
break;
}
case AVDTP_SI_RECONFIGURE:
printf("AVDTP_SI_RECONFIGURE\n");
avdtp_sep_t sep;
sep.seid = connection->query_seid;
sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+4, connection->signaling_packet.size-4);
sep.in_use = 1;
// find or sep
int i;
stream_endpoint->remote_sep_index = 0xFF;
for (i=0; i < stream_endpoint->remote_seps_num; i++){
if (stream_endpoint->remote_seps[i].seid == sep.seid){
stream_endpoint->remote_sep_index = i;
break;
}
}
// TODO check if configuration is supported
if (stream_endpoint->remote_sep_index != 0xFF){
remote_sep_index = avdtp_get_index_of_remote_stream_endpoint_with_seid(stream_endpoint, sep.seid);
if (remote_sep_index != 0xFF){
stream_endpoint->remote_sep_index = remote_sep_index;
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED;
printf(" INT: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
}
break;
case AVDTP_SI_SET_CONFIGURATION:{
printf("AVDTP_SI_SET_CONFIGURATION\n");
sep.configured_service_categories = connection->remote_capabilities_bitmap;
sep.configuration = connection->remote_capabilities;
sep.in_use = 1;
// TODO check if configuration is supported
// find or add sep
remote_sep_index = avdtp_get_index_of_remote_stream_endpoint_with_seid(stream_endpoint, sep.seid);
if (remote_sep_index != 0xFF){
stream_endpoint->remote_sep_index = remote_sep_index;
} else {
stream_endpoint->remote_sep_index = stream_endpoint->remote_seps_num;
stream_endpoint->remote_seps_num++;
}
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
printf(" INT: configured seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED;
break;
}
case AVDTP_SI_OPEN:
printf("AVDTP_SI_OPEN\n");
stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(connection->query_seid);
if (!stream_endpoint) {
status = 1;
break;
}
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
break;
case AVDTP_SI_START:
printf("AVDTP_SI_START\n");
stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(connection->query_seid);
if (!stream_endpoint) {
status = 1;
break;
}
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;
break;
case AVDTP_SI_SUSPEND:
printf("AVDTP_SI_SUSPEND\n");
stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(connection->query_seid);
if (!stream_endpoint) {
status = 1;
break;
}
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
break;
case AVDTP_SI_CLOSE:
printf("AVDTP_SI_CLOSE\n");
stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(connection->query_seid);
if (!stream_endpoint) {
status = 1;
break;
}
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CLOSING;
break;
case AVDTP_SI_ABORT:
printf("AVDTP_SI_ABORT\n");
stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(connection->query_seid);
if (!stream_endpoint) {
status = 1;
break;
}
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING;
break;
default:
@ -292,92 +230,112 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
default:
break;
}
connection->initiator_transaction_label++;
connection->int_seid = 0;
connection->acp_seid = 0;
avdtp_signaling_emit_accept(avdtp_sink_callback, connection->con_handle, connection->signaling_packet.signal_identifier, status);
}
void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection){
int sent = 1;
switch (connection->initiator_connection_state){
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SEPS_DISCOVERED\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SEPS_DISCOVERED;
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
avdtp_initiator_send_signaling_cmd(connection->l2cap_signaling_cid, AVDTP_SI_DISCOVER, connection->initiator_transaction_label);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES:
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_CAPABILITIES;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CAPABILITIES, connection->initiator_transaction_label, connection->query_seid);
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CAPABILITIES, connection->initiator_transaction_label, connection->acp_seid);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_GET_ALL_CAPABILITIES\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ALL_CAPABILITIES;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_ALL_CAPABILITIES, connection->initiator_transaction_label, connection->query_seid);
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_ALL_CAPABILITIES, connection->initiator_transaction_label, connection->acp_seid);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_GET_CONFIGURATION\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_GET_CONFIGURATION;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CONFIGURATION, connection->initiator_transaction_label, connection->query_seid);
printf(" INT: AVDTP_INITIATOR_W4_GET_CONFIGURATION\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CONFIGURATION, connection->initiator_transaction_label, connection->acp_seid);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SET_CONFIGURATION:{
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SET_CONFIGURATION bitmap %02x\n", connection->remote_capabilities_bitmap);
// printf_hexdump( connection->remote_capabilities.media_codec.media_codec_information, connection->remote_capabilities.media_codec.media_codec_information_len);
connection->signaling_packet.acp_seid = connection->query_seid;
default:
sent = 0;
break;
}
if (sent) return;
sent = 1;
avdtp_stream_endpoint_t * stream_endpoint = NULL;
printf(" run int seid %d, acp seid %d\n", connection->int_seid, connection->acp_seid);
stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(connection->acp_seid);
if (!stream_endpoint){
stream_endpoint = get_avdtp_stream_endpoint_with_seid(connection->int_seid);
}
if (!stream_endpoint) return;
avdtp_initiator_stream_endpoint_state_t stream_endpoint_state = stream_endpoint->initiator_config_state;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W4_ANSWER;
switch (stream_endpoint_state){
case AVDTP_INITIATOR_W2_SET_CONFIGURATION:
case AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID:{
printf(" INT: AVDTP_INITIATOR_W2_(RE)CONFIGURATION bitmap, int seid %d, acp seid %d\n", connection->int_seid, connection->acp_seid);
printf_hexdump( connection->remote_capabilities.media_codec.media_codec_information, connection->remote_capabilities.media_codec.media_codec_information_len);
connection->signaling_packet.acp_seid = connection->acp_seid;
connection->signaling_packet.int_seid = connection->int_seid;
connection->signaling_packet.signal_identifier = AVDTP_SI_SET_CONFIGURATION;
avdtp_prepare_capabilities(&connection->signaling_packet, connection->initiator_transaction_label, connection->remote_capabilities_bitmap, connection->remote_capabilities, AVDTP_SI_SET_CONFIGURATION);
if (stream_endpoint_state == AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID){
connection->signaling_packet.signal_identifier = AVDTP_SI_RECONFIGURE;
}
avdtp_prepare_capabilities(&connection->signaling_packet, connection->initiator_transaction_label, connection->remote_capabilities_bitmap, connection->remote_capabilities, connection->signaling_packet.signal_identifier);
l2cap_reserve_packet_buffer();
uint8_t * out_buffer = l2cap_get_outgoing_buffer();
uint16_t pos = avdtp_signaling_create_fragment(connection->l2cap_signaling_cid, &connection->signaling_packet, out_buffer);
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SET_CONFIGURATION;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_FRAGMENTATED_COMMAND;
printf(" INT: fragmented\n");
}
l2cap_send_prepared(connection->l2cap_signaling_cid, pos);
break;
}
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_RECONFIGURE_STREAM_WITH_SEID\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_RECONFIGURE_STREAM_WITH_SEID;
connection->signaling_packet.acp_seid = connection->query_seid;
connection->signaling_packet.int_seid = 0;
connection->signaling_packet.signal_identifier = AVDTP_SI_RECONFIGURE;
avdtp_prepare_capabilities(&connection->signaling_packet, connection->initiator_transaction_label, connection->remote_capabilities_bitmap, connection->remote_capabilities, AVDTP_SI_RECONFIGURE);
case AVDTP_INITIATOR_FRAGMENTATED_COMMAND:{
l2cap_reserve_packet_buffer();
uint8_t * out_buffer = l2cap_get_outgoing_buffer();
uint16_t pos = avdtp_signaling_create_fragment(connection->l2cap_signaling_cid, &connection->signaling_packet, out_buffer);
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_RECONFIGURE_STREAM_WITH_SEID;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_FRAGMENTATED_COMMAND;
printf(" INT: fragmented\n");
}
l2cap_send_prepared(connection->l2cap_signaling_cid, pos);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_MEDIA_CONNECTED:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_MEDIA_CONNECTED\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_MEDIA_CONNECTED;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_OPEN, connection->initiator_transaction_label, connection->query_seid);
}
case AVDTP_INITIATOR_W2_MEDIA_CONNECT:
printf(" INT: AVDTP_INITIATOR_W4_L2CAP_FOR_MEDIA_CONNECTED\n");
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_OPEN, connection->initiator_transaction_label, connection->acp_seid);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SUSPEND_STREAM_WITH_SEID\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SUSPEND_STREAM_WITH_SEID;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_SUSPEND, connection->initiator_transaction_label, connection->query_seid);
case AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID:
printf(" INT: AVDTP_INITIATOR_W4_SUSPEND_STREAM_WITH_SEID\n");
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_SUSPEND, connection->initiator_transaction_label, connection->acp_seid);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_STARTED:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_STREAMING_STARTED\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_STREAMING_STARTED;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_START, connection->initiator_transaction_label, connection->query_seid);
case AVDTP_INITIATOR_W2_STREAMING_START:
printf(" INT: AVDTP_INITIATOR_W4_STREAMING_START\n");
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_START, connection->initiator_transaction_label, connection->acp_seid);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_STOPED:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_STREAMING_STOPED\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_STREAMING_STOPED;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_CLOSE, connection->initiator_transaction_label, connection->query_seid);
case AVDTP_INITIATOR_W2_STREAMING_STOP:
printf(" INT: AVDTP_INITIATOR_W4_STREAMING_STOP\n");
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_CLOSE, connection->initiator_transaction_label, connection->acp_seid);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_ABORTED:
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_STREAMING_ABORTED\n");
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_L2CAP_FOR_STREAMING_ABORTED;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_ABORT, connection->initiator_transaction_label, connection->query_seid);
case AVDTP_INITIATOR_W2_STREAMING_ABORT:
printf(" INT: AVDTP_INITIATOR_W4_STREAMING_ABORT\n");
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->acp_seid);
break;
default:
break;

View File

@ -154,7 +154,7 @@ static avdtp_connection_t * avdtp_sink_create_connection(bd_addr_t remote_addr){
return connection;
}
uint8_t avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type){
avdtp_stream_endpoint_t * avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type){
avdtp_stream_endpoint_t * stream_endpoint = btstack_memory_avdtp_stream_endpoint_get();
memset(stream_endpoint, 0, sizeof(avdtp_stream_endpoint_t));
stream_endpoints_id_counter++;
@ -162,7 +162,7 @@ uint8_t avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media
stream_endpoint->sep.media_type = media_type;
stream_endpoint->sep.type = sep_type;
btstack_linked_list_add(&stream_endpoints, (btstack_linked_item_t *) stream_endpoint);
return stream_endpoint->sep.seid;
return stream_endpoint;
}
void avdtp_sink_register_media_transport_category(uint8_t seid){
@ -649,7 +649,7 @@ void avdtp_sink_disconnect(uint16_t con_handle){
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
}
void avdtp_sink_open_stream(uint16_t con_handle, uint8_t seid){
void avdtp_sink_open_stream(uint16_t con_handle, uint8_t acp_seid){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_media_connect: no connection for handle 0x%02x found\n", con_handle);
@ -661,25 +661,24 @@ void avdtp_sink_open_stream(uint16_t con_handle, uint8_t seid){
return;
}
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid);
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid);
if (!stream_endpoint) {
printf("avdtp_sink_media_connect: no stream_endpoint for seid %d found\n", seid);
printf("avdtp_sink_media_connect: no stream_endpoint with acp seid %d found\n", acp_seid);
return;
}
printf(" AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_MEDIA_CONNECTED \n");
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_MEDIA_CONNECTED;
connection->query_seid = seid;
if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED) return;
if (stream_endpoint->remote_sep_index == 0xFF) return;
if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED){
return;
} else {
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED;
}
printf(" AVDTP_INITIATOR_W2_MEDIA_CONNECT \n");
connection->initiator_transaction_label++;
connection->acp_seid = acp_seid;
connection->int_seid = stream_endpoint->sep.seid;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_MEDIA_CONNECT;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
void avdtp_sink_start_stream(uint16_t con_handle, uint8_t seid){
void avdtp_sink_start_stream(uint16_t con_handle, uint8_t acp_seid){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_media_connect: no connection for handle 0x%02x found\n", con_handle);
@ -691,47 +690,46 @@ void avdtp_sink_start_stream(uint16_t con_handle, uint8_t seid){
return;
}
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid);
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid);
if (!stream_endpoint) {
printf("avdtp_sink_media_connect: no stream_endpoint for seid %d found\n", seid);
printf("avdtp_sink_media_connect: no stream_endpoint with acp_seid %d found\n", acp_seid);
return;
}
printf(" AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_STARTED \n");
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_STARTED;
connection->query_seid = seid;
if (stream_endpoint->remote_sep_index == 0xFF) return;
if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_OPENED) return;
printf(" AVDTP_INITIATOR_W2_STREAMING_START \n");
connection->initiator_transaction_label++;
connection->acp_seid = acp_seid;
connection->int_seid = stream_endpoint->sep.seid;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_START;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
void avdtp_sink_stop_stream(uint16_t con_handle, uint8_t seid){
void avdtp_sink_stop_stream(uint16_t con_handle, uint8_t acp_seid){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_stop_stream: no connection for handle 0x%02x found\n", con_handle);
return;
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
printf("avdtp_sink_stop_stream: wrong connection state %d\n", connection->state);
return;
}
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid);
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid);
if (!stream_endpoint) {
printf("avdtp_sink_stop_stream: no stream_endpoint for seid %d found\n", seid);
printf("avdtp_sink_stop_stream: no stream_endpoint with acp seid %d found\n", acp_seid);
return;
}
if (stream_endpoint->remote_sep_index == 0xFF) return;
switch (stream_endpoint->state){
case AVDTP_STREAM_ENDPOINT_OPENED:
case AVDTP_STREAM_ENDPOINT_STREAMING:
printf(" AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_STOPED \n");
printf(" AVDTP_INITIATOR_W2_STREAMING_STOP \n");
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_STOPED;
connection->query_seid = seid;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CLOSING;
connection->acp_seid = acp_seid;
connection->int_seid = stream_endpoint->sep.seid;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_STOP;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
break;
default:
@ -739,7 +737,7 @@ void avdtp_sink_stop_stream(uint16_t con_handle, uint8_t seid){
}
}
void avdtp_sink_abort_stream(uint16_t con_handle, uint8_t seid){
void avdtp_sink_abort_stream(uint16_t con_handle, uint8_t acp_seid){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_abort_stream: no connection for handle 0x%02x found\n", con_handle);
@ -751,21 +749,22 @@ void avdtp_sink_abort_stream(uint16_t con_handle, uint8_t seid){
return;
}
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid);
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid);
if (!stream_endpoint) {
printf("avdtp_sink_abort_stream: no stream_endpoint for seid %d found\n", seid);
printf("avdtp_sink_abort_stream: no stream_endpoint for seid %d found\n", acp_seid);
return;
}
if (stream_endpoint->remote_sep_index == 0xFF) return;
switch (stream_endpoint->state){
case AVDTP_STREAM_ENDPOINT_CONFIGURED:
case AVDTP_STREAM_ENDPOINT_CLOSING:
case AVDTP_STREAM_ENDPOINT_OPENED:
case AVDTP_STREAM_ENDPOINT_STREAMING:
printf(" AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_ABORTED \n");
printf(" AVDTP_INITIATOR_W2_STREAMING_ABORT \n");
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_L2CAP_FOR_STREAMING_ABORTED;
connection->query_seid = seid;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING;
connection->acp_seid = acp_seid;
connection->int_seid = stream_endpoint->sep.seid;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_ABORT;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
break;
default:
@ -794,7 +793,7 @@ void avdtp_sink_discover_stream_endpoints(uint16_t con_handle){
}
void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t seid){
void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t acp_seid){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_get_capabilities: no connection for handle 0x%02x found\n", con_handle);
@ -804,12 +803,12 @@ void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t seid){
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES;
connection->query_seid = seid;
connection->acp_seid = acp_seid;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t seid){
void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_get_all_capabilities: no connection for handle 0x%02x found\n", con_handle);
@ -819,11 +818,11 @@ void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t seid){
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES;
connection->query_seid = seid;
connection->acp_seid = acp_seid;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
void avdtp_sink_get_configuration(uint16_t con_handle, uint8_t seid){
void avdtp_sink_get_configuration(uint16_t con_handle, uint8_t acp_seid){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_get_configuration: no connection for handle 0x%02x found\n", con_handle);
@ -833,11 +832,11 @@ void avdtp_sink_get_configuration(uint16_t con_handle, uint8_t seid){
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION;
connection->query_seid = seid;
connection->acp_seid = acp_seid;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
void avdtp_sink_set_configuration(uint16_t con_handle, uint8_t acp_seid, uint8_t int_seid, uint16_t remote_capabilities_bitmap, avdtp_capabilities_t remote_capabilities){
void avdtp_sink_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_set_configuration: no connection for handle 0x%02x found\n", con_handle);
@ -851,16 +850,39 @@ void avdtp_sink_set_configuration(uint16_t con_handle, uint8_t acp_seid, uint8_t
printf("avdtp_sink_set_configuration: no initiator stream endpoint for seid %d\n", int_seid);
return;
}
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SET_CONFIGURATION;
printf("avdtp_sink_set_configuration int seid %d, acp seid %d\n", int_seid, acp_seid);
connection->initiator_transaction_label++;
connection->query_seid = acp_seid;
connection->acp_seid = acp_seid;
connection->int_seid = int_seid;
connection->remote_capabilities = remote_capabilities;
connection->remote_capabilities_bitmap = remote_capabilities_bitmap;
connection->remote_capabilities_bitmap = configured_services_bitmap;
connection->remote_capabilities = configuration;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SET_CONFIGURATION;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
void avdtp_sink_suspend(uint16_t con_handle, uint8_t seid){
void avdtp_sink_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_reconfigure: no connection for handle 0x%02x found\n", con_handle);
return;
}
//TODO: if opened only app capabilities, enable reconfigure for not opened
if (connection->state < AVDTP_SIGNALING_CONNECTION_OPENED) return;
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid);
if (!stream_endpoint) return;
if (stream_endpoint->remote_sep_index == 0xFF) return;
connection->initiator_transaction_label++;
connection->acp_seid = acp_seid;
connection->int_seid = stream_endpoint->sep.seid;
connection->remote_capabilities_bitmap = configured_services_bitmap;
connection->remote_capabilities = configuration;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
void avdtp_sink_suspend(uint16_t con_handle, uint8_t acp_seid){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_suspend: no connection for handle 0x%02x found\n", con_handle);
@ -868,31 +890,12 @@ void avdtp_sink_suspend(uint16_t con_handle, uint8_t seid){
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid);
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid);
if (!stream_endpoint) return;
if (stream_endpoint->remote_sep_index == 0xFF) return;
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID;
connection->query_seid = seid;
connection->acp_seid = acp_seid;
connection->int_seid = stream_endpoint->sep.seid;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
void avdtp_sink_reconfigure(uint16_t con_handle, uint8_t seid){
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
if (!connection){
printf("avdtp_sink_reconfigure: no connection for handle 0x%02x found\n", con_handle);
return;
}
//TODO: if opened only app capabilities, enable reconfigure for not opened
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid);
if (!stream_endpoint) return;
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID;
//TODO: check if it is registered in remote_seps
connection->query_seid = seid;
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
}
}

View File

@ -70,8 +70,8 @@ void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_han
*/
void avdtp_sink_init(void);
// returns sep_id
uint8_t avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type);
// returns avdtp_stream_endpoint_t *
avdtp_stream_endpoint_t * avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type);
void avdtp_sink_register_media_transport_category(uint8_t seid);
void avdtp_sink_register_reporting_category(uint8_t seid);
@ -112,19 +112,26 @@ void avdtp_sink_discover_stream_endpoints(uint16_t con_handle);
* @brief Get capabilities
* @param con_handle
*/
void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t seid);
void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t acp_seid);
/**
* @brief Get all capabilities
* @param con_handle
*/
void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t seid);
void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid);
/**
* @brief Set configuration
* @param con_handle
*/
void avdtp_sink_set_configuration(uint16_t con_handle, uint8_t acp_seid, uint8_t int_seid, uint16_t remote_capabilities_bitmap, avdtp_capabilities_t remote_capabilities);
void avdtp_sink_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
/**
* @brief Reconfigure stream
* @param con_handle
* @param seid
*/
void avdtp_sink_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration);
/**
* @brief Get configuration
@ -137,15 +144,7 @@ void avdtp_sink_get_configuration(uint16_t con_handle, uint8_t acp_seid);
* @param con_handle
* @param seid
*/
void avdtp_sink_suspend(uint16_t con_handle, uint8_t seid);
/**
* @brief Reconfigure stream
* @param con_handle
* @param seid
*/
void avdtp_sink_reconfigure(uint16_t con_handle, uint8_t seid);
void avdtp_sink_suspend(uint16_t con_handle, uint8_t acp_seid);
/**
@ -153,28 +152,28 @@ void avdtp_sink_reconfigure(uint16_t con_handle, uint8_t seid);
* @param con_handle
* @param seid
*/
void avdtp_sink_open_stream(uint16_t con_handle, uint8_t seid);
void avdtp_sink_open_stream(uint16_t con_handle, uint8_t acp_seid);
/**
* @brief Start stream
* @param con_handle
* @param seid
*/
void avdtp_sink_start_stream(uint16_t con_handle, uint8_t seid);
void avdtp_sink_start_stream(uint16_t con_handle, uint8_t acp_seid);
/**
* @brief Start stream
* @param con_handle
* @param seid
*/
void avdtp_sink_abort_stream(uint16_t con_handle, uint8_t seid);
void avdtp_sink_abort_stream(uint16_t con_handle, uint8_t acp_seid);
/**
* @brief Start stream
* @param con_handle
* @param seid
*/
void avdtp_sink_stop_stream(uint16_t con_handle, uint8_t seid);
void avdtp_sink_stop_stream(uint16_t con_handle, uint8_t acp_seid);
/* API_END */

View File

@ -142,6 +142,7 @@ static avdtp_sep_t sep;
static adtvp_media_codec_information_sbc_t sbc_capability;
static avdtp_media_codec_configuration_sbc_t sbc_configuration;
static avdtp_stream_endpoint_t * local_stream_endpoint;
static uint16_t remote_configuration_bitmap;
static avdtp_capabilities_t remote_configuration;
@ -524,12 +525,24 @@ static void show_usage(void){
printf("---\n");
}
static const uint8_t media_sbc_codec_info[] = {
static const uint8_t media_sbc_codec_capabilities[] = {
0xFF,//(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
2, 53
};
static const uint8_t media_sbc_codec_configuration[] = {
(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
2, 53
};
static const uint8_t media_sbc_codec_reconfiguration[] = {
(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_SNR,
2, 53
};
static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
UNUSED(ds);
UNUSED(callback_type);
@ -567,14 +580,18 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
remote_configuration_bitmap = store_bit16(remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
remote_configuration.media_codec.media_type = AVDTP_AUDIO;
remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_info);
remote_configuration.media_codec.media_codec_information = media_sbc_codec_info;
avdtp_sink_set_configuration(con_handle, sep.seid, 1, remote_configuration_bitmap, remote_configuration);
remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_configuration);
remote_configuration.media_codec.media_codec_information = media_sbc_codec_configuration;
avdtp_sink_set_configuration(con_handle, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
break;
case 'R':
app_state = AVDTP_APPLICATION_W2_RECONFIGURE_WITH_SEID;
avdtp_sink_reconfigure(con_handle, sep.seid);
remote_configuration_bitmap = store_bit16(remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
remote_configuration.media_codec.media_type = AVDTP_AUDIO;
remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_reconfiguration);
remote_configuration.media_codec.media_codec_information = media_sbc_codec_reconfiguration;
avdtp_sink_reconfigure(con_handle, sep.seid, remote_configuration_bitmap, remote_configuration);
break;
case 'o':
app_state = AVDTP_APPLICATION_W2_OPEN_STREAM_WITH_SEID;
@ -587,9 +604,11 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
case 'A':
app_state = AVDTP_APPLICATION_W2_ABORT_STREAM_WITH_SEID;
avdtp_sink_abort_stream(con_handle, sep.seid);
break;
case 'S':
app_state = AVDTP_APPLICATION_W2_STOP_STREAM_WITH_SEID;
avdtp_sink_stop_stream(con_handle, sep.seid);
break;
case 'P':
app_state = AVDTP_APPLICATION_W2_SUSPEND_STREAM_WITH_SEID;
avdtp_sink_suspend(con_handle, sep.seid);
@ -622,9 +641,10 @@ int btstack_main(int argc, const char * argv[]){
avdtp_sink_register_packet_handler(&packet_handler);
//#ifndef SMG_BI
uint8_t seid = avdtp_sink_create_stream_endpoint(AVDTP_SINK, AVDTP_AUDIO);
avdtp_sink_register_media_transport_category(seid);
avdtp_sink_register_media_codec_category(seid, AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_info, sizeof(media_sbc_codec_info));
local_stream_endpoint = avdtp_sink_create_stream_endpoint(AVDTP_SINK, AVDTP_AUDIO);
local_stream_endpoint->sep.seid = 5;
avdtp_sink_register_media_transport_category(local_stream_endpoint->sep.seid);
avdtp_sink_register_media_codec_category(local_stream_endpoint->sep.seid, AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities));
//#endif
// uint8_t cp_type_lsb, uint8_t cp_type_msb, const uint8_t * cp_type_value, uint8_t cp_type_value_len
// avdtp_sink_register_content_protection_category(seid, 2, 2, NULL, 0);

View File

@ -50,6 +50,32 @@ inline uint8_t avdtp_header(uint8_t tr_label, avdtp_packet_type_t packet_type, a
return (tr_label<<4) | ((uint8_t)packet_type<<2) | (uint8_t)msg_type;
}
avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_with_seid(uint8_t seid){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &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->sep.seid == seid){
return stream_endpoint;
}
}
return NULL;
}
avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_associated_with_acp_seid(uint16_t acp_seid){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &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 >= 0 && stream_endpoint->remote_sep_index < MAX_NUM_SEPS){
if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid == acp_seid){
return stream_endpoint;
}
}
}
return NULL;
}
int get_bit16(uint16_t bitmap, int position){
return (bitmap >> position) & 1;
}
@ -224,8 +250,14 @@ uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdt
if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0;
int processed_cap_len = 0;
int rfa = 0;
//printf(" size %d, cat size %d\n", size, cap_len);
while (pos < size){
if (cap_len > size - pos){
connection->reject_service_category = category;
connection->error_code = BAD_LENGTH;
return 0;
}
rfa = 0;
processed_cap_len = pos;
switch(category){
@ -285,11 +317,12 @@ uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdt
registered_service_categories = store_bit16(registered_service_categories, category, 1);
}
if (pos < size-2){
//int old_pos = pos;
category = (avdtp_service_category_t)packet[pos++];
cap_len = packet[pos++];
if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0;
// printf("category %d, pos %d + 2 + %d -> %d\n", category, old_pos, cap_len, pos + cap_len);
// printf_hexdump(packet+old_pos, size-old_pos);
//printf("category %d, pos %d + 2 + %d -> %d\n", category, old_pos, cap_len, pos + cap_len);
//printf_hexdump(packet+old_pos, size-old_pos);
}
}
}
@ -646,4 +679,16 @@ avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_for_seid(uint16_t seid){
}
return NULL;
}
uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t seid){
if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid == seid){
return stream_endpoint->remote_sep_index;
}
int i;
for (i=0; i < stream_endpoint->remote_seps_num; i++){
if (stream_endpoint->remote_seps[i].seid == seid){
return i;
}
}
return 0xFF;
}

View File

@ -52,6 +52,9 @@
extern "C" {
#endif
avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_with_seid(uint8_t seid);
avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_associated_with_acp_seid(uint16_t acp_seid);
uint8_t avdtp_header(uint8_t tr_label, avdtp_packet_type_t packet_type, avdtp_message_type_t msg_type);
int avdtp_read_signaling_header(avdtp_signaling_packet_t * signaling_header, uint8_t * packet, uint16_t size);
@ -82,6 +85,8 @@ void avdtp_sink_request_can_send_now_acceptor(avdtp_connection_t * connection, u
void avdtp_sink_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid);
void avdtp_sink_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);
avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_for_seid(uint16_t seid);
#if defined __cplusplus

View File

@ -67,8 +67,8 @@ extern "C" {
#include "classic/btstack_link_key_db_memory.h"
#include "classic/rfcomm.h"
#include "classic/sdp_server.h"
#include "../test/avdtp/avdtp_sink.h"
#include "../test/avdtp/avdtp_source.h"
#include "classic/avdtp_sink.h"
#include "classic/avdtp_source.h"
// BLE
#ifdef ENABLE_BLE