a2dp source: handle incoming connection, send event to client on signaling connection established

This commit is contained in:
Milanka Ringwald 2017-08-16 16:06:05 +02:00
parent 2f6083d0d8
commit 5448c259b2
6 changed files with 105 additions and 33 deletions

View File

@ -306,6 +306,16 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) return;
switch (packet[2]){
case A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED:
a2dp_subevent_incoming_connection_established_get_bd_addr(packet, address);
media_tracker.a2dp_cid = a2dp_subevent_incoming_connection_established_get_a2dp_cid(packet);
printf("A2DP: Incoming connection established: address %s, a2dp cid 0x%02x. Create stream on local seid %d.\n",
bd_addr_to_str(address), media_tracker.a2dp_cid, media_tracker.local_seid);
status = a2dp_source_establish_stream(device_addr, media_tracker.local_seid, &media_tracker.a2dp_cid);
if (status != ERROR_CODE_SUCCESS){
printf("Could not perform command, status 0x%2x\n", status);
}
break;
case A2DP_SUBEVENT_STREAM_ESTABLISHED:
a2dp_subevent_stream_established_get_bd_addr(packet, address);
status = a2dp_subevent_stream_established_get_status(packet);
@ -318,10 +328,12 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
printf("A2DP: Stream establishment failed: wrong local seid %d, expected %d.\n", local_seid, media_tracker.local_seid);
break;
}
media_tracker.a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
printf("A2DP: Stream established: address %s, a2dp cid 0x%02x, local seid %d, remote seid %d.\n", bd_addr_to_str(address),
media_tracker.a2dp_cid, media_tracker.local_seid, a2dp_subevent_stream_established_get_remote_seid(packet));
printf("Start playing mod.\n");
data_source = STREAM_MOD;
status = a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
break;
case A2DP_SUBEVENT_STREAM_STARTED:

View File

