avdtp: introduced avdtp cid on connect; cmd functions return now status; use local and remote sedi in events instead of initiator and acceptor seid

This commit is contained in:
Milanka Ringwald 2017-07-11 23:10:59 +02:00
parent f39cc24ddf
commit 4ccacc40ad
19 changed files with 701 additions and 519 deletions

View File

@ -169,9 +169,10 @@ typedef struct {
#ifdef HAVE_BTSTACK_STDIN
// mac 2011: static bd_addr_t remote = {0x04, 0x0C, 0xCE, 0xE4, 0x85, 0xD3};
// pts: static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5};
// mac 2013: static const char * device_addr_string = "00:1B:DC:08:0A:A5";
// iPhone 5S:
static const char * device_addr_string = "54:E4:3A:26:A2:39";
// mac 2013:
// mac 2013:
static const char * device_addr_string = "84:38:35:65:d1:15";
// iPhone 5S: static const char * device_addr_string = "54:E4:3A:26:A2:39";
#endif
// bt dongle: -u 02-02 static bd_addr_t remote = {0x00, 0x02, 0x72, 0xDC, 0x31, 0xC1};
@ -719,6 +720,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
UNUSED(channel);
UNUSED(size);
uint8_t status;
uint16_t cid;
switch (packet_type) {
case HCI_EVENT_PACKET:
@ -750,60 +752,61 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
break;
}
case A2DP_SUBEVENT_STREAM_ESTABLISHED:
cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
if (cid != a2dp_cid) break;
status = a2dp_subevent_stream_established_get_status(packet);
if (status != 0){
printf(" -- a2dp sink demo: streaming connection cannot be established, status 0x%02X\n", status);
app_state = AVDTP_APPLICATION_IDLE;
break;
}
// TODO: check it it the correct a2dp cid
a2dp_cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
printf(" -- a2dp sink demo: streaming connection is established, a2dp cid 0x%02X\n", status);
local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
printf(" -- a2dp sink demo: streaming connection is established, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid);
app_state = AVDTP_APPLICATION_STREAMING;
break;
case A2DP_SUBEVENT_STREAM_STARTED:
cid = a2dp_subevent_stream_started_get_a2dp_cid(packet);
if (cid != a2dp_cid) break;
status = a2dp_subevent_stream_started_get_status(packet);
if (status != 0){
printf(" -- a2dp sink demo: stream cannot be started, status 0x%02X\n", status);
app_state = AVDTP_APPLICATION_IDLE;
break;
}
// TODO: check it it the correct a2dp cid
a2dp_cid = a2dp_subevent_stream_started_get_a2dp_cid(packet);
printf(" -- a2dp sink demo: streaming, a2dp cid 0x%02X\n", status);
local_seid = a2dp_subevent_stream_started_get_local_seid(packet);
printf(" -- a2dp sink demo: stream started, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid);
// started
// media_processing_init(sbc_configuration);
break;
case A2DP_SUBEVENT_STREAM_SUSPENDED:
cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet);
if (cid != a2dp_cid) break;
status = a2dp_subevent_stream_suspended_get_status(packet);
if (status != 0){
printf(" -- a2dp sink demo: stream cannot be paused, status 0x%02X\n", status);
break;
}
// TODO: check it it the correct a2dp cid
a2dp_cid = a2dp_subevent_stream_started_get_a2dp_cid(packet);
printf(" -- a2dp sink demo: stream paused, a2dp cid 0x%02X\n", status);
local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet);
printf(" -- a2dp sink demo: stream paused, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid);
// paused/stopped
// media_processing_close();
break;
break;
case A2DP_SUBEVENT_STREAM_RELEASED:
cid = a2dp_subevent_stream_released_get_a2dp_cid(packet);
if (cid != a2dp_cid) break;
status = a2dp_subevent_stream_released_get_status(packet);
if (status != 0){
printf(" -- a2dp sink demo: stream cannot be released, status 0x%02X\n", status);
break;
}
// TODO: check it it the correct a2dp cid
a2dp_cid = a2dp_subevent_stream_released_get_a2dp_cid(packet);
local_seid = a2dp_subevent_stream_released_get_local_seid(packet);
app_state = AVDTP_APPLICATION_IDLE;
printf(" -- a2dp sink demo: stream released, a2dp cid 0x%02X\n", status);
printf(" -- a2dp sink demo: stream released, a2dp cid 0x%02X, local_seid %d\n", a2dp_cid, local_seid);
// paused/stopped
media_processing_close();
@ -881,7 +884,7 @@ static void stdin_process(char cmd){
switch (cmd){
case 'b':
printf("Creating L2CAP Connection to %s, PSM_AVDTP\n", bd_addr_to_str(device_addr));
a2dp_sink_establish_stream(device_addr, local_seid);
a2dp_sink_establish_stream(device_addr, local_seid, &a2dp_cid);
break;
case 'B':
printf("Disconnect\n");

View File

@ -174,11 +174,12 @@ static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
static uint16_t avdtp_cid = 0;
static uint8_t sdp_avdtp_sink_service_buffer[150];
static avdtp_sep_t sep;
// static avdtp_sep_t sep;
static uint8_t local_seid;
static uint8_t remote_seid;
static avdtp_context_t adtvp_sink_context;
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;
@ -190,6 +191,7 @@ static avdtp_capabilities_t remote_configuration;
typedef enum {
AVDTP_APPLICATION_IDLE,
AVDTP_APPLICATION_CONNECTED,
AVDTP_APPLICATION_STREAM_ESTABLISHED,
AVDTP_APPLICATION_STREAMING
} avdtp_application_state_t;
@ -552,16 +554,6 @@ static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endp
#endif
}
static void dump_sbc_capability(adtvp_media_codec_information_sbc_t media_codec_sbc){
printf("Received media codec capability:\n");
printf(" - sampling_frequency: 0x%02x\n", media_codec_sbc.sampling_frequency_bitmap);
printf(" - channel_mode: 0x%02x\n", media_codec_sbc.channel_mode_bitmap);
printf(" - block_length: 0x%02x\n", media_codec_sbc.block_length_bitmap);
printf(" - subbands: 0x%02x\n", media_codec_sbc.subbands_bitmap);
printf(" - allocation_method: 0x%02x\n", media_codec_sbc.allocation_method_bitmap);
printf(" - bitpool_value [%d, %d] \n", media_codec_sbc.min_bitpool_value, media_codec_sbc.max_bitpool_value);
}
static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configuration){
printf("Received media codec configuration:\n");
printf(" - num_channels: %d\n", configuration.num_channels);
@ -575,15 +567,17 @@ static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configu
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) {
uint16_t cid;
uint8_t status;
uint8_t seid;
switch (packet_type){
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(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");
@ -593,34 +587,16 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case HCI_EVENT_DISCONNECTION_COMPLETE:
// connection closed -> quit test app
app_state = AVDTP_APPLICATION_IDLE;
printf("\n --- avdtp_test: HCI_EVENT_DISCONNECTION_COMPLETE ---\n");
printf("\n --- AVDTP Sink Demo: HCI_EVENT_DISCONNECTION_COMPLETE ---\n");
media_processing_close();
break;
case HCI_EVENT_AVDTP_META:
switch (packet[2]){
case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
if (cid != avdtp_cid) break;
app_state = AVDTP_APPLICATION_CONNECTED;
avdtp_cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
printf("\n --- avdtp_test: AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, cid 0x%02x ---\n", avdtp_cid);
break;
case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:
if (app_state < AVDTP_APPLICATION_CONNECTED) return;
sep.seid = avdtp_subevent_signaling_sep_found_get_seid(packet);
sep.in_use = avdtp_subevent_signaling_sep_found_get_in_use(packet);
sep.media_type = avdtp_subevent_signaling_sep_found_get_media_type(packet);
sep.type = avdtp_subevent_signaling_sep_found_get_sep_type(packet);
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 (app_state < AVDTP_APPLICATION_CONNECTED) return;
sbc_capability.sampling_frequency_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet);
sbc_capability.channel_mode_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet);
sbc_capability.block_length_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet);
sbc_capability.subbands_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet);
sbc_capability.allocation_method_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet);
sbc_capability.min_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet);
sbc_capability.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet);
dump_sbc_capability(sbc_capability);
printf("\n --- AVDTP Sink Demo: AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, cid 0x%02x ---\n", cid);
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
if (app_state < AVDTP_APPLICATION_CONNECTED) return;
@ -646,16 +622,36 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
}
break;
}
case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
app_state = AVDTP_APPLICATION_STREAMING;
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY:
printf(" received non SBC codec. not implemented\n");
break;
case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
// signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
// cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet);
// loc_seid = avdtp_subevent_signaling_accept_get_local_seid(packet);
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY:
printf("\n --- AVDTP Sink Demo: received non SBC codec. not implemented\n");
break;
case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
status = avdtp_subevent_streaming_connection_established_get_status(packet);
if (status){
printf("\n --- AVDTP Sink Demo: Stream establish failed with status 0x%02x\n", status);
break;
}
seid = avdtp_subevent_streaming_connection_established_get_local_seid(packet);
if (seid != local_seid){
printf("\n --- AVDTP Sink Demo:strema establich with wrong local seid, received %d, expected %d seid\n", seid, local_seid);
break;
}
remote_seid = avdtp_subevent_streaming_connection_established_get_remote_seid(packet);
app_state = AVDTP_APPLICATION_STREAMING;
printf("\n --- AVDTP Sink Demo: Stream established \n");
break;
default:
printf(" not implemented\n");
printf("\n --- AVDTP Sink Demo: not implemented %02x\n", packet[2]);
break;
}
break;
@ -674,19 +670,21 @@ static void show_usage(void){
bd_addr_t iut_address;
gap_local_bd_addr(iut_address);
printf("\n--- Bluetooth AVDTP SINK Test Console %s ---\n", bd_addr_to_str(iut_address));
printf("c - create connection to addr %s\n", bd_addr_to_str(remote));
printf("c - establish stream to addr %s\n", bd_addr_to_str(remote));
printf("C - disconnect\n");
printf("d - discover stream endpoints\n");
printf("g - get capabilities\n");
printf("a - get all capabilities\n");
printf("s - set configuration\n");
printf("f - get configuration\n");
printf("R - reconfigure stream with %d\n", sep.seid);
printf("o - open stream with seid %d\n", sep.seid);
printf("m - start stream with %d\n", sep.seid);
printf("A - abort stream with %d\n", sep.seid);
printf("S - stop stream with %d\n", sep.seid);
printf("P - suspend stream with %d\n", sep.seid);
if (remote_seid){
printf("R - reconfigure stream with %d\n", remote_seid);
printf("o - open stream with seid %d\n", remote_seid);
printf("m - start stream with %d\n", remote_seid);
printf("A - abort stream with %d\n", remote_seid);
printf("S - stop stream with %d\n", remote_seid);
printf("P - suspend stream with %d\n", remote_seid);
}
printf("Ctrl-c - exit\n");
printf("---\n");
}
@ -712,11 +710,11 @@ static uint8_t media_sbc_codec_reconfiguration[] = {
};
static void stdin_process(char cmd){
sep.seid = 1;
uint8_t status = 0;
switch (cmd){
case 'c':
printf("Creating L2CAP Connection to %s, BLUETOOTH_PROTOCOL_AVDTP\n", bd_addr_to_str(remote));
avdtp_sink_connect(remote);
avdtp_sink_connect(remote, &avdtp_cid);
break;
case 'C':
printf("Disconnect\n");
@ -726,13 +724,13 @@ static void stdin_process(char cmd){
avdtp_sink_discover_stream_endpoints(avdtp_cid);
break;
case 'g':
avdtp_sink_get_capabilities(avdtp_cid, sep.seid);
avdtp_sink_get_capabilities(avdtp_cid, remote_seid);
break;
case 'a':
avdtp_sink_get_all_capabilities(avdtp_cid, sep.seid);
avdtp_sink_get_all_capabilities(avdtp_cid, remote_seid);
break;
case 'f':
avdtp_sink_get_configuration(avdtp_cid, sep.seid);
avdtp_sink_get_configuration(avdtp_cid, remote_seid);
break;
case 's':
remote_configuration_bitmap = store_bit16(remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
@ -740,7 +738,7 @@ static void stdin_process(char cmd){
remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
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(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
avdtp_sink_set_configuration(avdtp_cid, avdtp_local_seid(local_stream_endpoint), remote_seid, remote_configuration_bitmap, remote_configuration);
break;
case 'R':
remote_configuration_bitmap = store_bit16(remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
@ -748,22 +746,27 @@ static void stdin_process(char cmd){
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(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
avdtp_sink_reconfigure(avdtp_cid, avdtp_local_seid(local_stream_endpoint), remote_seid, remote_configuration_bitmap, remote_configuration);
break;
case 'o':
avdtp_sink_open_stream(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid);
printf("avdtp_sink_open_stream: cid %d, local seid %d, remote seid %d\n", avdtp_cid, avdtp_local_seid(local_stream_endpoint), remote_seid);
status = avdtp_sink_open_stream(avdtp_cid, avdtp_local_seid(local_stream_endpoint), remote_seid);
break;
case 'm':
avdtp_sink_start_stream(local_stream_endpoint->sep.seid);
printf("avdtp_sink_start_stream: cid %d, local seid %d, remote seid %d\n", avdtp_cid, avdtp_local_seid(local_stream_endpoint), remote_seid);
status = avdtp_sink_start_stream(avdtp_cid, avdtp_local_seid(local_stream_endpoint));
break;
case 'A':
avdtp_sink_abort_stream(local_stream_endpoint->sep.seid);
printf("avdtp_sink_abort_stream: cid %d, local seid %d, remote seid %d\n", avdtp_cid, avdtp_local_seid(local_stream_endpoint), remote_seid);
status = avdtp_sink_abort_stream(avdtp_cid, avdtp_local_seid(local_stream_endpoint));
break;
case 'S':
avdtp_sink_stop_stream(local_stream_endpoint->sep.seid);
printf("avdtp_sink_stop_stream: cid %d, local seid %d, remote seid %d\n", avdtp_cid, avdtp_local_seid(local_stream_endpoint), remote_seid);
status = avdtp_sink_stop_stream(avdtp_cid, avdtp_local_seid(local_stream_endpoint));
break;
case 'P':
avdtp_sink_suspend(local_stream_endpoint->sep.seid);
printf("avdtp_sink_suspend: cid %d, local seid %d, remote seid %d\n", avdtp_cid, avdtp_local_seid(local_stream_endpoint), remote_seid);
status = avdtp_sink_suspend(avdtp_cid, avdtp_local_seid(local_stream_endpoint));
break;
case '\n':
@ -774,6 +777,9 @@ static void stdin_process(char cmd){
break;
}
if (status != 0){
printf("Command failed with status %d\n", status);
}
}
#endif
@ -795,9 +801,11 @@ int btstack_main(int argc, const char * argv[]){
//#ifndef SMG_BI
local_stream_endpoint = avdtp_sink_create_stream_endpoint(AVDTP_SINK, AVDTP_AUDIO);
local_stream_endpoint->sep.seid = 1;
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));
local_stream_endpoint->sep.seid = 5;
local_seid = local_stream_endpoint->sep.seid;
avdtp_sink_register_media_transport_category(avdtp_local_seid(local_stream_endpoint));
avdtp_sink_register_media_codec_category(avdtp_local_seid(local_stream_endpoint), 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

@ -171,7 +171,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case A2DP_SUBEVENT_STREAM_STARTED:
if (local_seid != media_tracker.local_seid) break;
if (!a2dp_source_stream_endpoint_ready(media_tracker.local_seid)) break;
if (!a2dp_source_stream_endpoint_ready(media_tracker.a2dp_cid, media_tracker.local_seid)) break;
a2dp_fill_audio_buffer_timer_start(&media_tracker);
printf(" --- application --- A2DP_SUBEVENT_STREAM_START_ACCEPTED, local seid %d\n", media_tracker.local_seid);
break;
@ -349,7 +349,7 @@ static void stdin_process(char cmd){
switch (cmd){
case 'c':
printf("Creating L2CAP Connection to %s, PSM_AVDTP\n", bd_addr_to_str(remote));
a2dp_source_establish_stream(remote, local_seid);
a2dp_source_establish_stream(remote, local_seid, &media_tracker.a2dp_cid);
break;
case 'C':
printf("Disconnect\n");
@ -358,20 +358,20 @@ static void stdin_process(char cmd){
case 'x':
printf("Stream sine, local seid %d\n", media_tracker.local_seid);
data_source = STREAM_SINE;
a2dp_source_start_stream(media_tracker.local_seid);
a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
break;
case 'z':
printf("Stream mode, local seid %d\n", media_tracker.local_seid);
data_source = STREAM_MOD;
a2dp_source_start_stream(media_tracker.local_seid);
a2dp_source_start_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
break;
case 'p':
printf("Pause stream, local seid %d\n", media_tracker.local_seid);
a2dp_source_pause_stream(media_tracker.local_seid);
a2dp_source_pause_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
break;
case 'X':
printf("Close stream, local seid %d\n", media_tracker.local_seid);
a2dp_source_release_stream(media_tracker.local_seid);
a2dp_source_release_stream(media_tracker.a2dp_cid, media_tracker.local_seid);
break;
default:
show_usage();

View File

@ -177,6 +177,13 @@ typedef uint8_t sm_key_t[16];
#define OBEX_CONNECT_FAILED 0xB1
#define OBEX_DISCONNECTED 0xB2
#define OBEX_NOT_FOUND 0xB3
#define AVDTP_SEID_DOES_NOT_EXIST 0xC0
#define AVDTP_CONNECTION_DOES_NOT_EXIST 0xC1
#define AVDTP_CONNECTION_IN_WRONG_STATE 0xC2
#define AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE 0xC3
#define AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST 0xC4
/* ENUM_END */
// DAEMON COMMANDS
@ -1274,7 +1281,7 @@ typedef uint8_t sm_key_t[16];
* @format 1211
* @param subevent_code
* @param avdtp_cid
* @param int_seid
* @param local_seid
* @param signal_identifier
*/
#define AVDTP_SUBEVENT_SIGNALING_REJECT 0x02
@ -1283,7 +1290,7 @@ typedef uint8_t sm_key_t[16];
* @format 1211
* @param subevent_code
* @param avdtp_cid
* @param int_seid
* @param local_seid
* @param signal_identifier
*/
#define AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT 0x03
@ -1308,7 +1315,7 @@ typedef uint8_t sm_key_t[16];
* @format 121111
* @param subevent_code
* @param avdtp_cid
* @param seid 0x01 0x3E
* @param remote_seid 0x01 0x3E
* @param in_use 0-not in use, 1-in use
* @param media_type 0-audio, 1-video, 2-multimedia
* @param sep_type 0-source, 1-sink
@ -1319,8 +1326,8 @@ typedef uint8_t sm_key_t[16];
* @format 121111111111
* @param subevent_code
* @param avdtp_cid
* @param int_seid
* @param acp_seid
* @param local_seid
* @param remote_seid
* @param media_type
* @param sampling_frequency_bitmap
* @param channel_mode_bitmap
@ -1336,8 +1343,8 @@ typedef uint8_t sm_key_t[16];
* @format 121112LV
* @param subevent_code
* @param avdtp_cid
* @param int_seid
* @param acp_seid
* @param local_seid
* @param remote_seid
* @param media_type
* @param media_codec_type
* @param media_codec_information_len
@ -1349,8 +1356,8 @@ typedef uint8_t sm_key_t[16];
* @format 12111121111111
* @param subevent_code
* @param avdtp_cid
* @param int_seid
* @param acp_seid
* @param local_seid
* @param remote_seid
* @param reconfigure
* @param media_type
* @param sampling_frequency
@ -1368,8 +1375,8 @@ typedef uint8_t sm_key_t[16];
* @format 1211112LV
* @param subevent_code
* @param avdtp_cid
* @param int_seid
* @param acp_seid
* @param local_seid
* @param remote_seid
* @param reconfigure
* @param media_type
* @param media_codec_type
@ -1382,8 +1389,8 @@ typedef uint8_t sm_key_t[16];
* @format 12111
* @param subevent_code
* @param avdtp_cid
* @param int_seid
* @param acp_seid
* @param local_seid
* @param remote_seid
* @param status 0 == OK
*/
#define AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED 0x0B
@ -1399,7 +1406,7 @@ typedef uint8_t sm_key_t[16];
* @format 1212
* @param subevent_code
* @param avdtp_cid
* @param int_seid
* @param local_seid
* @param sequence_number
*/
#define AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW 0x0D

View File

@ -4017,12 +4017,12 @@ static inline uint16_t avdtp_subevent_signaling_reject_get_avdtp_cid(const uint8
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_REJECT
* @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_REJECT
* @param event packet
* @return int_seid
* @return local_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_reject_get_int_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_reject_get_local_seid(const uint8_t * event){
return event[5];
}
/**
@ -4045,12 +4045,12 @@ static inline uint16_t avdtp_subevent_signaling_general_reject_get_avdtp_cid(con
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT
* @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT
* @param event packet
* @return int_seid
* @return local_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_general_reject_get_int_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_general_reject_get_local_seid(const uint8_t * event){
return event[5];
}
/**
@ -4111,12 +4111,12 @@ static inline uint16_t avdtp_subevent_signaling_sep_found_get_avdtp_cid(const ui
return little_endian_read_16(event, 3);
}
/**
* @brief Get field seid from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND
* @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND
* @param event packet
* @return seid
* @return remote_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_sep_found_get_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_sep_found_get_remote_seid(const uint8_t * event){
return event[5];
}
/**
@ -4157,21 +4157,21 @@ static inline uint16_t avdtp_subevent_signaling_media_codec_sbc_capability_get_a
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
* @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
* @param event packet
* @return int_seid
* @return local_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_int_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_local_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field acp_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
* @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY
* @param event packet
* @return acp_seid
* @return remote_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_acp_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_remote_seid(const uint8_t * event){
return event[6];
}
/**
@ -4257,21 +4257,21 @@ static inline uint16_t avdtp_subevent_signaling_media_codec_other_capability_get
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
* @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
* @param event packet
* @return int_seid
* @return local_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_int_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_local_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field acp_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
* @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY
* @param event packet
* @return acp_seid
* @return remote_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_acp_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_remote_seid(const uint8_t * event){
return event[6];
}
/**
@ -4321,21 +4321,21 @@ static inline uint16_t avdtp_subevent_signaling_media_codec_sbc_configuration_ge
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return int_seid
* @return local_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_int_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_local_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field acp_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION
* @param event packet
* @return acp_seid
* @return remote_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_acp_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_remote_seid(const uint8_t * event){
return event[6];
}
/**
@ -4439,21 +4439,21 @@ static inline uint16_t avdtp_subevent_signaling_media_codec_other_configuration_
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return int_seid
* @return local_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_int_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_local_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field acp_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION
* @param event packet
* @return acp_seid
* @return remote_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_acp_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_remote_seid(const uint8_t * event){
return event[6];
}
/**
@ -4512,21 +4512,21 @@ static inline uint16_t avdtp_subevent_streaming_connection_established_get_avdtp
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED
* @brief Get field local_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED
* @param event packet
* @return int_seid
* @return local_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_streaming_connection_established_get_int_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_streaming_connection_established_get_local_seid(const uint8_t * event){
return event[5];
}
/**
* @brief Get field acp_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED
* @brief Get field remote_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED
* @param event packet
* @return acp_seid
* @return remote_seid
* @note: btstack_type 1
*/
static inline uint8_t avdtp_subevent_streaming_connection_established_get_acp_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_streaming_connection_established_get_remote_seid(const uint8_t * event){
return event[6];
}
/**
@ -4559,12 +4559,12 @@ static inline uint16_t avdtp_subevent_streaming_can_send_media_packet_now_get_av
return little_endian_read_16(event, 3);
}
/**
* @brief Get field int_seid from event AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW
* @brief Get field local_seid from event AVDTP_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_streaming_can_send_media_packet_now_get_int_seid(const uint8_t * event){
static inline uint8_t avdtp_subevent_streaming_can_send_media_packet_now_get_local_seid(const uint8_t * event){
return event[5];
}
/**

View File

@ -55,8 +55,6 @@ static avdtp_context_t a2dp_sink_context;
static a2dp_state_t app_state = A2DP_IDLE;
static avdtp_stream_endpoint_context_t sc;
static uint16_t avdtp_cid = 0;
// static int next_remote_sep_index_to_query = 0;
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
@ -139,6 +137,23 @@ void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_han
de_add_number(service, DE_UINT, DE_SIZE_16, supported_features);
}
static inline uint16_t a2dp_cid(void){
if (!sc.local_stream_endpoint) return 0;
if (!sc.local_stream_endpoint->connection) return 0;
return sc.local_stream_endpoint->connection->avdtp_cid;
}
static inline uint8_t local_seid(void){
if (!sc.local_stream_endpoint) return 0;
return sc.local_stream_endpoint->sep.seid;
}
static inline uint8_t remote_seid(void){
if (!sc.local_stream_endpoint) return 0;
if (!sc.local_stream_endpoint->connection) return 0;
return sc.local_stream_endpoint->connection->remote_seps[sc.local_stream_endpoint->remote_sep_index].seid;
}
void a2dp_sink_register_packet_handler(btstack_packet_handler_t callback){
// avdtp_sink_register_packet_handler(callback);
// return;
@ -176,25 +191,32 @@ uint8_t a2dp_sink_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_me
return local_stream_endpoint->sep.seid;
}
void a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid){
uint8_t a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid, uint16_t * avdtp_cid){
sc.local_stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_sink_context);
if (!sc.local_stream_endpoint){
log_error(" no local_stream_endpoint for seid %d", local_seid);
return;
return AVDTP_SEID_DOES_NOT_EXIST;
}
avdtp_sink_connect(bd_addr);
return avdtp_sink_connect(bd_addr, avdtp_cid);
}
void a2dp_sink_disconnect(uint16_t a2dp_cid){
avdtp_disconnect(a2dp_cid, &a2dp_sink_context);
}
static void a2dp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint8_t * event, uint16_t event_size){
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;
if (event_size < 8) return;
event[0] = HCI_EVENT_A2DP_META;
event[2] = A2DP_SUBEVENT_STREAM_ESTABLISHED;
(*callback)(HCI_EVENT_PACKET, 0, event, event_size);
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 inline void a2dp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint8_t * event, uint16_t event_size){
@ -233,37 +255,43 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
uint8_t status;
uint8_t signal_identifier;
uint16_t cid;
uint8_t local_seid;
uint8_t loc_seid;
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");
log_info("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
app_state = A2DP_IDLE;
printf("\n --- a2dp sink: HCI_EVENT_DISCONNECTION_COMPLETE ---\n");
printf("\na2dp sink: HCI_EVENT_DISCONNECTION_COMPLETE ---\n");
break;
case HCI_EVENT_AVDTP_META:
switch (packet[2]){
case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
if (cid != a2dp_cid()){
a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER);
break;
}
status = avdtp_subevent_signaling_connection_established_get_status(packet);
if (status != 0){
log_info(" --- a2dp sink --- AVDTP_SUBEVENT_SIGNALING_CONNECTION could not be established, status %d ---", status);
a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), status);
break;
}
app_state = A2DP_CONNECTED;
avdtp_cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
log_info(" --- a2dp sink --- AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---", avdtp_cid);
log_info("a2dp sink: AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---", a2dp_cid());
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION:
log_info(" --- a2dp sink --- received non SBC codec. not implemented");
log_info("a2dp sink: received non SBC codec. not implemented");
avdtp_signaling_emit_media_codec_other(a2dp_sink_context.a2dp_callback, packet, size);
break;
@ -279,7 +307,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
} else {
app_state = A2DP_STREAMING_OPENED;
}
a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, packet, size);
a2dp_streaming_emit_connection_established(a2dp_sink_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), 0);
break;
case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
@ -287,19 +315,18 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
status = 0;
signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet);
local_seid = avdtp_subevent_signaling_accept_get_local_seid(packet);
printf(" --- a2dp sink --- Accepted %d, a2dp sink cid 0x%2x, local seid %d\n", signal_identifier, cid, local_seid);
loc_seid = avdtp_subevent_signaling_accept_get_local_seid(packet);
switch (signal_identifier){
case AVDTP_SI_START:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_STARTED, local_seid, status);
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_STARTED, loc_seid, status);
break;
case AVDTP_SI_SUSPEND:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_SUSPENDED, local_seid, status);
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_SUSPENDED, loc_seid, status);
break;
case AVDTP_SI_ABORT:
case AVDTP_SI_CLOSE:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, local_seid, status);
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, loc_seid, status);
break;
default:
break;
@ -312,19 +339,18 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
status = 1;
signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet);
local_seid = avdtp_subevent_signaling_accept_get_local_seid(packet);
printf(" --- a2dp sink --- Rejected %d, a2dp sink cid 0x%2x, local seid %d\n", signal_identifier, cid, local_seid);
loc_seid = avdtp_subevent_signaling_accept_get_local_seid(packet);
switch (signal_identifier){
case AVDTP_SI_START:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_STARTED, local_seid, status);
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_STARTED, loc_seid, status);
break;
case AVDTP_SI_SUSPEND:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_SUSPENDED, local_seid, status);
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_SUSPENDED, loc_seid, status);
break;
case AVDTP_SI_ABORT:
case AVDTP_SI_CLOSE:
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, local_seid, status);
a2dp_emit_stream_event(a2dp_sink_context.a2dp_callback, cid, A2DP_SUBEVENT_STREAM_RELEASED, loc_seid, status);
break;
default:
break;
@ -332,7 +358,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
break;
default:
app_state = A2DP_IDLE;
log_info(" --- a2dp sink --- not implemented");
log_info("a2dp sink: not implemented");
break;
}
break;

View File

@ -88,10 +88,12 @@ void a2dp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t *
/**
* @brief Open stream
* @param avdtp_cid
* @param bd_addr
* @param local_seid
* @param avdtp_cid
*/
void a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid);
uint8_t a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid, uint16_t * avdtp_cid);
/**
* @brief Start stream

View File

@ -57,7 +57,6 @@ static avdtp_context_t a2dp_source_context;
static a2dp_state_t app_state = A2DP_IDLE;
static avdtp_stream_endpoint_context_t sc;
static uint16_t avdtp_cid = 0;
static int next_remote_sep_index_to_query = 0;
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
@ -141,6 +140,23 @@ 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 inline uint16_t a2dp_cid(void){
if (!sc.local_stream_endpoint) return 0;
if (!sc.local_stream_endpoint->connection) return 0;
return sc.local_stream_endpoint->connection->avdtp_cid;
}
static inline uint8_t local_seid(void){
if (!sc.local_stream_endpoint) return 0;
return sc.local_stream_endpoint->sep.seid;
}
static inline uint8_t remote_seid(void){
if (!sc.local_stream_endpoint) return 0;
if (!sc.local_stream_endpoint->connection) return 0;
return sc.local_stream_endpoint->connection->remote_seps[sc.local_stream_endpoint->remote_sep_index].seid;
}
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];
@ -176,8 +192,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
uint8_t signal_identifier;
uint8_t status;
avdtp_sep_t sep;
uint8_t int_seid;
uint8_t acp_seid;
uint8_t loc_seid;
uint8_t rem_seid;
uint16_t cid;
switch (packet_type) {
@ -190,37 +207,55 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case HCI_EVENT_AVDTP_META:
switch (packet[2]){
case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
avdtp_cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
if (cid != a2dp_cid()){
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER);
break;
}
status = avdtp_subevent_signaling_connection_established_get_status(packet);
if (status != 0){
log_info(" --- a2dp source --- AVDTP_SUBEVENT_SIGNALING_CONNECTION could not be established, status %d ---", status);
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), status);
break;
}
sc.active_remote_sep = NULL;
next_remote_sep_index_to_query = 0;
app_state = A2DP_W2_DISCOVER_SEPS;
log_info(" --- a2dp source --- AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---", avdtp_cid);
avdtp_source_discover_stream_endpoints(avdtp_cid);
log_info(" --- a2dp source --- AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED, avdtp cid 0x%02x ---", a2dp_cid());
avdtp_source_discover_stream_endpoints(a2dp_cid());
break;
case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
status = avdtp_subevent_streaming_connection_established_get_status(packet);
avdtp_cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet);
int_seid = avdtp_subevent_streaming_connection_established_get_int_seid(packet);
acp_seid = avdtp_subevent_streaming_connection_established_get_acp_seid(packet);
if (status != 0){
log_info(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION could not be established, status %d ---", status);
cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet);
if (cid != a2dp_cid()){
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER);
break;
}
loc_seid = avdtp_subevent_streaming_connection_established_get_local_seid(packet);
if (loc_seid != local_seid()){
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER);
break;
}
rem_seid = avdtp_subevent_streaming_connection_established_get_remote_seid(packet);
if (status != 0){
log_info(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION could not be established, status %d ---", status);
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), rem_seid, status);
break;
}
app_state = A2DP_STREAMING_OPENED;
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, avdtp_cid, int_seid, acp_seid, 0);
log_info(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED --- avdtp_cid 0x%02x, local seid %d, remote seid %d", avdtp_cid, int_seid, acp_seid);
a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, a2dp_cid(), local_seid(), remote_seid(), 0);
log_info(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED --- avdtp_cid 0x%02x, local seid %d, remote seid %d", a2dp_cid(), local_seid(), remote_seid());
break;
case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:
// TODO check cid
if (app_state != A2DP_W2_DISCOVER_SEPS) return;
sep.seid = avdtp_subevent_signaling_sep_found_get_seid(packet);
sep.seid = avdtp_subevent_signaling_sep_found_get_remote_seid(packet);
sep.in_use = avdtp_subevent_signaling_sep_found_get_in_use(packet);
sep.media_type = (avdtp_media_type_t) avdtp_subevent_signaling_sep_found_get_media_type(packet);
sep.type = (avdtp_sep_type_t) avdtp_subevent_signaling_sep_found_get_sep_type(packet);
@ -228,6 +263,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY:{
// TODO check cid
if (!sc.local_stream_endpoint) 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));
@ -255,6 +291,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
// TODO check cid
sc.sampling_frequency = avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
sc.block_length = avdtp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
sc.subbands = avdtp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
@ -264,26 +301,27 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
break;
}
case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
a2dp_streaming_emit_can_send_media_packet_now(a2dp_source_context.a2dp_callback, avdtp_cid, 0);
a2dp_streaming_emit_can_send_media_packet_now(a2dp_source_context.a2dp_callback, a2dp_cid(), 0);
break;
case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
// TODO check cid
signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
log_info(" --- a2dp source --- Accepted %d", signal_identifier);
switch (app_state){
case A2DP_W2_DISCOVER_SEPS:
app_state = A2DP_W2_GET_ALL_CAPABILITIES;
sc.active_remote_sep = avdtp_source_remote_sep(avdtp_cid, next_remote_sep_index_to_query++);
sc.active_remote_sep = avdtp_source_remote_sep(a2dp_cid(), next_remote_sep_index_to_query++);
log_info(" --- a2dp source --- Query get caps for seid %d", sc.active_remote_sep->seid);
avdtp_source_get_capabilities(avdtp_cid, sc.active_remote_sep->seid);
avdtp_source_get_capabilities(a2dp_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(avdtp_cid)){
sc.active_remote_sep = avdtp_source_remote_sep(avdtp_cid, next_remote_sep_index_to_query++);
if (next_remote_sep_index_to_query < avdtp_source_remote_seps_num(a2dp_cid())){
sc.active_remote_sep = avdtp_source_remote_sep(a2dp_cid(), next_remote_sep_index_to_query++);
log_info(" --- a2dp source --- Query get caps for seid %d", sc.active_remote_sep->seid);
avdtp_source_get_capabilities(avdtp_cid, sc.active_remote_sep->seid);
avdtp_source_get_capabilities(a2dp_cid(), sc.active_remote_sep->seid);
} else {
log_info(" --- a2dp source --- No more remote seps found");
app_state = A2DP_IDLE;
@ -292,12 +330,12 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case A2DP_W2_SET_CONFIGURATION:{
if (!sc.local_stream_endpoint) return;
app_state = A2DP_W2_GET_CONFIGURATION;
avdtp_source_set_configuration(avdtp_cid, avdtp_stream_endpoint_seid(sc.local_stream_endpoint), sc.active_remote_sep->seid, sc.local_stream_endpoint->remote_configuration_bitmap, sc.local_stream_endpoint->remote_configuration);
avdtp_source_set_configuration(a2dp_cid(), avdtp_stream_endpoint_seid(sc.local_stream_endpoint), sc.active_remote_sep->seid, sc.local_stream_endpoint->remote_configuration_bitmap, sc.local_stream_endpoint->remote_configuration);
break;
}
case A2DP_W2_GET_CONFIGURATION:
app_state = A2DP_W2_OPEN_STREAM_WITH_SEID;
avdtp_source_get_configuration(avdtp_cid, sc.active_remote_sep->seid);
avdtp_source_get_configuration(a2dp_cid(), sc.active_remote_sep->seid);
break;
case A2DP_W2_OPEN_STREAM_WITH_SEID:{
app_state = A2DP_W4_OPEN_STREAM_WITH_SEID;
@ -305,7 +343,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
sc.block_length, sc.subbands,
sc.allocation_method, sc.sampling_frequency,
sc.max_bitpool_value);
avdtp_source_open_stream(avdtp_cid, avdtp_stream_endpoint_seid(sc.local_stream_endpoint), sc.active_remote_sep->seid);
avdtp_source_open_stream(a2dp_cid(), avdtp_stream_endpoint_seid(sc.local_stream_endpoint), sc.active_remote_sep->seid);
break;
}
case A2DP_STREAMING_OPENED:
@ -317,7 +355,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
event[pos++] = HCI_EVENT_A2DP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = A2DP_SUBEVENT_STREAM_STARTED;
little_endian_store_16(event, pos, avdtp_cid);
little_endian_store_16(event, pos, a2dp_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));
@ -329,7 +367,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
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);
little_endian_store_16(event, pos, a2dp_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));
@ -342,7 +380,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
event[pos++] = HCI_EVENT_A2DP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = A2DP_SUBEVENT_STREAM_RELEASED;
little_endian_store_16(event, pos, avdtp_cid);
little_endian_store_16(event, pos, a2dp_cid());
pos += 2;
log_info("send A2DP_SUBEVENT_STREAM_RELEASED to app");
event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
@ -411,37 +449,38 @@ uint8_t a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_
return local_stream_endpoint->sep.seid;
}
void a2dp_source_establish_stream(bd_addr_t bd_addr, uint8_t local_seid){
uint8_t a2dp_source_establish_stream(bd_addr_t bd_addr, uint8_t local_seid, uint16_t * avdtp_cid){
sc.local_stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
if (!sc.local_stream_endpoint){
log_error(" no local_stream_endpoint for seid %d", local_seid);
return;
return AVDTP_SEID_DOES_NOT_EXIST;
}
avdtp_source_connect(bd_addr);
return avdtp_source_connect(bd_addr, avdtp_cid);
}
void a2dp_source_disconnect(uint16_t local_seid){
avdtp_disconnect(local_seid, &a2dp_source_context);
uint8_t a2dp_source_disconnect(uint16_t avdtp_cid){
return avdtp_disconnect(avdtp_cid, &a2dp_source_context);
}
void a2dp_source_start_stream(uint8_t int_seid){
avdtp_start_stream(int_seid, &a2dp_source_context);
uint8_t a2dp_source_start_stream(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_start_stream(avdtp_cid, local_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_release_stream(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_stop_stream(avdtp_cid, local_seid, &a2dp_source_context);
}
void a2dp_source_pause_stream(uint8_t int_seid){
avdtp_suspend_stream(int_seid, &a2dp_source_context);
uint8_t a2dp_source_pause_stream(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_suspend_stream(avdtp_cid, local_seid, &a2dp_source_context);
}
uint8_t a2dp_source_stream_endpoint_ready(uint8_t local_seid){
uint8_t a2dp_source_stream_endpoint_ready(uint16_t avdtp_cid, uint8_t local_seid){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
if (!stream_endpoint) {
log_error("No stream_endpoint with seid %d", local_seid);
return 0;
}
if (!stream_endpoint->connection || stream_endpoint->connection->avdtp_cid != avdtp_cid) return 0;
return (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING);
}
@ -486,14 +525,14 @@ void a2dp_source_stream_endpoint_request_can_send_now(uint8_t local_seid){
avdtp_request_can_send_now_initiator(stream_endpoint->connection, stream_endpoint->l2cap_media_cid);
}
int a2dp_max_media_payload_size(uint8_t int_seid){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, &a2dp_source_context);
int a2dp_max_media_payload_size(uint8_t local_seid){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
if (!stream_endpoint) {
log_error("no stream_endpoint found for seid %d", int_seid);
log_error("no stream_endpoint found for seid %d", local_seid);
return 0;
}
if (stream_endpoint->l2cap_media_cid == 0){
log_error("no media cid found for seid %d", int_seid);
log_error("no media cid found for seid %d", local_seid);
return 0;
}
return l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid) - AVDTP_MEDIA_PAYLOAD_HEADER_SIZE;
@ -512,15 +551,15 @@ static void a2dp_source_copy_media_payload(uint8_t * media_packet, int size, int
*offset = pos;
}
int a2dp_source_stream_send_media_payload(uint8_t int_seid, uint8_t * storage, int num_bytes_to_copy, uint8_t num_frames, uint8_t marker){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, &a2dp_source_context);
int a2dp_source_stream_send_media_payload(uint8_t local_seid, uint8_t * storage, int num_bytes_to_copy, uint8_t num_frames, uint8_t marker){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, &a2dp_source_context);
if (!stream_endpoint) {
log_error("no stream_endpoint found for seid %d", int_seid);
log_error("no stream_endpoint found for seid %d", local_seid);
return 0;
}
if (stream_endpoint->l2cap_media_cid == 0){
log_error("no media cid found for seid %d", int_seid);
log_error("no media cid found for seid %d", local_seid);
return 0;
}

View File

@ -74,47 +74,48 @@ uint8_t a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_
/**
* @brief Open stream
* @param bd_addr
* @param local_seid
* @param avdtp_cid
* @param seid
*/
void a2dp_source_establish_stream(bd_addr_t bd_addr, uint8_t local_seid);
uint8_t a2dp_source_establish_stream(bd_addr_t bd_addr, uint8_t local_seid, uint16_t * avdtp_cid);
/**
* @brief Start stream
* @param avdtp_cid
* @param seid
*/
void a2dp_source_start_stream(uint8_t int_seid);
uint8_t a2dp_source_start_stream(uint16_t avdtp_cid, uint8_t local_seid);
/**
* @brief Start stream
* @param avdtp_cid
* @param seid
*/
void a2dp_source_pause_stream(uint8_t int_seid);
uint8_t a2dp_source_pause_stream(uint16_t avdtp_cid, uint8_t local_seid);
/**
* @brief Close stream
* @param avdtp_cid
* @param seid
*/
void a2dp_source_release_stream(uint8_t int_seid);
uint8_t a2dp_source_release_stream(uint16_t avdtp_cid, uint8_t local_seid);
/**
* @brief Disconnect from device with cid.
* @param avdtp_cid
*/
void a2dp_source_disconnect(uint16_t avdtp_cid);
uint8_t a2dp_source_disconnect(uint16_t avdtp_cid);
// size for media (does not include media header)
int a2dp_max_media_payload_size(uint8_t int_seid);
int a2dp_max_media_payload_size(uint8_t local_seid);
uint8_t a2dp_source_stream_endpoint_ready(uint8_t local_seid);
uint8_t a2dp_source_stream_endpoint_ready(uint16_t avdtp_cid, uint8_t local_seid);
void a2dp_source_stream_endpoint_request_can_send_now(uint8_t local_seid);
int a2dp_source_stream_send_media_payload(uint8_t int_seid, uint8_t * storage, int num_bytes_to_copy, uint8_t num_frames, uint8_t marker);
int a2dp_source_stream_send_media_payload(uint8_t local_seid, uint8_t * storage, int num_bytes_to_copy, uint8_t num_frames, uint8_t marker);
/* API_END */

View File

@ -61,11 +61,28 @@ typedef struct {
} avdtp_sdp_query_context_t;
static avdtp_sdp_query_context_t sdp_query_context;
static uint16_t avdtp_cid_counter = 0;
static void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
void avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_context_t * avdtp_context){
static uint16_t avdtp_get_next_avdtp_cid(){
avdtp_cid_counter++;
if (avdtp_cid_counter == 0){
avdtp_cid_counter = 1;
}
return avdtp_cid_counter;
}
static uint16_t avdtp_get_next_local_seid(avdtp_context_t * context){
context->stream_endpoints_id_counter++;
if (context->stream_endpoints_id_counter == 0){
context->stream_endpoints_id_counter = 1;
}
return context->stream_endpoints_id_counter;
}
uint8_t avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_context_t * avdtp_context, uint16_t * avdtp_cid){
sdp_query_context.connection = NULL;
avdtp_connection_t * connection = avdtp_connection_for_bd_addr(remote, avdtp_context);
if (!connection){
@ -73,8 +90,14 @@ void avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_context_
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_IDLE){
log_error("avdtp_connect: sink in wrong state,");
return;
return BTSTACK_MEMORY_ALLOC_FAILED;
}
if (!avdtp_cid) return L2CAP_LOCAL_CID_DOES_NOT_EXIST;
*avdtp_cid = avdtp_get_next_avdtp_cid();
connection->avdtp_cid = *avdtp_cid;
connection->state = AVDTP_SIGNALING_W4_SDP_QUERY_COMPLETE;
sdp_query_context.connection = connection;
sdp_query_context.query_role = query_role;
@ -82,6 +105,7 @@ void avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_context_
sdp_query_context.packet_handler = avdtp_context->packet_handler;
sdp_client_query_uuid16(&avdtp_handle_sdp_client_query_result, remote, BLUETOOTH_PROTOCOL_AVDTP);
return ERROR_CODE_SUCCESS;
}
void avdtp_register_media_transport_category(avdtp_stream_endpoint_t * stream_endpoint){
@ -189,7 +213,7 @@ void avdtp_handle_can_send_now(avdtp_connection_t * connection, uint16_t l2cap_c
if (stream_endpoint->connection == connection){
if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_OPENED && stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_DISCONNECTED){
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_DISCONNECTED;
avdtp_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_self(connection, connection->tl2cap_signaling_cid);
l2cap_disconnect(stream_endpoint->l2cap_media_cid, 0);
return;
}
@ -197,7 +221,7 @@ void avdtp_handle_can_send_now(avdtp_connection_t * connection, uint16_t l2cap_c
}
connection->disconnect = 0;
connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED;
l2cap_disconnect(connection->l2cap_signaling_cid, 0);
l2cap_disconnect(connection->tl2cap_signaling_cid, 0);
return;
}
}
@ -223,8 +247,7 @@ avdtp_connection_t * avdtp_create_connection(bd_addr_t remote_addr, avdtp_contex
avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type, avdtp_context_t * context){
avdtp_stream_endpoint_t * stream_endpoint = btstack_memory_avdtp_stream_endpoint_get();
memset(stream_endpoint, 0, sizeof(avdtp_stream_endpoint_t));
context->stream_endpoints_id_counter++;
stream_endpoint->sep.seid = context->stream_endpoints_id_counter;
stream_endpoint->sep.seid = avdtp_get_next_local_seid(context);
stream_endpoint->sep.media_type = media_type;
stream_endpoint->sep.type = sep_type;
btstack_linked_list_add(&context->stream_endpoints, (btstack_linked_item_t *) stream_endpoint);
@ -246,6 +269,7 @@ static void handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t packet_type, uint8_t event, uint8_t *packet, uint16_t size, avdtp_context_t * context){
uint16_t local_cid;
uint8_t status;
switch (packet_type){
case L2CAP_DATA_PACKET:{
int offset = avdtp_read_signaling_header(&connection->signaling_packet, packet, size);
@ -260,13 +284,24 @@ static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp
switch (event){
case L2CAP_EVENT_CHANNEL_OPENED:
if (stream_endpoint->l2cap_media_cid == 0){
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED) return;
if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED){
log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED failed - stream endpoint in wrong state %d, avdtp cid 0x%02x, l2cap_media_cid 0x%02x, local seid %d, remote seid %d\n", stream_endpoint->state, connection->avdtp_cid, stream_endpoint->l2cap_media_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint));
avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE);
break;
}
status = l2cap_event_channel_opened_get_status(packet);
if (status){
log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED failed with status %d, avdtp cid 0x%02x, l2cap_media_cid 0x%02x, local seid %d, remote seid %d\n", status, connection->avdtp_cid, stream_endpoint->l2cap_media_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint));
avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), status);
break;
}
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
stream_endpoint->connection = connection;
stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet);
stream_endpoint->media_con_handle = l2cap_event_channel_opened_get_handle(packet);
log_info(" -> AVDTP_STREAM_ENDPOINT_OPENED, media con handle 0x%02x, l2cap_media_cid 0x%02x", stream_endpoint->media_con_handle, stream_endpoint->l2cap_media_cid);
avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->l2cap_signaling_cid, stream_endpoint->sep.seid, connection->remote_seps[stream_endpoint->remote_sep_index].seid, 0);
printf(" -> AVDTP_STREAM_ENDPOINT_OPENED, avdtp cid 0x%02x, l2cap_media_cid 0x%02x, local seid %d, remote seid %d\n", connection->avdtp_cid, stream_endpoint->l2cap_media_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint));
avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), avdtp_remote_seid(stream_endpoint), 0);
break;
}
break;
@ -339,7 +374,7 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c
case BLUETOOTH_SERVICE_CLASS_AUDIO_SOURCE:
if (sdp_query_context.query_role != AVDTP_SOURCE) {
sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, SDP_SERVICE_NOT_FOUND);
avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->avdtp_cid, sdp_query_context.connection->remote_addr, SDP_SERVICE_NOT_FOUND);
break;
}
// log_info("SDP Attribute 0x%04x: AVDTP SOURCE protocol UUID: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet), uuid);
@ -348,7 +383,7 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c
case BLUETOOTH_SERVICE_CLASS_AUDIO_SINK:
if (sdp_query_context.query_role != AVDTP_SINK) {
sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, SDP_SERVICE_NOT_FOUND);
avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->avdtp_cid, sdp_query_context.connection->remote_addr, SDP_SERVICE_NOT_FOUND);
break;
}
// log_info("SDP Attribute 0x%04x: AVDTP SINK protocol UUID: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet), uuid);
@ -394,7 +429,7 @@ static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t c
}
if (!avdtp_l2cap_psm) {
sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_IDLE;
avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->l2cap_signaling_cid, sdp_query_context.connection->remote_addr, L2CAP_SERVICE_DOES_NOT_EXIST);
avdtp_signaling_emit_connection_established(sdp_query_context.avdtp_callback, sdp_query_context.connection->avdtp_cid, sdp_query_context.connection->remote_addr, L2CAP_SERVICE_DOES_NOT_EXIST);
break;
}
sdp_query_context.connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED;
@ -430,7 +465,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
// log_info("avdtp_packet_handler packet type %02x, event %02x ", packet_type, hci_event_packet_get_type(packet));
switch (packet_type) {
case L2CAP_DATA_PACKET:
connection = avdtp_connection_for_l2cap_signaling_cid(channel, context);
connection = avdtp_connection_for_tl2cap_signaling_cid(channel, context);
if (connection){
handle_l2cap_data_packet_for_signaling_connection(connection, packet, size, context);
break;
@ -443,7 +478,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
break;
}
if (channel == stream_endpoint->connection->l2cap_signaling_cid){
if (channel == stream_endpoint->connection->tl2cap_signaling_cid){
stream_endpoint_state_machine(stream_endpoint->connection, stream_endpoint, L2CAP_DATA_PACKET, 0, packet, size, context);
break;
}
@ -500,7 +535,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
l2cap_event_channel_opened_get_address(packet, event_addr);
local_cid = l2cap_event_channel_opened_get_local_cid(packet);
if (l2cap_event_channel_opened_get_status(packet)){
avdtp_signaling_emit_connection_established(context->avdtp_callback, connection->l2cap_signaling_cid, event_addr, l2cap_event_channel_opened_get_status(packet));
avdtp_signaling_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, event_addr, l2cap_event_channel_opened_get_status(packet));
log_error("L2CAP connection to connection %s failed. status code 0x%02x",
bd_addr_to_str(event_addr), l2cap_event_channel_opened_get_status(packet));
break;
@ -521,14 +556,13 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
connection = avdtp_connection_for_bd_addr(event_addr, context);
if (!connection) break;
if (connection->l2cap_signaling_cid == 0) {
if (connection->tl2cap_signaling_cid == 0) {
if (connection->state != AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED) break;
connection->l2cap_signaling_cid = local_cid;
connection->con_handle = con_handle;
connection->tl2cap_signaling_cid = local_cid;
connection->query_seid = 0;
connection->state = AVDTP_SIGNALING_CONNECTION_OPENED;
log_info(" -> AVDTP_SIGNALING_CONNECTION_OPENED, connection %p", connection);
avdtp_signaling_emit_connection_established(context->avdtp_callback, connection->l2cap_signaling_cid, event_addr, 0);
avdtp_signaling_emit_connection_established(context->avdtp_callback, connection->avdtp_cid, event_addr, 0);
break;
}
@ -543,7 +577,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
case L2CAP_EVENT_CHANNEL_CLOSED:
// data: event (8), len(8), channel (16)
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
connection = avdtp_connection_for_l2cap_signaling_cid(local_cid, context);
connection = avdtp_connection_for_tl2cap_signaling_cid(local_cid, context);
log_info(" -> L2CAP_EVENT_CHANNEL_CLOSED signaling cid 0x%0x", local_cid);
stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(local_cid, context);
@ -574,7 +608,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
break;
case L2CAP_EVENT_CAN_SEND_NOW:
connection = avdtp_connection_for_l2cap_signaling_cid(channel, context);
connection = avdtp_connection_for_tl2cap_signaling_cid(channel, context);
if (!connection) {
stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(channel, context);
if (!stream_endpoint->connection) break;
@ -594,120 +628,155 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
}
}
void avdtp_disconnect(uint16_t avdtp_cid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
if (!connection) return;
if (connection->state == AVDTP_SIGNALING_CONNECTION_IDLE) return;
if (connection->state == AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED) return;
uint8_t avdtp_disconnect(uint16_t avdtp_cid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection) return BTSTACK_MEMORY_ALLOC_FAILED;
if (connection->state == AVDTP_SIGNALING_CONNECTION_IDLE) return AVDTP_CONNECTION_IN_WRONG_STATE;
if (connection->state == AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED) return AVDTP_CONNECTION_IN_WRONG_STATE;
connection->disconnect = 1;
avdtp_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_self(connection, connection->tl2cap_signaling_cid);
return ERROR_CODE_SUCCESS;
}
void avdtp_open_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);
uint8_t avdtp_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_media_connect: no connection for signaling cid 0x%02x found", avdtp_cid);
return;
return AVDTP_CONNECTION_DOES_NOT_EXIST;
}
if (avdtp_find_remote_sep(connection, acp_seid) == 0xFF){
log_error("avdtp_media_connect: no remote sep for seid %d found", acp_seid);
return;
return AVDTP_SEID_DOES_NOT_EXIST;
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
log_error("avdtp_media_connect: wrong connection state %d", connection->state);
return;
return AVDTP_CONNECTION_IN_WRONG_STATE;
}
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
if (!stream_endpoint) {
log_error("avdtp_media_connect: no stream_endpoint with seid %d found", int_seid);
return;
return AVDTP_SEID_DOES_NOT_EXIST;
}
if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED) return;
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED) return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE;
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return AVDTP_SEID_DOES_NOT_EXIST;
connection->initiator_transaction_label++;
connection->acp_seid = acp_seid;
connection->int_seid = stream_endpoint->sep.seid;
connection->local_seid = stream_endpoint->sep.seid;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_OPEN_STREAM;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
return ERROR_CODE_SUCCESS;
}
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) {
log_error("avdtp_start_stream: no stream_endpoint with seid %d found", int_seid);
return;
}
avdtp_connection_t * connection = stream_endpoint->connection;
uint8_t avdtp_start_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_start_stream: no connection for seid %d found",stream_endpoint->sep.seid);
return;
log_error("avdtp_start_stream: no connection for signaling cid 0x%02x found", avdtp_cid);
return AVDTP_CONNECTION_DOES_NOT_EXIST;
}
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(local_seid, context);
if (!stream_endpoint) {
log_error("avdtp_start_stream: no stream_endpoint with seid %d found", local_seid);
return AVDTP_SEID_DOES_NOT_EXIST;
}
if (stream_endpoint->l2cap_media_cid == 0){
log_error("avdtp_start_stream: no media connection for stream_endpoint with seid %d found", local_seid);
return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX || stream_endpoint->start_stream){
return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE;
}
if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX || stream_endpoint->start_stream) return;
stream_endpoint->start_stream = 1;
connection->int_seid = int_seid;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
connection->local_seid = local_seid;
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
return ERROR_CODE_SUCCESS;
}
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) {
log_error("avdtp_stop_stream: no stream_endpoint with seid %d found", int_seid);
return;
}
avdtp_connection_t * connection = stream_endpoint->connection;
uint8_t avdtp_stop_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_stop_stream: no connection for seid %d found",stream_endpoint->sep.seid);
return;
log_error("avdtp_stop_stream: no connection for signaling cid 0x%02x found", avdtp_cid);
return AVDTP_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->stop_stream) return;
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(local_seid, context);
if (!stream_endpoint) {
log_error("avdtp_stop_stream: no stream_endpoint with seid %d found", local_seid);
return AVDTP_SEID_DOES_NOT_EXIST;
}
if (stream_endpoint->l2cap_media_cid == 0){
log_error("avdtp_stop_stream: no media connection for stream_endpoint with seid %d found", local_seid);
return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->stop_stream) return ERROR_CODE_SUCCESS;
stream_endpoint->stop_stream = 1;
connection->int_seid = int_seid;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
connection->local_seid = local_seid;
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
return ERROR_CODE_SUCCESS;
}
void avdtp_abort_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) {
log_error("avdtp_abort_stream: no stream_endpoint with seid %d found", int_seid);
return;
}
avdtp_connection_t * connection = stream_endpoint->connection;
uint8_t avdtp_abort_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_abort_stream: no connection for seid %d found",stream_endpoint->sep.seid);
return;
log_error("avdtp_abort_stream: no connection for signaling cid 0x%02x found", avdtp_cid);
return AVDTP_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->abort_stream) return;
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(local_seid, context);
if (!stream_endpoint) {
log_error("avdtp_abort_stream: no stream_endpoint with seid %d found", local_seid);
return AVDTP_SEID_DOES_NOT_EXIST;
}
if (stream_endpoint->l2cap_media_cid == 0){
log_error("avdtp_abort_stream: no media connection for stream_endpoint with seid %d found", local_seid);
return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->stop_stream) return ERROR_CODE_SUCCESS;
stream_endpoint->abort_stream = 1;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
return ERROR_CODE_SUCCESS;
}
void avdtp_suspend_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) {
log_error("avdtp_abort_stream: no stream_endpoint with seid %d found", int_seid);
return;
}
avdtp_connection_t * connection = stream_endpoint->connection;
uint8_t avdtp_suspend_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_abort_stream: no connection for seid %d found",stream_endpoint->sep.seid);
return;
log_error("avdtp_suspend_stream: no connection for signaling cid 0x%02x found", avdtp_cid);
return AVDTP_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->suspend_stream) return;
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(local_seid, context);
if (!stream_endpoint) {
log_error("avdtp_suspend_stream: no stream_endpoint with seid %d found", local_seid);
return AVDTP_SEID_DOES_NOT_EXIST;
}
if (stream_endpoint->l2cap_media_cid == 0){
log_error("avdtp_suspend_stream: no media connection for stream_endpoint with seid %d found", local_seid);
return AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST;
}
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->stop_stream) return ERROR_CODE_SUCCESS;
stream_endpoint->suspend_stream = 1;
connection->int_seid = int_seid;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
connection->local_seid = local_seid;
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
return ERROR_CODE_SUCCESS;
}
void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_discover_stream_endpoints: no connection for signaling cid 0x%02x found", avdtp_cid);
return;
@ -718,7 +787,7 @@ void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * conte
case AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE:
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
break;
default:
log_error("avdtp_discover_stream_endpoints: wrong state");
@ -728,9 +797,9 @@ void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * conte
void avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_get_capabilities: no connection for signaling cid 0x%02x found", avdtp_cid);
log_error("avdtp_get_capabilities: no connection for AVDTP cid 0x%02x found", avdtp_cid);
return;
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
@ -738,14 +807,14 @@ void avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES;
connection->acp_seid = acp_seid;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
}
void avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_get_all_capabilities: no connection for signaling cid 0x%02x found", avdtp_cid);
log_error("avdtp_get_all_capabilities: no connection for AVDTP cid 0x%02x found", avdtp_cid);
return;
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
@ -753,13 +822,13 @@ void avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_cont
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES;
connection->acp_seid = acp_seid;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
}
void avdtp_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_get_configuration: no connection for signaling cid 0x%02x found", avdtp_cid);
log_error("avdtp_get_configuration: no connection for AVDTP cid 0x%02x found", avdtp_cid);
return;
}
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
@ -767,46 +836,46 @@ void avdtp_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context
connection->initiator_transaction_label++;
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION;
connection->acp_seid = acp_seid;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
}
void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_set_configuration: no connection for signaling cid 0x%02x found", avdtp_cid);
log_error("avdtp_set_configuration: no connection for AVDTP cid 0x%02x found", avdtp_cid);
return;
}
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 = avdtp_stream_endpoint_for_seid(int_seid, context);
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, context);
if (!stream_endpoint) {
log_error("avdtp_set_configuration: no initiator stream endpoint for seid %d", int_seid);
log_error("avdtp_set_configuration: no initiator stream endpoint for seid %d", local_seid);
return;
}
connection->initiator_transaction_label++;
connection->acp_seid = acp_seid;
connection->int_seid = int_seid;
connection->local_seid = local_seid;
stream_endpoint->remote_capabilities_bitmap = configured_services_bitmap;
stream_endpoint->remote_capabilities = configuration;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SET_CONFIGURATION;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
}
void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_reconfigure: no connection for signaling cid 0x%02x found", avdtp_cid);
log_error("avdtp_reconfigure: no connection for AVDTP cid 0x%02x found", avdtp_cid);
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 = avdtp_stream_endpoint_for_seid(int_seid, context);
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, context);
if (!stream_endpoint) {
log_error("avdtp_reconfigure: no initiator stream endpoint for seid %d", int_seid);
log_error("avdtp_reconfigure: no initiator stream endpoint for seid %d", local_seid);
return;
}
@ -817,26 +886,26 @@ void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, u
connection->initiator_transaction_label++;
connection->acp_seid = acp_seid;
connection->int_seid = stream_endpoint->sep.seid;
connection->local_seid = stream_endpoint->sep.seid;
stream_endpoint->remote_capabilities_bitmap = configured_services_bitmap;
stream_endpoint->remote_capabilities = configuration;
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID;
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
}
uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_suspend: no connection for signaling cid 0x%02x found", avdtp_cid);
log_error("avdtp_suspend: no connection for AVDTP cid 0x%02x found", avdtp_cid);
return 0;
}
return connection->remote_seps_num;
}
avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context){
avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context);
if (!connection){
log_error("avdtp_suspend: no connection for signaling cid 0x%02x found", avdtp_cid);
log_error("avdtp_suspend: no connection for AVDTP cid 0x%02x found", avdtp_cid);
return NULL;
}
return &connection->remote_seps[index];

