use a2dp interface to init demo app

This commit is contained in:
Milanka Ringwald 2017-04-18 14:05:17 +02:00
parent b442c9e641
commit 274391e8b2
6 changed files with 101 additions and 43 deletions

View File

@ -52,6 +52,7 @@
static const char * default_a2dp_source_service_name = "BTstack A2DP Source Service"; static const char * default_a2dp_source_service_name = "BTstack A2DP Source Service";
static const char * default_a2dp_source_service_provider_name = "BTstack A2DP Source Service Provider"; static const char * default_a2dp_source_service_provider_name = "BTstack A2DP Source Service Provider";
static avdtp_context_t a2dp_source_context;
// static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); // static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
@ -135,4 +136,30 @@ void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_ha
} }
// static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ // static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
// UNUSED(channel);
// UNUSED(size);
// UNUSED(packet_type);
// UNUSED(packet);
// } // }
void a2dp_source_register_packet_handler(btstack_packet_handler_t callback){
if (callback == NULL){
log_error("a2dp_source_register_packet_handler called with NULL callback");
return;
}
avdtp_source_register_packet_handler(callback);
a2dp_source_context.a2dp_callback = callback;
}
void a2dp_source_init(void){
avdtp_source_init(&a2dp_source_context);
// l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0);
}
avdtp_stream_endpoint_t * a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len){
avdtp_stream_endpoint_t * local_stream_endpoint = avdtp_source_create_stream_endpoint(AVDTP_SOURCE, media_type);
avdtp_source_register_media_transport_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
avdtp_source_register_media_codec_category(avdtp_stream_endpoint_seid(local_stream_endpoint), media_type, media_codec_type, media_codec_info, media_codec_info_len);
return local_stream_endpoint;
}

View File

@ -64,6 +64,34 @@ extern "C" {
*/ */
void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name); void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name);
void a2dp_source_init(void);
void a2dp_source_register_packet_handler(btstack_packet_handler_t callback);
avdtp_stream_endpoint_t * a2dp_source_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len);
void a2dp_source_connect(bd_addr_t bd_addr);
/**
* @brief Start stream
* @param avdtp_cid
* @param seid
*/
void a2dp_source_start_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
/**
* @brief Start stream
* @param avdtp_cid
* @param seid
*/
void a2dp_source_stop_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid);
/**
* @brief Disconnect from device with connection handle.
* @param avdtp_cid
*/
void a2dp_source_disconnect(uint16_t avdtp_cid);
/* API_END */ /* API_END */
#if defined __cplusplus #if defined __cplusplus

View File

@ -451,6 +451,7 @@ typedef struct {
btstack_linked_list_t stream_endpoints; btstack_linked_list_t stream_endpoints;
uint16_t stream_endpoints_id_counter; uint16_t stream_endpoints_id_counter;
btstack_packet_handler_t avdtp_callback; btstack_packet_handler_t avdtp_callback;
btstack_packet_handler_t a2dp_callback;
void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size); void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
btstack_packet_handler_t packet_handler; btstack_packet_handler_t packet_handler;
} avdtp_context_t; } avdtp_context_t;

View File

