add configuration to sep type

This commit is contained in:
Milanka Ringwald 2017-01-11 15:38:03 +01:00
parent 3338b9aef0
commit e145da5176
7 changed files with 249 additions and 129 deletions

View File

@ -164,6 +164,7 @@ typedef enum{
} avdtp_sep_type_t;
typedef enum {
AVDTP_SERVICE_CATEGORY_INVALID_0 = 0x00,
AVDTP_MEDIA_TRANSPORT = 0X01,
AVDTP_REPORTING,
AVDTP_RECOVERY,
@ -171,7 +172,8 @@ typedef enum {
AVDTP_HEADER_COMPRESSION, //5
AVDTP_MULTIPLEXING, //6
AVDTP_MEDIA_CODEC, //7
AVDTP_DELAY_REPORTING //8
AVDTP_DELAY_REPORTING, //8
AVDTP_SERVICE_CATEGORY_INVALID_FF = 0xFF
} avdtp_service_category_t;
typedef struct {
@ -334,6 +336,9 @@ typedef struct {
uint16_t registered_service_categories;
avdtp_capabilities_t capabilities;
uint16_t configured_service_categories;
avdtp_capabilities_t configuration;
} avdtp_sep_t;
@ -398,6 +403,8 @@ typedef struct {
uint16_t num_packets;
} avdtp_signaling_packet_t;
btstack_packet_handler_t avdtp_sink_callback;
typedef struct {
btstack_linked_item_t item;
@ -439,6 +446,7 @@ typedef struct {
typedef struct avdtp_stream_endpoint {
btstack_linked_item_t item;
// original capabilities
avdtp_sep_t sep;
uint16_t l2cap_media_cid;
uint16_t l2cap_reporting_cid;
@ -450,7 +458,7 @@ typedef struct avdtp_stream_endpoint {
// active connection
avdtp_connection_t * connection;
// store remote seps
// store configurations with remote seps
avdtp_sep_t remote_seps[MAX_NUM_SEPS];
uint8_t remote_seps_num;

View File

@ -61,15 +61,14 @@ static int avdtp_acceptor_process_chunk(avdtp_signaling_packet_t * signaling_pac
return signaling_packet->packet_type == AVDTP_SINGLE_PACKET || signaling_packet->packet_type == AVDTP_END_PACKET;
}
int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t * packet, uint16_t size){
int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t * packet, uint16_t size, int offset){
if (!stream_endpoint) return 0;
if (!avdtp_acceptor_process_chunk(&connection->signaling_packet, packet, size)) return 0;
uint16_t packet_size = connection->signaling_packet.size;
connection->signaling_packet.size = 0;
int request_to_send = 1;
switch (stream_endpoint->acceptor_config_state){
case AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE:
@ -89,8 +88,8 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_st
stream_endpoint->remote_sep_index = 0xFF;
avdtp_sep_t sep;
sep.seid = connection->signaling_packet.command[3] >> 2;
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, connection->signaling_packet.command+4, packet_size-4);
sep.seid = connection->signaling_packet.command[offset++] >> 2;
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, connection->signaling_packet.command+offset, packet_size-offset);
sep.in_use = 1;
if (connection->error_code){
@ -122,6 +121,9 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_st
}
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
} else {
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
printf(" ACP: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
}
} else {
// add new
@ -132,6 +134,19 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_st
printf(" ACP: add seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
}
break;
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(avdtp_sink_callback, connection->con_handle, sep.capabilities.media_codec);
break;
default:
avdtp_signaling_emit_media_codec_other(avdtp_sink_callback, connection->con_handle, sep.capabilities.media_codec);
break;
}
}
avdtp_signaling_emit_done(avdtp_sink_callback, connection->con_handle, 0);
break;
}
case AVDTP_SI_RECONFIGURE:{
// if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_OPENED){
@ -146,9 +161,11 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_st
connection->reject_service_category = 0;
stream_endpoint->remote_sep_index = 0xFF;
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE %p in state %d (AVDTP_STREAM_ENDPOINT_OPENED %d)\n", stream_endpoint, stream_endpoint->state, AVDTP_STREAM_ENDPOINT_OPENED);
avdtp_sep_t sep;
sep.seid = packet[2] >> 2;
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE seid %d\n", sep.seid);
// printf_hexdump(connection->signaling_packet.command, packet_size);
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, connection->signaling_packet.command+3, packet_size-3);
if (connection->error_code){
@ -362,8 +379,9 @@ int avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avdt
avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_RECONFIGURE);
break;
case AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION:
avdtp_prepare_capabilities(&connection->signaling_packet, trid, stream_endpoint->sep.registered_service_categories, stream_endpoint->sep.capabilities, AVDTP_SI_GET_CONFIGURATION);
case AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION:{
avdtp_sep_t sep = stream_endpoint->remote_seps[stream_endpoint->remote_sep_index];
avdtp_prepare_capabilities(&connection->signaling_packet, trid, sep.registered_service_categories, sep.capabilities, AVDTP_SI_GET_CONFIGURATION);
l2cap_reserve_packet_buffer();
out_buffer = l2cap_get_outgoing_buffer();
pos = avdtp_signaling_create_fragment(cid, &connection->signaling_packet, out_buffer);
@ -373,6 +391,7 @@ int avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avdt
}
l2cap_send_prepared(cid, pos);
break;
}
case AVDTP_ACCEPTOR_W4_L2CAP_FOR_MEDIA_CONNECTED:
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W4_L2CAP_FOR_MEDIA_CONNECTED;
return 0;

View File

@ -51,7 +51,7 @@
extern "C" {
#endif
int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size, int offset);
int avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint);
int avdtp_acceptor_send_response_reject_with_error_code(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t error_code, uint8_t transaction_label);