View File

@ -376,11 +376,10 @@ typedef struct {
typedef struct {
btstack_linked_item_t item;
bd_addr_t remote_addr;
hci_con_handle_t con_handle;
uint16_t l2cap_signaling_cid;
uint16_t avdtp_cid;
uint16_t tl2cap_signaling_cid;
avdtp_service_mode_t service_mode;
avdtp_connection_state_t state;
@ -396,7 +395,7 @@ typedef struct {
uint8_t initiator_transaction_label;
uint8_t acceptor_transaction_label;
uint8_t query_seid;
uint8_t int_seid;
uint8_t local_seid;
uint8_t acp_seid;
uint8_t wait_to_send_acceptor;
@ -517,20 +516,20 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
avdtp_connection_t * avdtp_create_connection(bd_addr_t remote_addr, avdtp_context_t * context);
avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type, avdtp_context_t * context);
void avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_context_t * context);
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(uint8_t int_seid, avdtp_context_t * context);
void avdtp_stop_stream (uint8_t int_seid, avdtp_context_t * context);
void avdtp_abort_stream(uint8_t int_seid, avdtp_context_t * context);
void avdtp_suspend_stream(uint8_t int_seid, avdtp_context_t * context);
uint8_t avdtp_connect(bd_addr_t remote, avdtp_sep_type_t query_role, avdtp_context_t * context, uint16_t * avdtp_cid);
uint8_t avdtp_disconnect(uint16_t avdtp_cid, avdtp_context_t * context);
uint8_t avdtp_open_stream(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, avdtp_context_t * context);
uint8_t avdtp_start_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context);
uint8_t avdtp_stop_stream (uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context);
uint8_t avdtp_abort_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context);
uint8_t avdtp_suspend_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context);
void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context);
void avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context);
void avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context);
void avdtp_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context);
void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
void avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context);
void avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context);
void avdtp_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context);
void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context);
uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context);
avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context);