@ -51,52 +51,52 @@
#include "avdtp_util.h" #include "avdtp_util.h"
#include "avdtp_source.h" #include "avdtp_source.h"
static avdtp_context_t avdtp_source_context; static avdtp_context_t * avdtp_source_context;
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
void avdtp_source_register_media_transport_category(uint8_t seid){ void avdtp_source_register_media_transport_category(uint8_t seid){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context); avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
avdtp_register_media_transport_category(stream_endpoint); avdtp_register_media_transport_category(stream_endpoint);
} }
void avdtp_source_register_reporting_category(uint8_t seid){ void avdtp_source_register_reporting_category(uint8_t seid){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context); avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
avdtp_register_reporting_category(stream_endpoint); avdtp_register_reporting_category(stream_endpoint);
} }
void avdtp_source_register_delay_reporting_category(uint8_t seid){ void avdtp_source_register_delay_reporting_category(uint8_t seid){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context); avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
avdtp_register_delay_reporting_category(stream_endpoint); avdtp_register_delay_reporting_category(stream_endpoint);
} }
void avdtp_source_register_recovery_category(uint8_t seid, uint8_t maximum_recovery_window_size, uint8_t maximum_number_media_packets){ void avdtp_source_register_recovery_category(uint8_t seid, uint8_t maximum_recovery_window_size, uint8_t maximum_number_media_packets){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context); avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
avdtp_register_recovery_category(stream_endpoint, maximum_recovery_window_size, maximum_number_media_packets); avdtp_register_recovery_category(stream_endpoint, maximum_recovery_window_size, maximum_number_media_packets);
} }
void avdtp_source_register_content_protection_category(uint8_t seid, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len){ void avdtp_source_register_content_protection_category(uint8_t seid, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context); avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
avdtp_register_content_protection_category(stream_endpoint, cp_type, cp_type_value, cp_type_value_len); avdtp_register_content_protection_category(stream_endpoint, cp_type, cp_type_value, cp_type_value_len);
} }
void avdtp_source_register_header_compression_category(uint8_t seid, uint8_t back_ch, uint8_t media, uint8_t recovery){ void avdtp_source_register_header_compression_category(uint8_t seid, uint8_t back_ch, uint8_t media, uint8_t recovery){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context); avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
avdtp_register_header_compression_category(stream_endpoint, back_ch, media, recovery); avdtp_register_header_compression_category(stream_endpoint, back_ch, media, recovery);
} }
void avdtp_source_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len){ void avdtp_source_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, uint8_t * media_codec_info, uint16_t media_codec_info_len){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context); avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
avdtp_register_media_codec_category(stream_endpoint, media_type, media_codec_type, media_codec_info, media_codec_info_len); avdtp_register_media_codec_category(stream_endpoint, media_type, media_codec_type, media_codec_info, media_codec_info_len);
} }
void avdtp_source_register_multiplexing_category(uint8_t seid, uint8_t fragmentation){ void avdtp_source_register_multiplexing_category(uint8_t seid, uint8_t fragmentation){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, &avdtp_source_context); avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(seid, avdtp_source_context);
avdtp_register_multiplexing_category(stream_endpoint, fragmentation); avdtp_register_multiplexing_category(stream_endpoint, fragmentation);
} }
avdtp_stream_endpoint_t * avdtp_source_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type){ avdtp_stream_endpoint_t * avdtp_source_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type){
return avdtp_create_stream_endpoint(sep_type, media_type, &avdtp_source_context); return avdtp_create_stream_endpoint(sep_type, media_type, avdtp_source_context);
} }
void avdtp_source_register_packet_handler(btstack_packet_handler_t callback){ void avdtp_source_register_packet_handler(btstack_packet_handler_t callback){
@ -104,13 +104,13 @@ void avdtp_source_register_packet_handler(btstack_packet_handler_t callback){
log_error("avdtp_source_register_packet_handler called with NULL callback"); log_error("avdtp_source_register_packet_handler called with NULL callback");
return; return;
} }
avdtp_source_context.avdtp_callback = callback; avdtp_source_context->avdtp_callback = callback;
} }
void avdtp_source_connect(bd_addr_t bd_addr){ void avdtp_source_connect(bd_addr_t bd_addr){
avdtp_connection_t * connection = avdtp_connection_for_bd_addr(bd_addr, &avdtp_source_context); avdtp_connection_t * connection = avdtp_connection_for_bd_addr(bd_addr, avdtp_source_context);
if (!connection){ if (!connection){
connection = avdtp_create_connection(bd_addr, &avdtp_source_context); connection = avdtp_create_connection(bd_addr, avdtp_source_context);
} }
if (connection->state != AVDTP_SIGNALING_CONNECTION_IDLE) return; if (connection->state != AVDTP_SIGNALING_CONNECTION_IDLE) return;
connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED; connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED;
@ -118,62 +118,67 @@ void avdtp_source_connect(bd_addr_t bd_addr){
} }
void avdtp_source_disconnect(uint16_t con_handle){ void avdtp_source_disconnect(uint16_t con_handle){
avdtp_disconnect(con_handle, &avdtp_source_context); avdtp_disconnect(con_handle, avdtp_source_context);
} }
void avdtp_source_open_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){ void avdtp_source_open_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
avdtp_open_stream(con_handle, int_seid, acp_seid, &avdtp_source_context); avdtp_open_stream(con_handle, int_seid, acp_seid, avdtp_source_context);
} }
void avdtp_source_start_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){ void avdtp_source_start_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
avdtp_start_stream(con_handle, int_seid, acp_seid, &avdtp_source_context); avdtp_start_stream(con_handle, int_seid, acp_seid, avdtp_source_context);
} }
void avdtp_source_stop_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){ void avdtp_source_stop_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
avdtp_stop_stream(con_handle, int_seid, acp_seid, &avdtp_source_context); avdtp_stop_stream(con_handle, int_seid, acp_seid, avdtp_source_context);
} }
void avdtp_source_abort_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){ void avdtp_source_abort_stream(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
avdtp_abort_stream(con_handle, int_seid, acp_seid, &avdtp_source_context); avdtp_abort_stream(con_handle, int_seid, acp_seid, avdtp_source_context);
} }
void avdtp_source_discover_stream_endpoints(uint16_t con_handle){ void avdtp_source_discover_stream_endpoints(uint16_t con_handle){
avdtp_discover_stream_endpoints(con_handle, &avdtp_source_context); avdtp_discover_stream_endpoints(con_handle, avdtp_source_context);
} }
void avdtp_source_get_capabilities(uint16_t con_handle, uint8_t acp_seid){ void avdtp_source_get_capabilities(uint16_t con_handle, uint8_t acp_seid){
avdtp_get_capabilities(con_handle, acp_seid, &avdtp_source_context); avdtp_get_capabilities(con_handle, acp_seid, avdtp_source_context);
} }
void avdtp_source_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid){ 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); avdtp_get_all_capabilities(con_handle, acp_seid, avdtp_source_context);
} }
void avdtp_source_get_configuration(uint16_t con_handle, uint8_t acp_seid){ void avdtp_source_get_configuration(uint16_t con_handle, uint8_t acp_seid){
avdtp_get_configuration(con_handle, acp_seid, &avdtp_source_context); avdtp_get_configuration(con_handle, acp_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){ 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); avdtp_set_configuration(con_handle, int_seid, acp_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){ 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); avdtp_reconfigure(con_handle, int_seid, acp_seid, configured_services_bitmap, configuration, avdtp_source_context);
} }
void avdtp_source_suspend(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){ void avdtp_source_suspend(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid){
avdtp_suspend(con_handle, int_seid, acp_seid, &avdtp_source_context); avdtp_suspend(con_handle, int_seid, acp_seid, avdtp_source_context);
} }
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
avdtp_packet_handler(packet_type, channel, packet, size, &avdtp_source_context); avdtp_packet_handler(packet_type, channel, packet, size, avdtp_source_context);
} }
void avdtp_source_init(void){ void avdtp_source_init(avdtp_context_t * avdtp_context){
avdtp_source_context.stream_endpoints = NULL; if (!avdtp_context){
avdtp_source_context.connections = NULL; log_error("avdtp_source_context is NULL");
avdtp_source_context.stream_endpoints_id_counter = 0; return;
avdtp_source_context.packet_handler = packet_handler; }
avdtp_source_context = avdtp_context;
avdtp_source_context->stream_endpoints = NULL;
avdtp_source_context->connections = NULL;
avdtp_source_context->stream_endpoints_id_counter = 0;
avdtp_source_context->packet_handler = packet_handler;
l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0); l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0);
} }
@ -260,7 +265,7 @@ static void avdtp_source_copy_media_payload(uint8_t * media_packet, int size, in
} }
void avdtp_source_stream_send_media_payload(uint16_t l2cap_media_cid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker){ void avdtp_source_stream_send_media_payload(uint16_t l2cap_media_cid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker){
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(l2cap_media_cid, &avdtp_source_context); avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(l2cap_media_cid, avdtp_source_context);
if (!stream_endpoint) { if (!stream_endpoint) {
printf("no stream_endpoint found for 0x%02x", l2cap_media_cid); printf("no stream_endpoint found for 0x%02x", l2cap_media_cid);
return; return;
@ -279,9 +284,9 @@ void avdtp_source_stream_send_media_payload(uint16_t l2cap_media_cid, btstack_ri
} }
uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid){ uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid){
return avdtp_remote_seps_num(avdtp_cid, &avdtp_source_context); return avdtp_remote_seps_num(avdtp_cid, avdtp_source_context);
} }
avdtp_sep_t * avdtp_source_remote_sep(uint16_t avdtp_cid, uint8_t index){ avdtp_sep_t * avdtp_source_remote_sep(uint16_t avdtp_cid, uint8_t index){
return avdtp_remote_sep(avdtp_cid, index, &avdtp_source_context); return avdtp_remote_sep(avdtp_cid, index, avdtp_source_context);
} }

View File

@ -64,7 +64,7 @@ void avdtp_source_register_media_codec_category(uint8_t seid, avdtp_media_type_t
void avdtp_source_register_multiplexing_category(uint8_t seid, uint8_t fragmentation); void avdtp_source_register_multiplexing_category(uint8_t seid, uint8_t fragmentation);
void avdtp_source_init(void); void avdtp_source_init(avdtp_context_t * avdtp_context);
void avdtp_source_register_packet_handler(btstack_packet_handler_t callback); void avdtp_source_register_packet_handler(btstack_packet_handler_t callback);
/** /**
@ -73,7 +73,6 @@ void avdtp_source_register_packet_handler(btstack_packet_handler_t callback);
*/ */
void avdtp_source_connect(bd_addr_t bd_addr); void avdtp_source_connect(bd_addr_t bd_addr);
void avdtp_source_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size));
/** /**
* @brief Disconnect from device with connection handle. * @brief Disconnect from device with connection handle.
* @param avdtp_cid * @param avdtp_cid

View File

@ -569,13 +569,11 @@ int btstack_main(int argc, const char * argv[]){
l2cap_init(); l2cap_init();
// Initialize AVDTP Sink // Initialize AVDTP Sink
avdtp_source_init(); a2dp_source_init();
avdtp_source_register_packet_handler(&packet_handler); a2dp_source_register_packet_handler(&packet_handler);
//#ifndef SMG_BI //#ifndef SMG_BI
local_stream_endpoint = avdtp_source_create_stream_endpoint(AVDTP_SOURCE, AVDTP_AUDIO); local_stream_endpoint = a2dp_source_create_stream_endpoint(AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities));
avdtp_source_register_media_transport_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
avdtp_source_register_media_codec_category(avdtp_stream_endpoint_seid(local_stream_endpoint), AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities));
// Initialize SDP // Initialize SDP
sdp_init(); sdp_init();