mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-29 13:20:39 +00:00
a2dp source: handle incoming connection, send event to client on signaling connection established
This commit is contained in:
parent
2f6083d0d8
commit
5448c259b2
@ -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:
|
||||
|
@ -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 */
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user