mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-10 19:13:23 +00:00
clean up open/close stream api
This commit is contained in:
parent
0bdb280dbe
commit
46e6b06306
@ -932,9 +932,10 @@ typedef uint8_t sm_key_t[16];
|
||||
#define HCI_EVENT_HFP_META 0xE9
|
||||
#define HCI_EVENT_ANCS_META 0xEA
|
||||
#define HCI_EVENT_AVDTP_META 0xEB
|
||||
#define HCI_EVENT_AVRCP_META 0xEC
|
||||
#define HCI_EVENT_GOEP_META 0xED
|
||||
#define HCI_EVENT_PBAP_META 0xEE
|
||||
#define HCI_EVENT_A2DP_META 0xEC
|
||||
#define HCI_EVENT_AVRCP_META 0xED
|
||||
#define HCI_EVENT_GOEP_META 0xEE
|
||||
#define HCI_EVENT_PBAP_META 0xEF
|
||||
|
||||
// Potential other meta groups
|
||||
// #define HCI_EVENT_BNEP_META 0xxx
|
||||
@ -1374,24 +1375,50 @@ typedef uint8_t sm_key_t[16];
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW 0x0D
|
||||
|
||||
|
||||
/** A2DP Subevent */
|
||||
|
||||
/**
|
||||
* @format 1H111
|
||||
* @param subevent_code
|
||||
* @param a2dp_cid
|
||||
* @param local_seid
|
||||
* @param remote_seid
|
||||
* @param status
|
||||
*/
|
||||
#define A2DP_SUBEVENT_STREAM_ESTABLISHED 0x01
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @param subevent_code
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param a2dp_cid
|
||||
* @param local_seid
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_START_STREAMING 0x0E
|
||||
#define A2DP_SUBEVENT_STREAM_START_ACCEPTED 0x02
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @param subevent_code
|
||||
* @param a2dp_cid
|
||||
* @param local_seid
|
||||
*/
|
||||
#define A2DP_SUBEVENT_STREAM_SUSPENDED 0x03
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @param subevent_code
|
||||
* @param avdtp_cid
|
||||
* @param int_seid
|
||||
* @param local_seid
|
||||
*/
|
||||
#define AVDTP_SUBEVENT_STOP_STREAMING 0x0F
|
||||
|
||||
|
||||
#define A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW 0x04
|
||||
|
||||
/**
|
||||
* @format 1H1
|
||||
* @param subevent_code
|
||||
* @param avdtp_cid
|
||||
* @param local_seid
|
||||
*/
|
||||
#define A2DP_SUBEVENT_STREAM_RELEASED 0x05
|
||||
|
||||
/** AVRCP Subevent */
|
||||
|
||||
|
@ -85,6 +85,14 @@ static inline uint8_t hci_event_ancs_meta_get_subevent_code(const uint8_t * even
|
||||
static inline uint8_t hci_event_avdtp_meta_get_subevent_code(const uint8_t * event){
|
||||
return event[2];
|
||||
}
|
||||
/***
|
||||
* @brief Get subevent code for a2dp event
|
||||
* @param event packet
|
||||
* @return subevent_code
|
||||
*/
|
||||
static inline uint8_t hci_event_a2dp_meta_get_subevent_code(const uint8_t * event){
|
||||
return event[2];
|
||||
}
|
||||
/***
|
||||
* @brief Get subevent code for avrcp event
|
||||
* @param event packet
|
||||
@ -4479,40 +4487,115 @@ static inline uint16_t avdtp_subevent_streaming_can_send_media_packet_now_get_se
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_START_STREAMING
|
||||
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return avdtp_cid
|
||||
* @return a2dp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_start_streaming_get_avdtp_cid(const uint8_t * event){
|
||||
static inline hci_con_handle_t a2dp_subevent_stream_established_get_a2dp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_START_STREAMING
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_start_streaming_get_int_seid(const uint8_t * event){
|
||||
static inline uint8_t a2dp_subevent_stream_established_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
/**
|
||||
* @brief Get field remote_seid from event A2DP_SUBEVENT_STREAM_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return remote_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_established_get_remote_seid(const uint8_t * event){
|
||||
return event[6];
|
||||
}
|
||||
/**
|
||||
* @brief Get field status from event A2DP_SUBEVENT_STREAM_ESTABLISHED
|
||||
* @param event packet
|
||||
* @return status
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_established_get_status(const uint8_t * event){
|
||||
return event[7];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_START_ACCEPTED
|
||||
* @param event packet
|
||||
* @return a2dp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t a2dp_subevent_stream_start_accepted_get_a2dp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_START_ACCEPTED
|
||||
* @param event packet
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_start_accepted_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STOP_STREAMING
|
||||
* @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_SUSPENDED
|
||||
* @param event packet
|
||||
* @return a2dp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t a2dp_subevent_stream_suspended_get_a2dp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_SUSPENDED
|
||||
* @param event packet
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_suspended_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field avdtp_cid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
|
||||
* @param event packet
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t avdtp_subevent_stop_streaming_get_avdtp_cid(const uint8_t * event){
|
||||
static inline hci_con_handle_t a2dp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field int_seid from event AVDTP_SUBEVENT_STOP_STREAMING
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
|
||||
* @param event packet
|
||||
* @return int_seid
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t avdtp_subevent_stop_streaming_get_int_seid(const uint8_t * event){
|
||||
static inline uint8_t a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get field avdtp_cid from event A2DP_SUBEVENT_STREAM_RELEASED
|
||||
* @param event packet
|
||||
* @return avdtp_cid
|
||||
* @note: btstack_type H
|
||||
*/
|
||||
static inline hci_con_handle_t a2dp_subevent_stream_released_get_avdtp_cid(const uint8_t * event){
|
||||
return little_endian_read_16(event, 3);
|
||||
}
|
||||
/**
|
||||
* @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_RELEASED
|
||||
* @param event packet
|
||||
* @return local_seid
|
||||
* @note: btstack_type 1
|
||||
*/
|
||||
static inline uint8_t a2dp_subevent_stream_released_get_local_seid(const uint8_t * event){
|
||||
return event[5];
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,34 @@ void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_ha
|
||||
de_add_number(service, DE_UINT, DE_SIZE_16, supported_features);
|
||||
}
|
||||
|
||||
static void a2dp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t cid, uint8_t local_seid, uint8_t remote_seid, uint8_t status){
|
||||
if (!callback) return;
|
||||
uint8_t event[8];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAM_ESTABLISHED;
|
||||
little_endian_store_16(event, pos, cid);
|
||||
pos += 2;
|
||||
event[pos++] = local_seid;
|
||||
event[pos++] = remote_seid;
|
||||
event[pos++] = status;
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void a2dp_streaming_emit_can_send_media_packet_now(btstack_packet_handler_t callback, uint16_t cid, uint8_t seid){
|
||||
if (!callback) return;
|
||||
uint8_t event[8];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW;
|
||||
little_endian_store_16(event, pos, cid);
|
||||
pos += 2;
|
||||
event[pos++] = seid;
|
||||
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
@ -188,6 +216,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
// connection closed -> quit test app
|
||||
printf("\n --- a2dp source --- HCI_EVENT_DISCONNECTION_COMPLETE ---\n");
|
||||
|
||||
break;
|
||||
case HCI_EVENT_AVDTP_META:
|
||||
switch (packet[2]){
|
||||
@ -216,7 +245,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
break;
|
||||
}
|
||||
app_state = A2DP_STREAMING_OPENED;
|
||||
avdtp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, avdtp_cid, int_seid, acp_seid, 0);
|
||||
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, avdtp_cid, int_seid, acp_seid, 0);
|
||||
printf(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED --- avdtp_cid 0x%02x, local seid %d, remote seid %d\n", avdtp_cid, int_seid, acp_seid);
|
||||
break;
|
||||
|
||||
@ -275,7 +304,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
break;
|
||||
}
|
||||
case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
|
||||
avdtp_streaming_emit_can_send_media_packet_now(a2dp_source_context.a2dp_callback, avdtp_cid, 0, 0);
|
||||
a2dp_streaming_emit_can_send_media_packet_now(a2dp_source_context.a2dp_callback, avdtp_cid, 0);
|
||||
break;
|
||||
|
||||
case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
|
||||
@ -326,23 +355,34 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
case AVDTP_SI_START:{
|
||||
uint8_t event[6];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_START_STREAMING;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAM_START_ACCEPTED;
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
|
||||
(*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
break;
|
||||
}
|
||||
case AVDTP_SI_CLOSE:
|
||||
case AVDTP_SI_SUSPEND:
|
||||
case AVDTP_SI_ABORT:{
|
||||
case AVDTP_SI_CLOSE:{
|
||||
uint8_t event[6];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_AVDTP_META;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = AVDTP_SUBEVENT_STOP_STREAMING;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAM_RELEASED;
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
|
||||
(*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
break;
|
||||
}
|
||||
|
||||
case AVDTP_SI_SUSPEND:{
|
||||
uint8_t event[6];
|
||||
int pos = 0;
|
||||
event[pos++] = HCI_EVENT_A2DP_META;
|
||||
event[pos++] = sizeof(event) - 2;
|
||||
event[pos++] = A2DP_SUBEVENT_STREAM_SUSPENDED;
|
||||
little_endian_store_16(event, pos, avdtp_cid);
|
||||
pos += 2;
|
||||
event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
|
||||
@ -411,7 +451,7 @@ uint8_t a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_
|
||||
return local_stream_endpoint->sep.seid;
|
||||
}
|
||||
|
||||
void a2dp_source_connect(bd_addr_t bd_addr, uint8_t local_seid){
|
||||
void a2dp_source_establish_stream(bd_addr_t bd_addr, uint8_t local_seid){
|
||||
sc.local_stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
|
||||
if (!sc.local_stream_endpoint){
|
||||
printf(" no local_stream_endpoint for seid %d\n", local_seid);
|
||||
@ -424,11 +464,116 @@ void a2dp_source_disconnect(uint16_t con_handle){
|
||||
avdtp_disconnect(con_handle, &a2dp_source_context);
|
||||
}
|
||||
|
||||
void a2dp_source_start_stream(uint16_t cid, uint8_t int_seid, uint8_t acp_seid){
|
||||
avdtp_start_stream(cid, int_seid, acp_seid, &a2dp_source_context);
|
||||
void a2dp_source_start_stream(uint8_t int_seid){
|
||||
avdtp_start_stream(int_seid, &a2dp_source_context);
|
||||
}
|
||||
|
||||
void a2dp_source_stop_stream(uint16_t cid, uint8_t int_seid, uint8_t acp_seid){
|
||||
avdtp_stop_stream(cid, int_seid, acp_seid, &a2dp_source_context);
|
||||
void a2dp_source_release_stream(uint8_t int_seid){
|
||||
avdtp_stop_stream(int_seid, &a2dp_source_context);
|
||||
}
|
||||
|
||||
uint8_t a2dp_source_stream_endpoint_ready(uint8_t local_seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
printf("no stream_endpoint");
|
||||
return 0;
|
||||
}
|
||||
return (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING || stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND);
|
||||
}
|
||||
|
||||
|
||||
static void a2dp_source_setup_media_header(uint8_t * media_packet, int size, int *offset, uint8_t marker, uint16_t sequence_number){
|
||||
if (size < 12){
|
||||
printf("small outgoing buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t rtp_version = 2;
|
||||
uint8_t padding = 0;
|
||||
uint8_t extension = 0;
|
||||
uint8_t csrc_count = 0;
|
||||
uint8_t payload_type = 0x60;
|
||||
// uint16_t sequence_number = stream_endpoint->sequence_number;
|
||||
uint32_t timestamp = btstack_run_loop_get_time_ms();
|
||||
uint32_t ssrc = 0x11223344;
|
||||
|
||||
// rtp header (min size 12B)
|
||||
int pos = 0;
|
||||
// int mtu = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
|
||||
|
||||
media_packet[pos++] = (rtp_version << 6) | (padding << 5) | (extension << 4) | csrc_count;
|
||||
media_packet[pos++] = (marker << 1) | payload_type;
|
||||
big_endian_store_16(media_packet, pos, sequence_number);
|
||||
pos += 2;
|
||||
big_endian_store_32(media_packet, pos, timestamp);
|
||||
pos += 4;
|
||||
big_endian_store_32(media_packet, pos, ssrc); // only used for multicast
|
||||
pos += 4;
|
||||
*offset = pos;
|
||||
}
|
||||
|
||||
static void a2dp_source_copy_media_payload(uint8_t * media_packet, int size, int * offset, btstack_ring_buffer_t * sbc_ring_buffer){
|
||||
if (size < 18){
|
||||
printf("small outgoing buffer\n");
|
||||
return;
|
||||
}
|
||||
int pos = *offset;
|
||||
// media payload
|
||||
// sbc_header (size 1B)
|
||||
uint8_t sbc_header_index = pos;
|
||||
pos++;
|
||||
uint8_t fragmentation = 0;
|
||||
uint8_t starting_packet = 0; // set to 1 for the first packet of a fragmented SBC frame
|
||||
uint8_t last_packet = 0; // set to 1 for the last packet of a fragmented SBC frame
|
||||
uint8_t num_frames = 0;
|
||||
|
||||
uint32_t total_sbc_bytes_read = 0;
|
||||
uint8_t sbc_frame_size = 0;
|
||||
// payload
|
||||
uint16_t sbc_frame_bytes = btstack_sbc_encoder_sbc_buffer_length();
|
||||
|
||||
while (size - 13 - total_sbc_bytes_read >= sbc_frame_bytes && btstack_ring_buffer_bytes_available(sbc_ring_buffer)){
|
||||
uint32_t number_of_bytes_read = 0;
|
||||
btstack_ring_buffer_read(sbc_ring_buffer, &sbc_frame_size, 1, &number_of_bytes_read);
|
||||
btstack_ring_buffer_read(sbc_ring_buffer, media_packet + pos, sbc_frame_size, &number_of_bytes_read);
|
||||
pos += sbc_frame_size;
|
||||
total_sbc_bytes_read += sbc_frame_size;
|
||||
num_frames++;
|
||||
// printf("send sbc frame: timestamp %d, seq. nr %d\n", timestamp, stream_endpoint->sequence_number);
|
||||
}
|
||||
media_packet[sbc_header_index] = (fragmentation << 7) | (starting_packet << 6) | (last_packet << 5) | num_frames;
|
||||
*offset = pos;
|
||||
}
|
||||
void a2dp_source_stream_endpoint_request_can_send_now(uint8_t local_seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
printf("no stream_endpoint");
|
||||
return;
|
||||
}
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND;
|
||||
avdtp_request_can_send_now_self(stream_endpoint->connection, stream_endpoint->l2cap_media_cid);
|
||||
}
|
||||
|
||||
void a2dp_source_stream_send_media_payload(uint8_t int_seid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, &a2dp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
printf("no stream_endpoint found for seid %d", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream_endpoint->l2cap_media_cid == 0){
|
||||
printf("no media cid found for seid %d", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
|
||||
int offset = 0;
|
||||
|
||||
l2cap_reserve_packet_buffer();
|
||||
uint8_t * media_packet = l2cap_get_outgoing_buffer();
|
||||
//int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
|
||||
a2dp_source_setup_media_header(media_packet, size, &offset, marker, stream_endpoint->sequence_number);
|
||||
a2dp_source_copy_media_payload(media_packet, size, &offset, sbc_ring_buffer);
|
||||
stream_endpoint->sequence_number++;
|
||||
l2cap_send_prepared(stream_endpoint->l2cap_media_cid, offset);
|
||||
}
|
||||
|
@ -72,21 +72,26 @@ uint8_t a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_
|
||||
uint8_t * codec_capabilities, uint16_t codec_capabilities_len,
|
||||
uint8_t * codec_configuration, uint16_t codec_configuration_len);
|
||||
|
||||
void a2dp_source_connect(bd_addr_t bd_addr, uint8_t local_seid);
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void a2dp_source_establish_stream(bd_addr_t bd_addr, uint8_t local_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void a2dp_source_start_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
|
||||
void a2dp_source_start_stream(uint8_t int_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void a2dp_source_stop_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
|
||||
void a2dp_source_release_stream(uint8_t int_seid);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from device with connection handle.
|
||||
@ -94,6 +99,10 @@ void a2dp_source_stop_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_s
|
||||
*/
|
||||
void a2dp_source_disconnect(uint16_t avdtp_cid);
|
||||
|
||||
|
||||
uint8_t a2dp_source_stream_endpoint_ready(uint8_t local_seid);
|
||||
void a2dp_source_stream_endpoint_request_can_send_now(uint8_t local_seid);
|
||||
void a2dp_source_stream_send_media_payload(uint8_t int_seid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker);
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
|
@ -485,67 +485,52 @@ void avdtp_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, a
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_start_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
printf("avdtp_start_stream: no connection for signaling cid 0x%02x found\n", avdtp_cid);
|
||||
return;
|
||||
}
|
||||
if (avdtp_find_remote_sep(connection, acp_seid) == 0xFF){
|
||||
printf("avdtp_start_stream: no remote sep for seid %d found\n", acp_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
|
||||
printf("avdtp_start_stream: wrong connection state %d\n", connection->state);
|
||||
return;
|
||||
}
|
||||
|
||||
void avdtp_start_stream(uint8_t int_seid, avdtp_context_t * context){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
printf("avdtp_start_stream: no stream_endpoint with seid %d found\n", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
avdtp_connection_t * connection = stream_endpoint->connection;
|
||||
if (!connection){
|
||||
printf("avdtp_start_stream: no connection for seid %d found\n", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream_endpoint->remote_sep_index == 0xFF) return;
|
||||
if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_OPENED) return;
|
||||
connection->initiator_transaction_label++;
|
||||
connection->acp_seid = acp_seid;
|
||||
connection->acp_seid = stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid;
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_START;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
void avdtp_stop_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context){
|
||||
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
|
||||
if (!connection){
|
||||
printf("avdtp_stop_stream: no connection for signaling cid 0x%02x found\n", avdtp_cid);
|
||||
return;
|
||||
}
|
||||
if (avdtp_find_remote_sep(connection, acp_seid) == 0xFF){
|
||||
printf("avdtp_stop_stream: no remote sep for seid %d found\n", acp_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
|
||||
printf("avdtp_stop_stream: wrong connection state %d\n", connection->state);
|
||||
return;
|
||||
}
|
||||
|
||||
void avdtp_stop_stream(uint8_t int_seid, avdtp_context_t * context){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
|
||||
if (!stream_endpoint) {
|
||||
printf("avdtp_stop_stream: no stream_endpoint with seid %d found\n", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream_endpoint->remote_sep_index == 0xFF) return;
|
||||
|
||||
switch (stream_endpoint->state){
|
||||
case AVDTP_STREAM_ENDPOINT_OPENED:
|
||||
case AVDTP_STREAM_ENDPOINT_STREAMING:
|
||||
|
||||
if (!stream_endpoint->connection){
|
||||
printf("avdtp_stop_stream: no connection for seid %d found\n",stream_endpoint->sep.seid);
|
||||
return;
|
||||
}
|
||||
|
||||
printf(" AVDTP_INITIATOR_W2_STREAMING_STOP \n");
|
||||
connection->initiator_transaction_label++;
|
||||
connection->acp_seid = acp_seid;
|
||||
connection->int_seid = stream_endpoint->sep.seid;
|
||||
stream_endpoint->connection->initiator_transaction_label++;
|
||||
stream_endpoint->connection->acp_seid = stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid;
|
||||
stream_endpoint->connection->int_seid = stream_endpoint->sep.seid;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_STOP;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
avdtp_request_can_send_now_initiator(stream_endpoint->connection, stream_endpoint->connection->l2cap_signaling_cid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -491,8 +491,8 @@ avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type
|
||||
|
||||
void avdtp_disconnect(uint16_t avdtp_cid, avdtp_context_t * context);
|
||||
void avdtp_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_start_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_stop_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context);
|
||||
void avdtp_start_stream(uint8_t int_seid, avdtp_context_t * context);
|
||||
void avdtp_stop_stream (uint8_t int_seid, avdtp_context_t * context);
|
||||
void avdtp_abort_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context);
|
||||
|
||||
void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context);
|
||||
|
@ -155,12 +155,12 @@ void avdtp_sink_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_se
|
||||
avdtp_open_stream(avdtp_cid, int_seid, acp_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_start_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid){
|
||||
avdtp_start_stream(avdtp_cid, int_seid, acp_seid, &avdtp_sink_context);
|
||||
void avdtp_sink_start_stream(uint8_t int_seid){
|
||||
avdtp_start_stream(int_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_stop_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid){
|
||||
avdtp_stop_stream(avdtp_cid, int_seid, acp_seid, &avdtp_sink_context);
|
||||
void avdtp_sink_stop_stream(uint8_t int_seid){
|
||||
avdtp_stop_stream(int_seid, &avdtp_sink_context);
|
||||
}
|
||||
|
||||
void avdtp_sink_abort_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid){
|
||||
|
@ -150,7 +150,7 @@ void avdtp_sink_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_se
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_sink_start_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
|
||||
void avdtp_sink_start_stream(uint8_t int_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
@ -164,7 +164,7 @@ void avdtp_sink_abort_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_s
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_sink_stop_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
|
||||
void avdtp_sink_stop_stream(uint8_t int_seid);
|
||||
|
||||
/* API_END */
|
||||
|
||||
|
@ -125,12 +125,12 @@ void avdtp_source_open_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp
|
||||
avdtp_open_stream(con_handle, int_seid, acp_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_start_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
|
||||
avdtp_start_stream(con_handle, int_seid, acp_seid, avdtp_source_context);
|
||||
void avdtp_source_start_stream(uint8_t int_seid){
|
||||
avdtp_start_stream(int_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_stop_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
|
||||
avdtp_stop_stream(con_handle, int_seid, acp_seid, avdtp_source_context);
|
||||
void avdtp_source_stop_stream(uint8_t int_seid){
|
||||
avdtp_stop_stream(int_seid, avdtp_source_context);
|
||||
}
|
||||
|
||||
void avdtp_source_abort_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
|
||||
@ -183,113 +183,6 @@ void avdtp_source_init(avdtp_context_t * avdtp_context){
|
||||
l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0);
|
||||
}
|
||||
|
||||
int avdtp_source_stream_endpoint_ready(uint8_t local_seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, avdtp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
printf("no stream_endpoint");
|
||||
return 0;
|
||||
}
|
||||
return (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING || stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND);
|
||||
}
|
||||
|
||||
void avdtp_source_stream_endpoint_request_can_send_now(uint8_t local_seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, avdtp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
printf("no stream_endpoint");
|
||||
return;
|
||||
}
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND;
|
||||
avdtp_request_can_send_now_self(stream_endpoint->connection, stream_endpoint->l2cap_media_cid);
|
||||
}
|
||||
|
||||
|
||||
static void avdtp_source_setup_media_header(uint8_t * media_packet, int size, int *offset, uint8_t marker, uint16_t sequence_number){
|
||||
if (size < 12){
|
||||
printf("small outgoing buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t rtp_version = 2;
|
||||
uint8_t padding = 0;
|
||||
uint8_t extension = 0;
|
||||
uint8_t csrc_count = 0;
|
||||
uint8_t payload_type = 0x60;
|
||||
// uint16_t sequence_number = stream_endpoint->sequence_number;
|
||||
uint32_t timestamp = btstack_run_loop_get_time_ms();
|
||||
uint32_t ssrc = 0x11223344;
|
||||
|
||||
// rtp header (min size 12B)
|
||||
int pos = 0;
|
||||
// int mtu = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
|
||||
|
||||
media_packet[pos++] = (rtp_version << 6) | (padding << 5) | (extension << 4) | csrc_count;
|
||||
media_packet[pos++] = (marker << 1) | payload_type;
|
||||
big_endian_store_16(media_packet, pos, sequence_number);
|
||||
pos += 2;
|
||||
big_endian_store_32(media_packet, pos, timestamp);
|
||||
pos += 4;
|
||||
big_endian_store_32(media_packet, pos, ssrc); // only used for multicast
|
||||
pos += 4;
|
||||
*offset = pos;
|
||||
}
|
||||
|
||||
static void avdtp_source_copy_media_payload(uint8_t * media_packet, int size, int * offset, btstack_ring_buffer_t * sbc_ring_buffer){
|
||||
if (size < 18){
|
||||
printf("small outgoing buffer\n");
|
||||
return;
|
||||
}
|
||||
int pos = *offset;
|
||||
// media payload
|
||||
// sbc_header (size 1B)
|
||||
uint8_t sbc_header_index = pos;
|
||||
pos++;
|
||||
uint8_t fragmentation = 0;
|
||||
uint8_t starting_packet = 0; // set to 1 for the first packet of a fragmented SBC frame
|
||||
uint8_t last_packet = 0; // set to 1 for the last packet of a fragmented SBC frame
|
||||
uint8_t num_frames = 0;
|
||||
|
||||
uint32_t total_sbc_bytes_read = 0;
|
||||
uint8_t sbc_frame_size = 0;
|
||||
// payload
|
||||
uint16_t sbc_frame_bytes = btstack_sbc_encoder_sbc_buffer_length();
|
||||
|
||||
while (size - 13 - total_sbc_bytes_read >= sbc_frame_bytes && btstack_ring_buffer_bytes_available(sbc_ring_buffer)){
|
||||
uint32_t number_of_bytes_read = 0;
|
||||
btstack_ring_buffer_read(sbc_ring_buffer, &sbc_frame_size, 1, &number_of_bytes_read);
|
||||
btstack_ring_buffer_read(sbc_ring_buffer, media_packet + pos, sbc_frame_size, &number_of_bytes_read);
|
||||
pos += sbc_frame_size;
|
||||
total_sbc_bytes_read += sbc_frame_size;
|
||||
num_frames++;
|
||||
// printf("send sbc frame: timestamp %d, seq. nr %d\n", timestamp, stream_endpoint->sequence_number);
|
||||
}
|
||||
media_packet[sbc_header_index] = (fragmentation << 7) | (starting_packet << 6) | (last_packet << 5) | num_frames;
|
||||
*offset = pos;
|
||||
}
|
||||
|
||||
void avdtp_source_stream_send_media_payload(uint8_t int_seid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, avdtp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
printf("no stream_endpoint found for seid %d", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream_endpoint->l2cap_media_cid == 0){
|
||||
printf("no media cid found for seid %d", int_seid);
|
||||
return;
|
||||
}
|
||||
|
||||
int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
|
||||
int offset = 0;
|
||||
|
||||
l2cap_reserve_packet_buffer();
|
||||
uint8_t * media_packet = l2cap_get_outgoing_buffer();
|
||||
//int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
|
||||
avdtp_source_setup_media_header(media_packet, size, &offset, marker, stream_endpoint->sequence_number);
|
||||
avdtp_source_copy_media_payload(media_packet, size, &offset, sbc_ring_buffer);
|
||||
stream_endpoint->sequence_number++;
|
||||
l2cap_send_prepared(stream_endpoint->l2cap_media_cid, offset);
|
||||
}
|
||||
|
||||
uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid){
|
||||
return avdtp_remote_seps_num(avdtp_cid, avdtp_source_context);
|
||||
}
|
||||
|
@ -129,14 +129,14 @@ void avdtp_source_suspend(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_source_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
|
||||
void avdtp_source_open_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_source_start_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
|
||||
void avdtp_source_start_stream(uint8_t int_seid);
|
||||
|
||||
/**
|
||||
* @brief Start stream
|
||||
@ -150,14 +150,10 @@ void avdtp_source_abort_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp
|
||||
* @param avdtp_cid
|
||||
* @param seid
|
||||
*/
|
||||
void avdtp_source_stop_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
|
||||
void avdtp_source_stop_stream(uint8_t int_seid);
|
||||
|
||||
avdtp_stream_endpoint_t * avdtp_source_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type);
|
||||
|
||||
void avdtp_source_stream_endpoint_request_can_send_now(uint8_t local_seid);
|
||||
int avdtp_source_stream_endpoint_ready(uint8_t local_seid);
|
||||
void avdtp_source_stream_send_media_payload(uint8_t local_seid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker);
|
||||
|
||||
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 */
|
||||
|
@ -605,7 +605,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
break;
|
||||
case 'm':
|
||||
app_state = AVDTP_APPLICATION_W2_START_STREAM_WITH_SEID;
|
||||
avdtp_sink_start_stream(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid);
|
||||
avdtp_sink_start_stream(local_stream_endpoint->sep.seid);
|
||||
break;
|
||||
case 'A':
|
||||
app_state = AVDTP_APPLICATION_W2_ABORT_STREAM_WITH_SEID;
|
||||
@ -613,7 +613,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
break;
|
||||
case 'S':
|
||||
app_state = AVDTP_APPLICATION_W2_STOP_STREAM_WITH_SEID;
|
||||
avdtp_sink_stop_stream(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid);
|
||||
avdtp_sink_stop_stream(local_stream_endpoint->sep.seid);
|
||||
break;
|
||||
case 'P':
|
||||
app_state = AVDTP_APPLICATION_W2_SUSPEND_STREAM_WITH_SEID;
|
||||
|
@ -109,8 +109,8 @@ static uint8_t sbc_storage[44100*4];
|
||||
|
||||
typedef struct {
|
||||
uint16_t a2dp_cid;
|
||||
uint8_t int_seid;
|
||||
uint8_t acp_seid;
|
||||
uint8_t local_seid;
|
||||
uint8_t remote_seid;
|
||||
|
||||
uint32_t fill_audio_ring_buffer_timeout_ms;
|
||||
uint32_t time_audio_data_sent; // ms
|
||||
@ -130,65 +130,56 @@ static modcontext mod_context;
|
||||
static tracker_buffer_state trkbuf;
|
||||
|
||||
static uint8_t local_seid = 0;
|
||||
a2dp_state_t app_state = A2DP_IDLE;
|
||||
stream_data_source_t data_source = STREAM_SINE;
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static void avdtp_fill_audio_ring_buffer_timer_start(a2dp_media_sending_context_t * context);
|
||||
static void avdtp_fill_audio_ring_buffer_timer_stop(a2dp_media_sending_context_t * context);
|
||||
static void a2dp_fill_audio_ring_buffer_timer_start(a2dp_media_sending_context_t * context);
|
||||
static void a2dp_fill_audio_ring_buffer_timer_stop(a2dp_media_sending_context_t * context);
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
UNUSED(channel);
|
||||
UNUSED(size);
|
||||
|
||||
bd_addr_t event_addr;
|
||||
switch (packet_type) {
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (hci_event_packet_get_type(packet)) {
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
// inform about pin code request
|
||||
printf("Pin code request - using '0000'\n");
|
||||
hci_event_pin_code_request_get_bd_addr(packet, event_addr);
|
||||
hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
|
||||
break;
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
// connection closed -> quit test app
|
||||
printf("\n --- application --- HCI_EVENT_DISCONNECTION_COMPLETE ---\n");
|
||||
break;
|
||||
case HCI_EVENT_AVDTP_META:
|
||||
case HCI_EVENT_A2DP_META:
|
||||
switch (packet[2]){
|
||||
case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
|
||||
media_tracker.int_seid = avdtp_subevent_streaming_connection_established_get_int_seid(packet);
|
||||
media_tracker.acp_seid = avdtp_subevent_streaming_connection_established_get_acp_seid(packet);
|
||||
media_tracker.a2dp_cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet);
|
||||
printf(" --- application --- AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED --- a2dp_cid 0x%02x, local seid %d, remote seid %d\n",
|
||||
media_tracker.a2dp_cid, media_tracker.int_seid, media_tracker.acp_seid);
|
||||
case A2DP_SUBEVENT_STREAM_ESTABLISHED:
|
||||
media_tracker.local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
|
||||
media_tracker.remote_seid = a2dp_subevent_stream_established_get_remote_seid(packet);
|
||||
media_tracker.a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_ESTABLISHED, a2dp_cid 0x%02x, local seid %d, remote seid %d\n",
|
||||
media_tracker.a2dp_cid, media_tracker.local_seid, media_tracker.remote_seid);
|
||||
break;
|
||||
|
||||
case AVDTP_SUBEVENT_START_STREAMING:
|
||||
if (local_seid != media_tracker.int_seid) break;
|
||||
if (!avdtp_source_stream_endpoint_ready(media_tracker.int_seid)) break;
|
||||
printf(" --- application --- start streaming : int seid %d\n", media_tracker.int_seid);
|
||||
avdtp_fill_audio_ring_buffer_timer_start(&media_tracker);
|
||||
case A2DP_SUBEVENT_STREAM_START_ACCEPTED:
|
||||
if (local_seid != media_tracker.local_seid) break;
|
||||
if (!a2dp_source_stream_endpoint_ready(media_tracker.local_seid)) break;
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_START_ACCEPTED, local seid %d\n", media_tracker.local_seid);
|
||||
a2dp_fill_audio_ring_buffer_timer_start(&media_tracker);
|
||||
break;
|
||||
|
||||
case AVDTP_SUBEVENT_STOP_STREAMING:
|
||||
if (local_seid != media_tracker.int_seid) break;
|
||||
avdtp_fill_audio_ring_buffer_timer_stop(&media_tracker);
|
||||
break;
|
||||
|
||||
case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
|
||||
if (local_seid != media_tracker.int_seid) break;
|
||||
avdtp_source_stream_send_media_payload(media_tracker.int_seid, &media_tracker.sbc_ring_buffer, 0);
|
||||
case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
|
||||
if (local_seid != media_tracker.local_seid) break;
|
||||
a2dp_source_stream_send_media_payload(media_tracker.local_seid, &media_tracker.sbc_ring_buffer, 0);
|
||||
if (btstack_ring_buffer_bytes_available(&media_tracker.sbc_ring_buffer)){
|
||||
avdtp_source_stream_endpoint_request_can_send_now(media_tracker.int_seid);
|
||||
a2dp_source_stream_endpoint_request_can_send_now(media_tracker.local_seid);
|
||||
}
|
||||
break;
|
||||
|
||||
case A2DP_SUBEVENT_STREAM_SUSPENDED:
|
||||
if (local_seid != media_tracker.local_seid) break;
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_SUSPENDED, local seid %d\n", media_tracker.local_seid);
|
||||
a2dp_fill_audio_ring_buffer_timer_stop(&media_tracker);
|
||||
break;
|
||||
|
||||
case A2DP_SUBEVENT_STREAM_RELEASED:
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_RELEASED, local seid %d\n", media_tracker.local_seid);
|
||||
break;
|
||||
default:
|
||||
app_state = A2DP_IDLE;
|
||||
printf(" --- application --- not implemented\n");
|
||||
break;
|
||||
}
|
||||
@ -306,11 +297,11 @@ static void avdtp_fill_audio_ring_buffer_timeout_handler(btstack_timer_source_t
|
||||
int total_num_bytes_read = fill_sbc_ring_buffer(context);
|
||||
// schedule sending
|
||||
if (total_num_bytes_read != 0){
|
||||
avdtp_source_stream_endpoint_request_can_send_now(context->int_seid);
|
||||
a2dp_source_stream_endpoint_request_can_send_now(context->local_seid);
|
||||
}
|
||||
}
|
||||
|
||||
static void avdtp_fill_audio_ring_buffer_timer_start(a2dp_media_sending_context_t * context){
|
||||
static void a2dp_fill_audio_ring_buffer_timer_start(a2dp_media_sending_context_t * context){
|
||||
btstack_run_loop_remove_timer(&context->fill_audio_ring_buffer_timer);
|
||||
btstack_run_loop_set_timer_handler(&context->fill_audio_ring_buffer_timer, avdtp_fill_audio_ring_buffer_timeout_handler);
|
||||
btstack_run_loop_set_timer_context(&context->fill_audio_ring_buffer_timer, context);
|
||||
@ -318,7 +309,7 @@ static void avdtp_fill_audio_ring_buffer_timer_start(a2dp_media_sending_context_
|
||||
btstack_run_loop_add_timer(&context->fill_audio_ring_buffer_timer);
|
||||
}
|
||||
|
||||
static void avdtp_fill_audio_ring_buffer_timer_stop(a2dp_media_sending_context_t * context){
|
||||
static void a2dp_fill_audio_ring_buffer_timer_stop(a2dp_media_sending_context_t * context){
|
||||
btstack_run_loop_remove_timer(&context->fill_audio_ring_buffer_timer);
|
||||
}
|
||||
|
||||
@ -338,18 +329,18 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
switch (cmd){
|
||||
case 'c':
|
||||
printf("Creating L2CAP Connection to %s, PSM_AVDTP\n", bd_addr_to_str(remote));
|
||||
a2dp_source_connect(remote, local_seid);
|
||||
a2dp_source_establish_stream(remote, local_seid);
|
||||
break;
|
||||
case 'C':
|
||||
printf("Disconnect not implemented\n");
|
||||
a2dp_source_disconnect(media_tracker.a2dp_cid);
|
||||
break;
|
||||
case 'x':
|
||||
printf(" --- application --- a2dp_source_stream_data_start --- local seid %d, remote seid %d\n", media_tracker.int_seid, media_tracker.acp_seid);
|
||||
a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.int_seid, media_tracker.acp_seid);
|
||||
printf(" --- application --- a2dp_source_stream_data_start --- local seid %d, remote seid %d\n", media_tracker.local_seid, media_tracker.remote_seid);
|
||||
a2dp_source_start_stream(media_tracker.local_seid);
|
||||
break;
|
||||
case 'X':
|
||||
a2dp_source_stop_stream(media_tracker.a2dp_cid, media_tracker.int_seid, media_tracker.acp_seid);
|
||||
a2dp_source_release_stream(media_tracker.local_seid);
|
||||
break;
|
||||
default:
|
||||
show_usage();
|
||||
|
@ -11,6 +11,7 @@ import btstack_parser as parser
|
||||
meta_events = [
|
||||
'ANCS',
|
||||
'AVDTP',
|
||||
'A2DP',
|
||||
'AVRCP',
|
||||
'GOEP',
|
||||
'HFP',
|
||||
|
Loading…
x
Reference in New Issue
Block a user