View File

@ -87,7 +87,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
connection->error_code = BAD_LENGTH;
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_acceptor(connection, connection->tl2cap_signaling_cid);
return;
}
@ -96,7 +96,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
log_info(" ACP: AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS");
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS;
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_acceptor(connection, connection->tl2cap_signaling_cid);
return;
case AVDTP_SI_GET_CAPABILITIES:
case AVDTP_SI_GET_ALL_CAPABILITIES:
@ -122,7 +122,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
}
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_acceptor(connection, connection->tl2cap_signaling_cid);
return;
}
break;
@ -145,7 +145,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
connection->reject_service_category = connection->query_seid;
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_acceptor(connection, connection->tl2cap_signaling_cid);
return;
}
// deal with first susspended seid
@ -158,7 +158,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
connection->num_suspended_seids = 0;
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_acceptor(connection, connection->tl2cap_signaling_cid);
return;
}
break;
@ -167,7 +167,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_GENERAL_REJECT_WITH_ERROR_CODE;
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
log_info("AVDTP_CMD_MSG signal %d not implemented, general reject", connection->signaling_packet.signal_identifier);
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_acceptor(connection, connection->tl2cap_signaling_cid);
return;
}
@ -248,14 +248,14 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){
switch (sep.configuration.media_codec.media_codec_type){
case AVDTP_CODEC_SBC:
avdtp_signaling_emit_media_codec_sbc_configuration(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->acp_seid, sep.configuration.media_codec);
avdtp_signaling_emit_media_codec_sbc_configuration(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), connection->acp_seid, sep.configuration.media_codec);
break;
default:
avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->acp_seid, sep.configuration.media_codec);
avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), connection->acp_seid, sep.configuration.media_codec);
break;
}
}
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->signaling_packet.signal_identifier, 0);
avdtp_signaling_emit_accept(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), connection->signaling_packet.signal_identifier);
break;
}
case AVDTP_SI_RECONFIGURE:{
@ -292,14 +292,14 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){
switch (sep.capabilities.media_codec.media_codec_type){
case AVDTP_CODEC_SBC:
avdtp_signaling_emit_media_codec_sbc_reconfiguration(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->acp_seid, sep.capabilities.media_codec);
avdtp_signaling_emit_media_codec_sbc_reconfiguration(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), connection->acp_seid, sep.capabilities.media_codec);
break;
default:
avdtp_signaling_emit_media_codec_other_reconfiguration(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->acp_seid, sep.capabilities.media_codec);
avdtp_signaling_emit_media_codec_other_reconfiguration(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), connection->acp_seid, sep.capabilities.media_codec);
break;
}
}
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->signaling_packet.signal_identifier, 0);
avdtp_signaling_emit_accept(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), connection->signaling_packet.signal_identifier);
break;
}
@ -402,7 +402,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
if (!request_to_send){
log_info(" ACP: NOT IMPLEMENTED");
}
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_acceptor(connection, connection->tl2cap_signaling_cid);
}
static int avdtp_acceptor_send_seps_response(uint16_t cid, uint8_t transaction_label, avdtp_stream_endpoint_t * endpoints){
@ -460,19 +460,19 @@ void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avd
case AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS:
connection->state = AVDTP_SIGNALING_CONNECTION_OPENED;
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE;
avdtp_acceptor_send_seps_response(connection->l2cap_signaling_cid, connection->acceptor_transaction_label, (avdtp_stream_endpoint_t *) stream_endpoints);
avdtp_acceptor_send_seps_response(connection->tl2cap_signaling_cid, connection->acceptor_transaction_label, (avdtp_stream_endpoint_t *) stream_endpoints);
break;
case AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE:
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE;
avdtp_acceptor_send_response_reject_with_error_code(connection->l2cap_signaling_cid, connection->reject_signal_identifier, connection->error_code, connection->acceptor_transaction_label);
avdtp_acceptor_send_response_reject_with_error_code(connection->tl2cap_signaling_cid, connection->reject_signal_identifier, connection->error_code, connection->acceptor_transaction_label);
break;
case AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE:
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE;
avdtp_acceptor_send_response_reject_service_category(connection->l2cap_signaling_cid, connection->reject_signal_identifier, connection->reject_service_category, connection->error_code, connection->acceptor_transaction_label);
avdtp_acceptor_send_response_reject_service_category(connection->tl2cap_signaling_cid, connection->reject_signal_identifier, connection->reject_service_category, connection->error_code, connection->acceptor_transaction_label);
break;
case AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_GENERAL_REJECT_WITH_ERROR_CODE:
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE;
avdtp_acceptor_send_response_general_reject(connection->l2cap_signaling_cid, connection->reject_signal_identifier, connection->acceptor_transaction_label);
avdtp_acceptor_send_response_general_reject(connection->tl2cap_signaling_cid, connection->reject_signal_identifier, connection->acceptor_transaction_label);
break;
default:
sent = 0;
@ -489,7 +489,7 @@ void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avd
uint8_t reject_service_category = connection->reject_service_category;
avdtp_signal_identifier_t reject_signal_identifier = connection->reject_signal_identifier;
uint8_t error_code = connection->error_code;
uint16_t cid = stream_endpoint->connection ? stream_endpoint->connection->l2cap_signaling_cid : connection->l2cap_signaling_cid;
uint16_t cid = stream_endpoint->connection ? stream_endpoint->connection->tl2cap_signaling_cid : connection->tl2cap_signaling_cid;
uint8_t trid = stream_endpoint->connection ? stream_endpoint->connection->acceptor_transaction_label : connection->acceptor_transaction_label;
avdtp_acceptor_stream_endpoint_state_t acceptor_config_state = stream_endpoint->acceptor_config_state;
@ -603,10 +603,9 @@ void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avd
log_info(" ACP: NOT IMPLEMENTED");
sent = 0;
}
avdtp_signaling_emit_accept(context->avdtp_callback, connection->con_handle, connection->int_seid, connection->signaling_packet.signal_identifier, status);
avdtp_signaling_emit_accept(context->avdtp_callback, connection->avdtp_cid, avdtp_local_seid(stream_endpoint), connection->signaling_packet.signal_identifier);
// check fragmentation
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
avdtp_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_acceptor(connection, connection->tl2cap_signaling_cid);
}
}