@ -1522,6 +1522,14 @@ typedef uint8_t sm_key_t[16];
*/
#define A2DP_SUBEVENT_COMMAND_REJECTED 0x09
/**
* @format 12B Signaling channel is opened.
* @param subevent_code
* @param a2dp_cid
* @param bd_addr
*/
#define A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED 0x0A
/** AVRCP Subevent */
/**

View File

@ -4964,6 +4964,25 @@ static inline uint8_t a2dp_subevent_command_rejected_get_signal_identifier(const
return event[6];
}
/**
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED
* @param event packet
* @return a2dp_cid
* @note: btstack_type 2
*/
static inline uint16_t a2dp_subevent_incoming_connection_established_get_a2dp_cid(const uint8_t * event){
return little_endian_read_16(event, 3);
}
/**
* @brief Get field bd_addr from event A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED
* @param event packet
* @param Pointer to storage for bd_addr
* @note: btstack_type B
*/
static inline void a2dp_subevent_incoming_connection_established_get_bd_addr(const uint8_t * event, bd_addr_t bd_addr){
reverse_bd_addr(&event[5], bd_addr);
}
/**
* @brief Get field status from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED
* @param event packet

View File

@ -184,8 +184,23 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
sc.active_remote_sep = NULL;
next_remote_sep_index_to_query = 0;
if (!sc.local_stream_endpoint) {
app_state = A2DP_CONNECTED;
uint8_t event[11];
int pos = 0;
event[pos++] = HCI_EVENT_A2DP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED;
little_endian_store_16(event, pos, cid);
pos += 2;
reverse_bd_addr(event+pos, sc.remote_addr);
pos += 6;
(*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
return;
}
app_state = A2DP_W2_DISCOVER_SEPS;
log_info("AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---", cid);
// printf("AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---\n", cid);
avdtp_source_discover_stream_endpoints(cid);
break;
@ -198,11 +213,14 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
sep.media_type = (avdtp_media_type_t) sep_media_type;
sep_type = avdtp_subevent_signaling_sep_found_get_sep_type(packet);
sep.type = (avdtp_sep_type_t) sep_type;
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);
// printf("found sep: seid %u, in_use %d, media type %d, sep type %d (1-SNK)\n", sep.seid, sep.in_use, sep.media_type, sep.type);
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY:{
if (!sc.local_stream_endpoint) return;
if (!sc.local_stream_endpoint) {
// printf("local seid %d \n", avdtp_subevent_signaling_media_codec_sbc_capability_get_local_seid(packet));
return;
}
uint8_t sampling_frequency = avdtp_choose_sbc_sampling_frequency(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet));
uint8_t channel_mode = avdtp_choose_sbc_channel_mode(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet));
uint8_t block_length = avdtp_choose_sbc_block_length(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet));
@ -277,17 +295,17 @@ 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, sc.remote_addr, 0, 0, AVDTP_SEID_DOES_NOT_EXIST);
break;
}
log_info("Query get caps for seid %d", sc.active_remote_sep->seid);
// printf("Query get caps for seid %d\n", sc.active_remote_sep->seid);
avdtp_source_get_capabilities(cid, sc.active_remote_sep->seid);
break;
case A2DP_W2_GET_CAPABILITIES:
case A2DP_W2_GET_ALL_CAPABILITIES:
if (next_remote_sep_index_to_query < avdtp_source_remote_seps_num(cid)){
sc.active_remote_sep = avdtp_source_remote_sep(cid, next_remote_sep_index_to_query++);
log_info("Query get caps for seid %d", sc.active_remote_sep->seid);
// printf("Query get caps for seid %d\n", sc.active_remote_sep->seid);
avdtp_source_get_capabilities(cid, sc.active_remote_sep->seid);
} else {
log_info("No more remote seps found");
// printf("No more remote seps found\n");
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);
}

View File

@ -104,30 +104,36 @@ uint8_t avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_conte
return BTSTACK_MEMORY_ALLOC_FAILED;
}
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_IDLE){
log_error("avdtp_connect: sink in wrong state");
return AVDTP_CONNECTION_IN_WRONG_STATE;
}
*avdtp_cid = connection->avdtp_cid;
if (!avdtp_cid) {
return L2CAP_LOCAL_CID_DOES_NOT_EXIST;
}
*avdtp_cid = connection->avdtp_cid;
connection->state = AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE;
avdtp_context->avdtp_l2cap_psm = 0;
avdtp_context->avdtp_version = 0;
avdtp_context->avdtp_cid = connection->avdtp_cid;
avdtp_context->query_role = query_role;
sdp_query_context = avdtp_context;
uint8_t err = sdp_client_query_uuid16(&avdtp_handle_sdp_client_query_result, remote, BLUETOOTH_PROTOCOL_AVDTP);
if (err != ERROR_CODE_SUCCESS){
connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
btstack_linked_list_remove(&avdtp_context->connections, (btstack_linked_item_t*) connection);
btstack_memory_avdtp_connection_free(connection);
return err;
uint8_t err;
switch (connection->state){
case AVDTP_SIGNALING_CONNECTION_IDLE:
connection->state = AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE;
sdp_query_context = avdtp_context;
avdtp_context->avdtp_l2cap_psm = 0;
avdtp_context->avdtp_version = 0;
avdtp_context->query_role = query_role;
err = sdp_client_query_uuid16(&avdtp_handle_sdp_client_query_result, remote, BLUETOOTH_PROTOCOL_AVDTP);
if (err != ERROR_CODE_SUCCESS){
connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
btstack_linked_list_remove(&avdtp_context->connections, (btstack_linked_item_t*) connection);
btstack_memory_avdtp_connection_free(connection);
}
return err;
case AVDTP_SIGNALING_CONNECTION_OPENED:
avdtp_signaling_emit_connection_established(avdtp_context->avdtp_callback, avdtp_context->avdtp_cid, connection->remote_addr, ERROR_CODE_SUCCESS);
break;
default:
log_error("avdtp_connect: sink in wrong state");
return AVDTP_CONNECTION_IN_WRONG_STATE;
}
return ERROR_CODE_SUCCESS;
}
@ -432,7 +438,7 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c
// avdtp_remote_uuid = uuid;
break;
case BLUETOOTH_SERVICE_CLASS_AUDIO_SINK:
if (sdp_query_context->query_role != AVDTP_SINK) {
if (sdp_query_context->query_role == AVDTP_SINK) {
sdp_query_context->role_supported = 1;
break;
}
@ -490,7 +496,7 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c
case SDP_EVENT_QUERY_COMPLETE:
status = sdp_event_query_complete_get_status(packet);
if (status != ERROR_CODE_SUCCESS){
avdtp_signaling_emit_connection_established(sdp_query_context->avdtp_callback, sdp_query_context->avdtp_cid, connection->remote_addr, L2CAP_SERVICE_DOES_NOT_EXIST);
avdtp_signaling_emit_connection_established(sdp_query_context->avdtp_callback, sdp_query_context->avdtp_cid, connection->remote_addr, status);
btstack_linked_list_remove(&sdp_query_context->connections, (btstack_linked_item_t*) connection);
btstack_memory_avdtp_connection_free(connection);
log_info("AVDTP: SDP query failed with status 0x%02x.", status);

View File

@ -416,7 +416,7 @@ static void avrcp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c
UNUSED(packet_type);
UNUSED(channel);
UNUSED(size);
uint8_t status;
des_iterator_t des_list_it;
des_iterator_t prot_it;
// uint32_t avdtp_remote_uuid = 0;
@ -544,13 +544,23 @@ static void avrcp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c
break;
case SDP_EVENT_QUERY_COMPLETE:
log_info("General query done with status %d, role supported %d.\n", sdp_event_query_complete_get_status(packet), sdp_query_context->role_supported);
status = sdp_event_query_complete_get_status(packet);
if (status != ERROR_CODE_SUCCESS){
avrcp_emit_connection_established(sdp_query_context->avrcp_callback, connection->avrcp_cid, connection->remote_addr, status);
btstack_linked_list_remove(&sdp_query_context->connections, (btstack_linked_item_t*) connection);
btstack_memory_avrcp_connection_free(connection);
log_info("AVRCP: SDP query failed with status 0x%02x.", status);
break;
}
if (!sdp_query_context->role_supported || !sdp_query_context->avrcp_l2cap_psm){
connection->state = AVCTP_CONNECTION_IDLE;
avrcp_emit_connection_established(sdp_query_context->avrcp_callback, connection->avrcp_cid, connection->remote_addr, SDP_SERVICE_NOT_FOUND);
btstack_linked_list_remove(&sdp_query_context->connections, (btstack_linked_item_t*) connection);
btstack_memory_avrcp_connection_free(connection);
break;
}
log_info("AVRCP Control PSM 0x%02x, Browsing PSM 0x%02x", sdp_query_context->avrcp_l2cap_psm, sdp_query_context->avrcp_browsing_l2cap_psm);
// log_info("AVRCP Control PSM 0x%02x, Browsing PSM 0x%02x", sdp_query_context->avrcp_l2cap_psm, sdp_query_context->avrcp_browsing_l2cap_psm);
connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
l2cap_create_channel(sdp_query_context->packet_handler, connection->remote_addr, sdp_query_context->avrcp_l2cap_psm, l2cap_max_mtu(), NULL);
break;
@ -651,6 +661,5 @@ uint8_t avrcp_connect(bd_addr_t bd_addr, avrcp_context_t * context, uint16_t * a
sdp_query_context = context;
sdp_client_query_uuid16(&avrcp_handle_sdp_client_query_result, bd_addr, BLUETOOTH_PROTOCOL_AVCTP);
return ERROR_CODE_SUCCESS;
return sdp_client_query_uuid16(&avrcp_handle_sdp_client_query_result, bd_addr, BLUETOOTH_PROTOCOL_AVCTP);
}