View File

@ -58,7 +58,6 @@ static uint16_t stream_endpoints_id_counter;
static btstack_linked_list_t stream_endpoints;
static btstack_packet_handler_t avdtp_sink_callback;
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
@ -142,88 +141,6 @@ 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 void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, bd_addr_t addr, uint8_t status){
if (!callback) return;
uint8_t event[12];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED;
little_endian_store_16(event, pos, con_handle);
pos += 2;
reverse_bd_addr(addr,&event[pos]);
pos += 6;
event[pos++] = status;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){
if (!callback) return;
uint8_t event[9];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_SEP_FOUND;
little_endian_store_16(event, pos, con_handle);
pos += 2;
event[pos++] = sep.seid;
event[pos++] = sep.in_use;
event[pos++] = sep.media_type;
event[pos++] = sep.type;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void avdtp_signaling_emit_done(btstack_packet_handler_t callback, uint16_t con_handle, uint8_t status){
if (!callback) return;
uint8_t event[6];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_DONE;
little_endian_store_16(event, pos, con_handle);
pos += 2;
event[pos++] = status;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
uint8_t event[13];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC;
little_endian_store_16(event, pos, con_handle);
pos += 2;
event[pos++] = media_codec.media_type;
event[pos++] = media_codec.media_codec_information[0] >> 4;
event[pos++] = media_codec.media_codec_information[0] & 0x0F;
event[pos++] = media_codec.media_codec_information[1] >> 4;
event[pos++] = (media_codec.media_codec_information[1] & 0x0F) >> 2;
event[pos++] = media_codec.media_codec_information[1] & 0x03;
event[pos++] = media_codec.media_codec_information[2];
event[pos++] = media_codec.media_codec_information[3];
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
uint8_t event[109];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER;
little_endian_store_16(event, pos, con_handle);
pos += 2;
event[pos++] = media_codec.media_type;
little_endian_store_16(event, pos, media_codec.media_codec_type);
pos += 2;
little_endian_store_16(event, pos, media_codec.media_codec_information_len);
pos += 2;
memcpy(event+pos, media_codec.media_codec_information, media_codec.media_codec_information_len);
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_for_seid(uint16_t seid){
btstack_linked_list_iterator_t it;
@ -650,11 +567,11 @@ static void avdtp_sink_handle_can_send_now(avdtp_connection_t * connection, uint
/* END: tracking can send now requests pro l2cap cid */
static int handle_l2cap_data_packet_for_stream_endpoint(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size){
static int handle_l2cap_data_packet_for_stream_endpoint(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size, int offset){
avdtp_read_signaling_header(&connection->signaling_packet, packet, size);
if (connection->signaling_packet.message_type == AVDTP_CMD_MSG){
if (avdtp_acceptor_stream_config_subsm(connection, stream_endpoint, packet, size)){
if (avdtp_acceptor_stream_config_subsm(connection, stream_endpoint, packet, size, offset)){
avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid);
return 1;
}
@ -669,7 +586,7 @@ static int handle_l2cap_data_packet_for_stream_endpoint(avdtp_connection_t * con
static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t * connection, uint8_t *packet, uint16_t size){
avdtp_stream_endpoint_t * stream_endpoint = NULL;
int pos = avdtp_read_signaling_header(&connection->signaling_packet, packet, size);
int offset = avdtp_read_signaling_header(&connection->signaling_packet, packet, size);
switch (connection->signaling_packet.message_type){
case AVDTP_CMD_MSG:
@ -701,7 +618,7 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
return 1;
}
connection->query_seid = packet[pos++] >> 2;
connection->query_seid = packet[offset++] >> 2;
stream_endpoint = get_avdtp_stream_endpoint_for_active_seid(connection->query_seid);
if (!stream_endpoint){
printf(" ACP: cmd %d - RESPONSE REJECT BAD_ACP_SEID\n", connection->signaling_packet.signal_identifier);
@ -711,7 +628,8 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
return 1;
}
return handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size);
return handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size, offset);
case AVDTP_SI_RECONFIGURE:
if (size < 3) {
connection->error_code = BAD_LENGTH;
@ -720,7 +638,7 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
return 1;
}
connection->query_seid = packet[pos++] >> 2;
connection->query_seid = packet[offset++] >> 2;
stream_endpoint = get_avdtp_stream_endpoint_for_active_seid(connection->query_seid);
if (!stream_endpoint){
printf(" ACP: AVDTP_SI_RECONFIGURE - CATEGORY RESPONSE REJECT BAD_ACP_SEID\n");
@ -731,7 +649,7 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
return 1;
}
return handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size);
return handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size, offset);
case AVDTP_SI_OPEN:
if (size < 3) {
@ -741,7 +659,7 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
return 1;
}
connection->query_seid = packet[pos++] >> 2;
connection->query_seid = packet[offset++] >> 2;
stream_endpoint = get_avdtp_stream_endpoint_for_active_seid(connection->query_seid);
if (!stream_endpoint){
printf(" ACP: AVDTP_SI_OPEN - RESPONSE REJECT BAD_STATE\n");
@ -751,7 +669,7 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
return 1;
}
return handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size);
return handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size, offset);
case AVDTP_SI_SUSPEND:{
int i;
@ -759,8 +677,9 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
printf(" ACP: AVDTP_SI_SUSPEND seids: ");
connection->num_suspended_seids = 0;
for (i=pos; i<size; i++){
for (i = offset; i < size; i++){
connection->suspended_seids[connection->num_suspended_seids] = packet[i] >> 2;
offset++;
printf("%d, \n", connection->suspended_seids[connection->num_suspended_seids]);
connection->num_suspended_seids++;
}
@ -788,7 +707,7 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
connection->num_suspended_seids = 0;
return 1;
}
request_to_send = handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size);
request_to_send = handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size, offset);
}
return request_to_send;
}
@ -811,14 +730,15 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
}
if (size == 3){
printf(" ERROR code %02x\n", packet[pos]);
printf(" ERROR code %02x\n", packet[offset]);
return 0;
}
avdtp_sep_t sep;
int i;
for (i = pos; i < size; i += 2){
for (i = offset; i < size; i += 2){
sep.seid = packet[i] >> 2;
offset++;
if (sep.seid < 0x01 || sep.seid > 0x3E){
printf(" invalid sep id\n");
return 0;
@ -838,9 +758,9 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
case AVDTP_SI_GET_ALL_CAPABILITIES:
case AVDTP_SI_GET_CONFIGURATION:{
avdtp_sep_t sep;
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, packet+pos, size-pos);
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, packet+offset, size-offset);
printf_hexdump(packet, size);
if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){
switch (sep.capabilities.media_codec.media_codec_type){
case AVDTP_CODEC_SBC:
@ -866,16 +786,44 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
avdtp_signaling_emit_done(avdtp_sink_callback, connection->con_handle, 0);
return 0;
case AVDTP_SI_SET_CONFIGURATION:
case AVDTP_SI_SET_CONFIGURATION:{
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE;
stream_endpoint = get_avdtp_stream_endpoint_for_seid(connection->query_seid);
stream_endpoint = get_avdtp_stream_endpoint_for_seid(connection->int_seid);
if (!stream_endpoint) {
avdtp_signaling_emit_done(avdtp_sink_callback, connection->con_handle, 0);
avdtp_signaling_emit_done(avdtp_sink_callback, connection->con_handle, 1);
return 0;
}
avdtp_sep_t sep;
sep.seid = connection->signaling_packet.command[3] >> 2;
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, connection->signaling_packet.command+4, connection->signaling_packet.size-4);
sep.in_use = 1;
// find or add sep
int i;
stream_endpoint->remote_sep_index = 0xFF;
for (i=0; i < stream_endpoint->remote_seps_num; i++){
if (stream_endpoint->remote_seps[i].seid == sep.seid){
stream_endpoint->remote_sep_index = i;
break;
}
}
if (stream_endpoint->remote_sep_index != 0xFF){
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
printf(" INT: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
} else {
// add new
printf(" INT: seid %d not found in %p\n", sep.seid, stream_endpoint);
stream_endpoint->remote_sep_index = stream_endpoint->remote_seps_num;
stream_endpoint->remote_seps_num++;
stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep;
printf(" INT: add seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
}
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED;
avdtp_signaling_emit_done(avdtp_sink_callback, connection->con_handle, 0);
return 0;
}
case AVDTP_SI_START:
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE;
stream_endpoint = get_avdtp_stream_endpoint_for_seid(connection->query_seid);
@ -949,7 +897,7 @@ static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp
uint16_t local_cid;
switch (packet_type){
case L2CAP_DATA_PACKET:
handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size);
handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size, 0);
break;
case HCI_EVENT_PACKET:
switch (event){

View File

@ -78,6 +78,7 @@
#define BYTES_PER_FRAME (2*NUM_CHANNELS)
#define PREBUFFER_MS 150
#define PREBUFFER_BYTES (PREBUFFER_MS*SAMPLE_RATE/1000*BYTES_PER_FRAME)
static uint8_t ring_buffer_storage[2*PREBUFFER_BYTES];
static btstack_ring_buffer_t ring_buffer;
@ -182,11 +183,61 @@ avdtp_application_state_t app_state = AVDTP_APPLICATION_IDLE;
static btstack_packet_callback_registration_t hci_event_callback_registration;
static int media_initialized = 0;
static int init_media_processing(void){
if (media_initialized) return 0;
static int init_media_processing(adtvp_media_codec_information_sbc_t media_codec_sbc){
int num_channels = NUM_CHANNELS;
int sample_rate = SAMPLE_RATE;
int frames_per_buffer = FRAMES_PER_BUFFER;
int subbands = 8;
int block_length = 16;
if (media_codec_sbc.channel_mode_bitmap & AVDTP_SBC_MONO){
num_channels = 1;
}
if ( (media_codec_sbc.channel_mode_bitmap & AVDTP_SBC_JOINT_STEREO) ||
(media_codec_sbc.channel_mode_bitmap & AVDTP_SBC_STEREO) ||
(media_codec_sbc.channel_mode_bitmap & AVDTP_SBC_DUAL_CHANNEL) ){
num_channels = 2;
}
if (media_codec_sbc.sampling_frequency_bitmap & AVDTP_SBC_16000){
sample_rate = 16000;
}
if (media_codec_sbc.sampling_frequency_bitmap & AVDTP_SBC_32000){
sample_rate = 32000;
}
if (media_codec_sbc.sampling_frequency_bitmap & AVDTP_SBC_44100){
sample_rate = 44100;
}
if (media_codec_sbc.sampling_frequency_bitmap & AVDTP_SBC_48000){
sample_rate = 48000;
}
if (media_codec_sbc.subbands_bitmap & AVDTP_SBC_SUBBANDS_4){
subbands = 4;
}
if (media_codec_sbc.subbands_bitmap & AVDTP_SBC_SUBBANDS_8){
subbands = 8;
}
if (media_codec_sbc.block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_4){
block_length = 4;
}
if (media_codec_sbc.block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_8){
block_length = 8;
}
if (media_codec_sbc.block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_12){
block_length = 12;
}
if (media_codec_sbc.block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_16){
block_length = 16;
}
frames_per_buffer = subbands * block_length;
#ifdef STORE_SBC_TO_WAV_FILE
btstack_sbc_decoder_init(&state, mode, handle_pcm_data, NULL);
wav_writer_open(wav_filename, NUM_CHANNELS, SAMPLE_RATE);
wav_writer_open(wav_filename, num_channels, sample_rate);
#endif
#ifdef STORE_SBC_TO_SBC_FILE
@ -205,7 +256,7 @@ static int init_media_processing(void){
}
/* -- setup input and output -- */
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
outputParameters.channelCount = NUM_CHANNELS;
outputParameters.channelCount = num_channels;
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
@ -214,8 +265,8 @@ static int init_media_processing(void){
&stream,
NULL, /* &inputParameters */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
sample_rate,
frames_per_buffer,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback, /* use callback */
NULL );
@ -309,7 +360,7 @@ static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endp
// printf("SBC HEADER: num_frames %u, fragmented %u, start %u, stop %u\n", sbc_header.num_frames, sbc_header.fragmentation, sbc_header.starting_packet, sbc_header.last_packet);
// printf_hexdump( packet+pos, size-pos );
init_media_processing();
#ifdef STORE_SBC_TO_WAV_FILE
btstack_sbc_decoder_process_data(&state, 0, packet+pos, size-pos);
#endif
@ -382,6 +433,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
sbc.min_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_get_min_bitpool_value(packet);
sbc.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_get_max_bitpool_value(packet);
dump_media_codec_sbc(sbc);
init_media_processing(sbc);
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER:
printf(" received non SBC codec. not implemented\n");
@ -415,12 +467,12 @@ static void show_usage(void){
printf("a - get all capabilities\n");
printf("s - set configuration\n");
printf("f - get configuration\n");
printf("R - reconfigure stream with seid 1\n");
printf("o - open stream with seid 1\n");
printf("m - start stream with seid 1\n");
printf("A - abort stream with seid 1\n");
printf("S - stop stream with seid 1\n");
printf("P - suspend stream with seid 1\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);
printf("Ctrl-c - exit\n");
printf("---\n");
}

View File

@ -138,6 +138,8 @@ int avdtp_pack_service_capabilities(uint8_t * buffer, int size, avdtp_capabiliti
buffer[pos++] = caps.media_codec.media_codec_information[i];
}
break;
default:
break;
}
buffer[0] = pos - 1; // length
return pos;
@ -145,8 +147,8 @@ int avdtp_pack_service_capabilities(uint8_t * buffer, int size, avdtp_capabiliti
static int avdtp_unpack_service_capabilities_has_errors(avdtp_connection_t * connection, avdtp_service_category_t category, uint8_t cap_len){
connection->error_code = 0;
if (category < AVDTP_MEDIA_TRANSPORT){
if (category == AVDTP_SERVICE_CATEGORY_INVALID_0 || category == AVDTP_SERVICE_CATEGORY_INVALID_FF){
printf(" ERROR: BAD SERVICE CATEGORY %d\n", category);
connection->reject_service_category = category;
connection->error_code = BAD_SERV_CATEGORY;
@ -209,6 +211,8 @@ static int avdtp_unpack_service_capabilities_has_errors(avdtp_connection_t * con
}
uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdtp_capabilities_t * caps, uint8_t * packet, uint16_t size){
if (size == 0) return 0;
uint16_t registered_service_categories = 0;
int pos = 0;
int i;
@ -379,3 +383,86 @@ int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * sig
return pos;
}
void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, bd_addr_t addr, uint8_t status){
if (!callback) return;
uint8_t event[12];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED;
little_endian_store_16(event, pos, con_handle);
pos += 2;
reverse_bd_addr(addr,&event[pos]);
pos += 6;
event[pos++] = status;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){
if (!callback) return;
uint8_t event[9];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_SEP_FOUND;
little_endian_store_16(event, pos, con_handle);
pos += 2;
event[pos++] = sep.seid;
event[pos++] = sep.in_use;
event[pos++] = sep.media_type;
event[pos++] = sep.type;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_done(btstack_packet_handler_t callback, uint16_t con_handle, uint8_t status){
if (!callback) return;
uint8_t event[6];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_DONE;
little_endian_store_16(event, pos, con_handle);
pos += 2;
event[pos++] = status;
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
uint8_t event[13];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC;
little_endian_store_16(event, pos, con_handle);
pos += 2;
event[pos++] = media_codec.media_type;
event[pos++] = media_codec.media_codec_information[0] >> 4;
event[pos++] = media_codec.media_codec_information[0] & 0x0F;
event[pos++] = media_codec.media_codec_information[1] >> 4;
event[pos++] = (media_codec.media_codec_information[1] & 0x0F) >> 2;
event[pos++] = media_codec.media_codec_information[1] & 0x03;
event[pos++] = media_codec.media_codec_information[2];
event[pos++] = media_codec.media_codec_information[3];
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){
if (!callback) return;
uint8_t event[109];
int pos = 0;
event[pos++] = HCI_EVENT_AVDTP_META;
event[pos++] = sizeof(event) - 2;
event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER;
little_endian_store_16(event, pos, con_handle);
pos += 2;
event[pos++] = media_codec.media_type;
little_endian_store_16(event, pos, media_codec.media_codec_type);
pos += 2;
little_endian_store_16(event, pos, media_codec.media_codec_information_len);
pos += 2;
memcpy(event+pos, media_codec.media_codec_information, media_codec.media_codec_information_len);
(*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}

View File

@ -63,6 +63,12 @@ uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdt
void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uint8_t transaction_label, uint16_t registered_service_categories, avdtp_capabilities_t configuration, uint8_t identifier);
int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * signaling_packet, uint8_t * out_buffer);
void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, bd_addr_t addr, uint8_t status);
void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep);
void avdtp_signaling_emit_done(btstack_packet_handler_t callback, uint16_t con_handle, uint8_t status);
void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec);
void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec);
#if defined __cplusplus
}
#endif