View File

@ -75,7 +75,7 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
} else {
stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(connection->acp_seid, context);
if (!stream_endpoint){
stream_endpoint = avdtp_stream_endpoint_with_seid(connection->int_seid, context);
stream_endpoint = avdtp_stream_endpoint_with_seid(connection->local_seid, context);
}
if (!stream_endpoint) return;
sep.seid = connection->acp_seid;
@ -117,22 +117,22 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
if (avdtp_find_remote_sep(connection, sep.seid) == 0xFF){
connection->remote_seps[connection->remote_seps_num++] = sep;
}
avdtp_signaling_emit_sep(context->avdtp_callback, connection->l2cap_signaling_cid, sep);
avdtp_signaling_emit_sep(context->avdtp_callback, connection->avdtp_cid, sep);
}
break;
}
case AVDTP_SI_GET_CAPABILITIES:
case AVDTP_SI_GET_ALL_CAPABILITIES:
log_info("AVDTP_SI_GET(_ALL)_CAPABILITIES int %d, acp %d", connection->int_seid, connection->acp_seid);
log_info("AVDTP_SI_GET(_ALL)_CAPABILITIES int %d, acp %d", connection->local_seid, connection->acp_seid);
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, packet+offset, size-offset);
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(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->acp_seid, sep.capabilities.media_codec);
avdtp_signaling_emit_media_codec_sbc_capability(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->acp_seid, sep.capabilities.media_codec);
break;
default:
avdtp_signaling_emit_media_codec_other_capability(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->acp_seid, sep.capabilities.media_codec);
avdtp_signaling_emit_media_codec_other_capability(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->acp_seid, sep.capabilities.media_codec);
break;
}
}
@ -144,10 +144,10 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){
switch (sep.configuration.media_codec.media_codec_type){
case AVDTP_CODEC_SBC:
avdtp_signaling_emit_media_codec_sbc_configuration(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->acp_seid, sep.configuration.media_codec);
avdtp_signaling_emit_media_codec_sbc_configuration(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->acp_seid, sep.configuration.media_codec);
break;
default:
avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->acp_seid, sep.configuration.media_codec);
avdtp_signaling_emit_media_codec_other_configuration(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->acp_seid, sep.configuration.media_codec);
break;
}
}
@ -228,16 +228,16 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
log_info(" AVDTP_RESPONSE_ACCEPT_MSG, signal %d not implemented", connection->signaling_packet.signal_identifier);
break;
}
avdtp_signaling_emit_accept(context->avdtp_callback, connection->l2cap_signaling_cid, 0, connection->signaling_packet.signal_identifier, status);
avdtp_signaling_emit_accept(context->avdtp_callback, connection->avdtp_cid, 0, connection->signaling_packet.signal_identifier);
connection->initiator_transaction_label++;
break;
case AVDTP_RESPONSE_REJECT_MSG:
log_info(" AVDTP_RESPONSE_REJECT_MSG signal %d", connection->signaling_packet.signal_identifier);
avdtp_signaling_emit_reject(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->signaling_packet.signal_identifier);
avdtp_signaling_emit_reject(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->signaling_packet.signal_identifier);
return;
case AVDTP_GENERAL_REJECT_MSG:
log_info(" AVDTP_GENERAL_REJECT_MSG signal %d", connection->signaling_packet.signal_identifier);
avdtp_signaling_emit_general_reject(context->avdtp_callback, connection->l2cap_signaling_cid, connection->int_seid, connection->signaling_packet.signal_identifier);
avdtp_signaling_emit_general_reject(context->avdtp_callback, connection->avdtp_cid, connection->local_seid, connection->signaling_packet.signal_identifier);
return;
default:
break;
@ -250,22 +250,22 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS:
log_info(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS");
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);
avdtp_initiator_send_signaling_cmd(connection->tl2cap_signaling_cid, AVDTP_SI_DISCOVER, connection->initiator_transaction_label);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES:
log_info(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES");
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);
avdtp_initiator_send_signaling_cmd_with_seid(connection->tl2cap_signaling_cid, AVDTP_SI_GET_CAPABILITIES, connection->initiator_transaction_label, connection->acp_seid);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES:
log_info(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES");
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);
avdtp_initiator_send_signaling_cmd_with_seid(connection->tl2cap_signaling_cid, AVDTP_SI_GET_ALL_CAPABILITIES, connection->initiator_transaction_label, connection->acp_seid);
break;
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION:
log_info(" INT: AVDTP_INITIATOR_W4_GET_CONFIGURATION");
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);
avdtp_initiator_send_signaling_cmd_with_seid(connection->tl2cap_signaling_cid, AVDTP_SI_GET_CONFIGURATION, connection->initiator_transaction_label, connection->acp_seid);
break;
default:
sent = 0;
@ -279,7 +279,7 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(connection->acp_seid, context);
if (!stream_endpoint){
stream_endpoint = avdtp_stream_endpoint_with_seid(connection->int_seid, context);
stream_endpoint = avdtp_stream_endpoint_with_seid(connection->local_seid, context);
}
if (!stream_endpoint) return;
@ -289,9 +289,9 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
if (stream_endpoint->start_stream){
stream_endpoint->start_stream = 0;
if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_OPENED){
connection->int_seid = stream_endpoint->sep.seid;
connection->local_seid = stream_endpoint->sep.seid;
connection->acp_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_START, connection->initiator_transaction_label++, connection->acp_seid);
avdtp_initiator_send_signaling_cmd_with_seid(connection->tl2cap_signaling_cid, AVDTP_SI_START, connection->initiator_transaction_label++, connection->acp_seid);
return;
}
return;
@ -300,9 +300,9 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
if (stream_endpoint->stop_stream){
stream_endpoint->stop_stream = 0;
if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_OPENED){
connection->int_seid = stream_endpoint->sep.seid;
connection->local_seid = stream_endpoint->sep.seid;
connection->acp_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_CLOSE, connection->initiator_transaction_label++, connection->acp_seid);
avdtp_initiator_send_signaling_cmd_with_seid(connection->tl2cap_signaling_cid, AVDTP_SI_CLOSE, connection->initiator_transaction_label++, connection->acp_seid);
return;
}
}
@ -314,10 +314,10 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
case AVDTP_STREAM_ENDPOINT_CLOSING:
case AVDTP_STREAM_ENDPOINT_OPENED:
case AVDTP_STREAM_ENDPOINT_STREAMING:
connection->int_seid = stream_endpoint->sep.seid;
connection->local_seid = stream_endpoint->sep.seid;
connection->acp_seid = connection->remote_seps[stream_endpoint->remote_sep_index].seid;
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_ABORT, connection->initiator_transaction_label++, connection->acp_seid);
avdtp_initiator_send_signaling_cmd_with_seid(connection->tl2cap_signaling_cid, AVDTP_SI_ABORT, connection->initiator_transaction_label++, connection->acp_seid);
return;
default:
break;
@ -328,7 +328,7 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
stream_endpoint->suspend_stream = 0;
if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING){
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_SUSPEND, connection->initiator_transaction_label, connection->acp_seid);
avdtp_initiator_send_signaling_cmd_with_seid(connection->tl2cap_signaling_cid, AVDTP_SI_SUSPEND, connection->initiator_transaction_label, connection->acp_seid);
return;
}
}
@ -346,10 +346,10 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
switch (stream_endpoint_state){
case AVDTP_INITIATOR_W2_SET_CONFIGURATION:
case AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID:{
log_info(" INT: AVDTP_INITIATOR_W2_(RE)CONFIGURATION bitmap, int seid %d, acp seid %d", connection->int_seid, connection->acp_seid);
log_info(" INT: AVDTP_INITIATOR_W2_(RE)CONFIGURATION bitmap, int seid %d, acp seid %d", connection->local_seid, connection->acp_seid);
// log_info_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.int_seid = connection->local_seid;
connection->signaling_packet.signal_identifier = AVDTP_SI_SET_CONFIGURATION;
@ -360,30 +360,30 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
avdtp_prepare_capabilities(&connection->signaling_packet, connection->initiator_transaction_label, stream_endpoint->remote_capabilities_bitmap, stream_endpoint->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);
uint16_t pos = avdtp_signaling_create_fragment(connection->tl2cap_signaling_cid, &connection->signaling_packet, out_buffer);
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_FRAGMENTATED_COMMAND;
log_info(" INT: fragmented");
}
l2cap_send_prepared(connection->l2cap_signaling_cid, pos);
l2cap_send_prepared(connection->tl2cap_signaling_cid, pos);
break;
}
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);
uint16_t pos = avdtp_signaling_create_fragment(connection->tl2cap_signaling_cid, &connection->signaling_packet, out_buffer);
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_FRAGMENTATED_COMMAND;
log_info(" INT: fragmented");
}
l2cap_send_prepared(connection->l2cap_signaling_cid, pos);
l2cap_send_prepared(connection->tl2cap_signaling_cid, pos);
break;
}
case AVDTP_INITIATOR_W2_OPEN_STREAM:
switch (stream_endpoint->state){
case AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM:
log_info(" INT: AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM");
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_OPEN, connection->initiator_transaction_label, connection->acp_seid);
avdtp_initiator_send_signaling_cmd_with_seid(connection->tl2cap_signaling_cid, AVDTP_SI_OPEN, connection->initiator_transaction_label, connection->acp_seid);
break;
default:
sent = 0;
@ -397,6 +397,6 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
// check fragmentation
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
avdtp_request_can_send_now_initiator(connection, connection->tl2cap_signaling_cid);
}
}

