mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-23 09:41:03 +00:00
add configuration to sep type
This commit is contained in:
parent
3338b9aef0
commit
e145da5176
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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){
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user