View File

@ -141,55 +141,55 @@ void avdtp_sink_register_packet_handler(btstack_packet_handler_t callback){
avdtp_sink_context->avdtp_callback = callback;
}
void avdtp_sink_connect(bd_addr_t remote){
avdtp_connect(remote, AVDTP_SOURCE, avdtp_sink_context);
uint8_t avdtp_sink_connect(bd_addr_t remote, uint16_t * avdtp_cid){
return avdtp_connect(remote, AVDTP_SOURCE, avdtp_sink_context, avdtp_cid);
}
void avdtp_sink_disconnect(uint16_t avdtp_cid){
avdtp_disconnect(avdtp_cid, avdtp_sink_context);
uint8_t avdtp_sink_disconnect(uint16_t avdtp_cid){
return avdtp_disconnect(avdtp_cid, avdtp_sink_context);
}
void avdtp_sink_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid){
avdtp_open_stream(avdtp_cid, int_seid, acp_seid, avdtp_sink_context);
uint8_t avdtp_sink_open_stream(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid){
return avdtp_open_stream(avdtp_cid, local_seid, remote_seid, avdtp_sink_context);
}
void avdtp_sink_start_stream(uint8_t int_seid){
avdtp_start_stream(int_seid, avdtp_sink_context);
uint8_t avdtp_sink_start_stream(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_start_stream(avdtp_cid, local_seid, avdtp_sink_context);
}
void avdtp_sink_stop_stream(uint8_t int_seid){
avdtp_stop_stream(int_seid, avdtp_sink_context);
uint8_t avdtp_sink_stop_stream(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_stop_stream(avdtp_cid, local_seid, avdtp_sink_context);
}
void avdtp_sink_abort_stream(uint8_t int_seid){
avdtp_abort_stream(int_seid, avdtp_sink_context);
uint8_t avdtp_sink_abort_stream(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_abort_stream(avdtp_cid, local_seid, avdtp_sink_context);
}
void avdtp_sink_suspend(uint8_t int_seid){
avdtp_suspend_stream(int_seid, avdtp_sink_context);
uint8_t avdtp_sink_suspend(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_suspend_stream(avdtp_cid, local_seid, avdtp_sink_context);
}
void avdtp_sink_discover_stream_endpoints(uint16_t avdtp_cid){
avdtp_discover_stream_endpoints(avdtp_cid, avdtp_sink_context);
}
void avdtp_sink_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid){
avdtp_get_capabilities(avdtp_cid, acp_seid, avdtp_sink_context);
void avdtp_sink_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){
avdtp_get_capabilities(avdtp_cid, remote_seid, avdtp_sink_context);
}
void avdtp_sink_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid){
avdtp_get_all_capabilities(avdtp_cid, acp_seid, avdtp_sink_context);
void avdtp_sink_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){
avdtp_get_all_capabilities(avdtp_cid, remote_seid, avdtp_sink_context);
}
void avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid){
avdtp_get_configuration(avdtp_cid, acp_seid, avdtp_sink_context);
void avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid){
avdtp_get_configuration(avdtp_cid, remote_seid, avdtp_sink_context);
}
void avdtp_sink_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_set_configuration(avdtp_cid, int_seid, acp_seid, configured_services_bitmap, configuration, avdtp_sink_context);
void avdtp_sink_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_set_configuration(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_sink_context);
}
void avdtp_sink_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_reconfigure(avdtp_cid, int_seid, acp_seid, configured_services_bitmap, configuration, avdtp_sink_context);
void avdtp_sink_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_reconfigure(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_sink_context);
}

View File

@ -83,15 +83,16 @@ void avdtp_sink_register_packet_handler(btstack_packet_handler_t callback);
/**
* @brief Connect to device with a bluetooth address. (and perform configuration?)
* @param bd_addr
* @param avdtp_cid Assigned avdtp cid
*/
void avdtp_sink_connect(bd_addr_t bd_addr);
uint8_t avdtp_sink_connect(bd_addr_t bd_addr, uint16_t * avdtp_cid);
void avdtp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size));
/**
* @brief Disconnect from device with connection handle.
* @param avdtp_cid
*/
void avdtp_sink_disconnect(uint16_t avdtp_cid);
uint8_t avdtp_sink_disconnect(uint16_t avdtp_cid);
/**
* @brief Discover stream endpoints
@ -136,32 +137,32 @@ void avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid);
* @param avdtp_cid
* @param seid
*/
void avdtp_sink_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
uint8_t avdtp_sink_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
/**
* @brief Start stream
* @param local_seid
*/
void avdtp_sink_start_stream(uint8_t local_seid);
uint8_t avdtp_sink_start_stream(uint16_t avdtp_cid, uint8_t local_seid);
/**
* @brief Abort stream
* @param local_seid
*/
void avdtp_sink_abort_stream(uint8_t local_seid);
uint8_t avdtp_sink_abort_stream(uint16_t avdtp_cid, uint8_t local_seid);
/**
* @brief Start stream
* @param local_seid
*/
void avdtp_sink_stop_stream(uint8_t local_seid);
uint8_t avdtp_sink_stop_stream(uint16_t avdtp_cid, uint8_t local_seid);
/**
* @brief Suspend stream
* @param local_seid
*/
void avdtp_sink_suspend(uint8_t local_seid);
uint8_t avdtp_sink_suspend(uint16_t avdtp_cid, uint8_t local_seid);
/* API_END */

View File

@ -105,56 +105,56 @@ void avdtp_source_register_packet_handler(btstack_packet_handler_t callback){
avdtp_source_context->avdtp_callback = callback;
}
void avdtp_source_connect(bd_addr_t remote){
avdtp_connect(remote, AVDTP_SINK, avdtp_source_context);
uint8_t avdtp_source_connect(bd_addr_t remote, uint16_t * avdtp_cid){
return avdtp_connect(remote, AVDTP_SINK, avdtp_source_context, avdtp_cid);
}
void avdtp_source_disconnect(uint16_t con_handle){
avdtp_disconnect(con_handle, avdtp_source_context);
uint8_t avdtp_source_disconnect(uint16_t avdtp_cid){
return avdtp_disconnect(avdtp_cid, avdtp_source_context);
}
void avdtp_source_open_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
avdtp_open_stream(con_handle, int_seid, acp_seid, avdtp_source_context);
uint8_t avdtp_source_open_stream(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid){
return avdtp_open_stream(avdtp_cid, local_seid, remote_seid, avdtp_source_context);
}
void avdtp_source_start_stream(uint8_t int_seid){
avdtp_start_stream(int_seid, avdtp_source_context);
uint8_t avdtp_source_start_stream(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_start_stream(avdtp_cid, local_seid, avdtp_source_context);
}
void avdtp_source_stop_stream(uint8_t int_seid){
avdtp_stop_stream(int_seid, avdtp_source_context);
uint8_t avdtp_source_stop_stream(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_stop_stream(avdtp_cid, local_seid, avdtp_source_context);
}
void avdtp_source_abort_stream(uint8_t int_seid){
avdtp_abort_stream(int_seid, avdtp_source_context);
uint8_t avdtp_source_abort_stream(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_abort_stream(avdtp_cid, local_seid, avdtp_source_context);
}
void avdtp_source_suspend(uint8_t int_seid){
avdtp_suspend_stream(int_seid, avdtp_source_context);
uint8_t avdtp_source_suspend(uint16_t avdtp_cid, uint8_t local_seid){
return avdtp_suspend_stream(avdtp_cid, local_seid, avdtp_source_context);
}
void avdtp_source_discover_stream_endpoints(uint16_t con_handle){
avdtp_discover_stream_endpoints(con_handle, avdtp_source_context);
void avdtp_source_discover_stream_endpoints(uint16_t avdtp_cid){
avdtp_discover_stream_endpoints(avdtp_cid, avdtp_source_context);
}
void avdtp_source_get_capabilities(uint16_t con_handle, uint8_t acp_seid){
avdtp_get_capabilities(con_handle, acp_seid, avdtp_source_context);
void avdtp_source_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){
avdtp_get_capabilities(avdtp_cid, remote_seid, avdtp_source_context);
}
void avdtp_source_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid){
avdtp_get_all_capabilities(con_handle, acp_seid, avdtp_source_context);
void avdtp_source_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){
avdtp_get_all_capabilities(avdtp_cid, remote_seid, avdtp_source_context);
}
void avdtp_source_get_configuration(uint16_t con_handle, uint8_t acp_seid){
avdtp_get_configuration(con_handle, acp_seid, avdtp_source_context);
void avdtp_source_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid){
avdtp_get_configuration(avdtp_cid, remote_seid, avdtp_source_context);
}
void avdtp_source_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_set_configuration(con_handle, int_seid, acp_seid, configured_services_bitmap, configuration, avdtp_source_context);
void avdtp_source_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_set_configuration(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_source_context);
}
void avdtp_source_reconfigure(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_reconfigure(con_handle, int_seid, acp_seid, configured_services_bitmap, configuration, avdtp_source_context);
void avdtp_source_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){
avdtp_reconfigure(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_source_context);
}
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){

View File

@ -70,14 +70,15 @@ void avdtp_source_register_packet_handler(btstack_packet_handler_t callback);
/**
* @brief Connect to device with a bluetooth address. (and perform configuration?)
* @param bd_addr
* @param avdtp_cid Assigned avdtp cid
*/
void avdtp_source_connect(bd_addr_t bd_addr);
uint8_t avdtp_source_connect(bd_addr_t bd_addr, uint16_t * avdtp_cid);
/**
* @brief Disconnect from device with connection handle.
* @param avdtp_cid
*/
void avdtp_source_disconnect(uint16_t avdtp_cid);
uint8_t avdtp_source_disconnect(uint16_t avdtp_cid);
/**
* @brief Discover stream endpoints
@ -122,31 +123,31 @@ void avdtp_source_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid);
* @param avdtp_cid
* @param seid
*/
void avdtp_source_open_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid);
uint8_t avdtp_source_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
/**
* @brief Start stream
* @param local_seid
*/
void avdtp_source_start_stream(uint8_t local_seid);
uint8_t avdtp_source_start_stream(uint16_t avdtp_cid, uint8_t local_seid);
/**
* @brief Abort stream
* @param local_seid
*/
void avdtp_source_abort_stream(uint8_t local_seid);
uint8_t avdtp_source_abort_stream(uint16_t avdtp_cid, uint8_t local_seid);
/**
* @brief Start stream
* @param local_seid
*/
void avdtp_source_stop_stream(uint8_t local_seid);
uint8_t avdtp_source_stop_stream(uint16_t avdtp_cid, uint8_t local_seid);
/**
* @brief Suspend stream
* @param local_seid
*/
void avdtp_source_suspend(uint8_t local_seid);
uint8_t avdtp_source_suspend(uint16_t avdtp_cid, uint8_t local_seid);
avdtp_stream_endpoint_t * avdtp_source_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type);

View File

@ -81,12 +81,23 @@ avdtp_connection_t * avdtp_connection_for_bd_addr(bd_addr_t addr, avdtp_context_
return NULL;
}
avdtp_connection_t * avdtp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid, avdtp_context_t * context){
avdtp_connection_t * avdtp_connection_for_avdtp_cid(uint16_t avdtp_cid, avdtp_context_t * context){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, &context->connections);
while (btstack_linked_list_iterator_has_next(&it)){
avdtp_connection_t * connection = (avdtp_connection_t *)btstack_linked_list_iterator_next(&it);
if (connection->l2cap_signaling_cid != l2cap_cid) continue;
if (connection->avdtp_cid != avdtp_cid) continue;
return connection;
}
return NULL;
}
avdtp_connection_t * avdtp_connection_for_tl2cap_signaling_cid(uint16_t l2cap_cid, avdtp_context_t * context){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, &context->connections);
while (btstack_linked_list_iterator_has_next(&it)){
avdtp_connection_t * connection = (avdtp_connection_t *)btstack_linked_list_iterator_next(&it);
if (connection->tl2cap_signaling_cid != l2cap_cid) continue;
return connection;
}
return NULL;
@ -506,7 +517,7 @@ void avdtp_streaming_emit_can_send_media_packet_now(btstack_packet_handler_t cal
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint8_t status){
void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint8_t status){
if (!callback) return;
uint8_t event[8];
int pos = 0;
@ -515,8 +526,8 @@ void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callba
event[pos++] = AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED;
little_endian_store_16(event, pos, avdtp_cid);
pos += 2;
event[pos++] = int_seid;
event[pos++] = acp_seid;
event[pos++] = local_seid;
event[pos++] = remote_seid;
event[pos++] = status;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
@ -537,22 +548,21 @@ void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t avdtp_
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier, uint8_t status){
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, avdtp_signal_identifier_t identifier){
if (!callback) return;
uint8_t event[8];
uint8_t event[7];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_ACCEPT;
little_endian_store_16(event, pos, avdtp_cid);
pos += 2;
event[pos++] = int_seid;
event[pos++] = local_seid;
event[pos++] = identifier;
event[pos++] = status;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier){
void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, avdtp_signal_identifier_t identifier){
if (!callback) return;
uint8_t event[7];
int pos = 0;
@ -561,12 +571,12 @@ void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t avd
event[pos++] = AVDTP_SUBEVENT_SIGNALING_REJECT;
little_endian_store_16(event, pos, avdtp_cid);
pos += 2;
event[pos++] = int_seid;
event[pos++] = local_seid;
event[pos++] = identifier;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier){
void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, avdtp_signal_identifier_t identifier){
if (!callback) return;
uint8_t event[7];
int pos = 0;
@ -575,12 +585,12 @@ void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint
event[pos++] = AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT;
little_endian_store_16(event, pos, avdtp_cid);
pos += 2;
event[pos++] = int_seid;
event[pos++] = local_seid;
event[pos++] = identifier;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
uint8_t event[15];
int pos = 0;
@ -589,8 +599,8 @@ void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t ca
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY;
little_endian_store_16(event, pos, avdtp_cid);
pos += 2;
event[pos++] = int_seid;
event[pos++] = acp_seid;
event[pos++] = local_seid;
event[pos++] = remote_seid;
event[pos++] = media_codec.media_type;
event[pos++] = media_codec.media_codec_information[0] >> 4;
event[pos++] = media_codec.media_codec_information[0] & 0x0F;
@ -602,7 +612,7 @@ void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t ca
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
uint8_t event[111];
int pos = 0;
@ -611,8 +621,8 @@ void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY;
little_endian_store_16(event, pos, avdtp_cid);
pos += 2;
event[pos++] = int_seid;
event[pos++] = acp_seid;
event[pos++] = local_seid;
event[pos++] = remote_seid;
event[pos++] = media_codec.media_type;
little_endian_store_16(event, pos, media_codec.media_codec_type);
pos += 2;
@ -626,7 +636,7 @@ void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static inline void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){
static inline void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){
if (!callback) return;
uint8_t event[16+2];
int pos = 0;
@ -636,8 +646,8 @@ static inline void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION;
little_endian_store_16(event, pos, avdtp_cid);
pos += 2;
event[pos++] = int_seid;
event[pos++] = acp_seid;
event[pos++] = local_seid;
event[pos++] = remote_seid;
event[pos++] = reconfigure;
uint8_t num_channels = 0;
@ -706,17 +716,17 @@ static inline void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_media_codec_sbc_configuration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
void avdtp_signaling_emit_media_codec_sbc_configuration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
avdtp_signaling_emit_media_codec_sbc(callback, avdtp_cid, int_seid, acp_seid, media_codec, 0);
avdtp_signaling_emit_media_codec_sbc(callback, avdtp_cid, local_seid, remote_seid, media_codec, 0);
}
void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
avdtp_signaling_emit_media_codec_sbc(callback, avdtp_cid, int_seid, acp_seid, media_codec, 1);
avdtp_signaling_emit_media_codec_sbc(callback, avdtp_cid, local_seid, remote_seid, media_codec, 1);
}
static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){
static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){
uint8_t event[112];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
@ -724,8 +734,8 @@ static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION;
little_endian_store_16(event, pos, avdtp_cid);
pos += 2;
event[pos++] = int_seid;
event[pos++] = acp_seid;
event[pos++] = local_seid;
event[pos++] = remote_seid;
event[pos++] = reconfigure;
event[pos++] = media_codec.media_type;
@ -742,14 +752,14 @@ static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
avdtp_signaling_emit_media_codec_other(callback, avdtp_cid, int_seid, acp_seid, media_codec, 0);
avdtp_signaling_emit_media_codec_other(callback, avdtp_cid, local_seid, remote_seid, media_codec, 0);
}
void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec){
void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
avdtp_signaling_emit_media_codec_other(callback, avdtp_cid, int_seid, acp_seid, media_codec, 1);
avdtp_signaling_emit_media_codec_other(callback, avdtp_cid, local_seid, remote_seid, media_codec, 1);
}
@ -790,4 +800,16 @@ uint8_t avdtp_find_remote_sep(avdtp_connection_t * connection, uint8_t remote_se
}
return AVDTP_INVALID_SEP_INDEX;
}
uint8_t avdtp_local_seid(avdtp_stream_endpoint_t * stream_endpoint){
if (!stream_endpoint) return 0;
return stream_endpoint->sep.seid;
}
uint8_t avdtp_remote_seid(avdtp_stream_endpoint_t * stream_endpoint){
if (!stream_endpoint) return 0;
if (!stream_endpoint->connection) return 0;
return stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid;
}

View File

@ -55,7 +55,8 @@ extern "C" {
#define AVDTP_INVALID_SEP_INDEX 0xff
avdtp_connection_t * avdtp_connection_for_bd_addr(bd_addr_t addr, avdtp_context_t * context);
avdtp_connection_t * avdtp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid, avdtp_context_t * context);
avdtp_connection_t * avdtp_connection_for_avdtp_cid(uint16_t l2cap_cid, avdtp_context_t * context);
avdtp_connection_t * avdtp_connection_for_tl2cap_signaling_cid(uint16_t l2cap_cid, avdtp_context_t * context);
avdtp_stream_endpoint_t * avdtp_stream_endpoint_for_l2cap_cid(uint16_t l2cap_cid, avdtp_context_t * context);
avdtp_stream_endpoint_t * avdtp_stream_endpoint_with_seid(uint8_t seid, avdtp_context_t * context);
avdtp_stream_endpoint_t * avdtp_stream_endpoint_associated_with_acp_seid(uint16_t acp_seid, avdtp_context_t * context);
@ -80,7 +81,7 @@ int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * sig
void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, bd_addr_t addr, uint8_t status);
void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint8_t status);
void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t avdtp_cid, avdtp_sep_t sep);
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t seid, avdtp_signal_identifier_t identifier, uint8_t status);
void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t seid, avdtp_signal_identifier_t identifier);
void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier);
void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier);
void avdtp_streaming_emit_can_send_media_packet_now(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint16_t sequence_number);
@ -101,6 +102,10 @@ uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoin
void avdtp_initialize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint);
uint8_t avdtp_find_remote_sep(avdtp_connection_t * connection, uint8_t remote_seid);
// uint16_t avdtp_cid(avdtp_stream_endpoint_t * stream_endpoint);
uint8_t avdtp_local_seid(avdtp_stream_endpoint_t * stream_endpoint);
uint8_t avdtp_remote_seid(avdtp_stream_endpoint_t * stream_endpoint);
#if defined __cplusplus
}
#endif