mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-14 01:27:41 +00:00
send set configuration
This commit is contained in:
parent
a85cbb87fc
commit
000b53bc60
@ -295,8 +295,6 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
AVDTP_INITIATOR_STREAM_CONFIG_IDLE,
|
||||
AVDTP_INITIATOR_W2_SET_CONFIGURATION,
|
||||
AVDTP_INITIATOR_W4_CONFIGURATION_SET,
|
||||
AVDTP_INITIATOR_W2_GET_CONFIGURATION,
|
||||
AVDTP_INITIATOR_W4_CONFIGURATION_RECEIVED,
|
||||
AVDTP_INITIATOR_STREAM_CONFIGURED
|
||||
@ -358,7 +356,9 @@ typedef enum {
|
||||
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_CAPABILITIES,
|
||||
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES,
|
||||
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ALL_CAPABILITIES,
|
||||
|
||||
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SET_CAPABILITIES,
|
||||
AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SET_CAPABILITIES,
|
||||
|
||||
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_REJECT_WITH_ERROR_CODE,
|
||||
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE,
|
||||
AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GENERAL_REJECT_WITH_ERROR_CODE
|
||||
@ -371,6 +371,8 @@ typedef struct {
|
||||
avdtp_signal_identifier_t signal_identifier;
|
||||
avdtp_message_type_t message_type;
|
||||
avdtp_packet_type_t packet_type;
|
||||
uint8_t acp_seid;
|
||||
uint8_t int_seid;
|
||||
uint16_t transaction_label;
|
||||
uint16_t num_packets;
|
||||
} avdtp_signaling_packet_t;
|
||||
@ -395,6 +397,10 @@ typedef struct {
|
||||
uint8_t initiator_transaction_label;
|
||||
uint8_t acceptor_transaction_label;
|
||||
uint8_t query_seid;
|
||||
uint8_t int_seid;
|
||||
|
||||
avdtp_capabilities_t remote_capabilities;
|
||||
uint16_t remote_capabilities_bitmap;
|
||||
|
||||
uint8_t wait_to_send_acceptor;
|
||||
uint8_t wait_to_send_initiator;
|
||||
|
@ -47,33 +47,6 @@
|
||||
#include "avdtp_util.h"
|
||||
#include "avdtp_acceptor.h"
|
||||
|
||||
static inline void avdtp_acceptor_prepare_capabilities_response(avdtp_signaling_packet_t * signaling_packet, uint8_t transaction_label, avdtp_sep_t sep, uint8_t identifier){
|
||||
if (signaling_packet->offset) return;
|
||||
uint8_t pack_all_capabilities = 1;
|
||||
if (identifier == AVDTP_SI_GET_CAPABILITIES){
|
||||
pack_all_capabilities = 0;
|
||||
}
|
||||
|
||||
signaling_packet->size = 0;
|
||||
int i = 0;
|
||||
for (i = 1; i < 9; i++){
|
||||
if (get_bit16(sep.registered_service_categories, i)){
|
||||
// service category
|
||||
signaling_packet->command[signaling_packet->size++] = i;
|
||||
signaling_packet->size += avdtp_pack_service_capabilities(signaling_packet->command+signaling_packet->size, sizeof(signaling_packet->command)-signaling_packet->size, sep.capabilities, (avdtp_service_category_t)i, pack_all_capabilities);
|
||||
}
|
||||
}
|
||||
signaling_packet->command[signaling_packet->size++] = 0x04;
|
||||
signaling_packet->command[signaling_packet->size++] = 0x02;
|
||||
signaling_packet->command[signaling_packet->size++] = 0x02;
|
||||
signaling_packet->command[signaling_packet->size++] = 0x00;
|
||||
|
||||
// printf(" avdtp_acceptor_send_capabilities_response: \n");
|
||||
// printf_hexdump(signaling_packet->command, signaling_packet->size);
|
||||
signaling_packet->signal_identifier = identifier;
|
||||
signaling_packet->transaction_label = transaction_label;
|
||||
signaling_packet->message_type = AVDTP_RESPONSE_ACCEPT_MSG;
|
||||
}
|
||||
|
||||
static int avdtp_acceptor_send_accept_response(uint16_t cid, uint8_t transaction_label, avdtp_signal_identifier_t identifier){
|
||||
uint8_t command[2];
|
||||
@ -142,7 +115,7 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_st
|
||||
// find first registered category and fire the error
|
||||
connection->reject_service_category = 0;
|
||||
for (i = 1; i < 9; i++){
|
||||
if (get_bit16(sep.registered_service_categories, i-1)){
|
||||
if (get_bit16(sep.registered_service_categories, i)){
|
||||
connection->reject_service_category = i;
|
||||
break;
|
||||
}
|
||||
@ -335,61 +308,7 @@ int avdtp_acceptor_send_response_reject_with_error_code(uint16_t cid, avdtp_sign
|
||||
}
|
||||
|
||||
|
||||
static int avdtp_acceptor_signaling_response_create_fragment(uint16_t cid, avdtp_signaling_packet_t * signaling_packet, uint8_t * out_buffer) {
|
||||
int mtu = l2cap_get_remote_mtu_for_local_cid(cid);
|
||||
// hack for test
|
||||
// int mtu = 6;
|
||||
int data_len = 0;
|
||||
|
||||
uint16_t offset = signaling_packet->offset;
|
||||
uint16_t pos = 1;
|
||||
// printf(" avdtp_acceptor_signaling_response_create_fragment offset %d, packet type %d\n", signaling_packet->offset, signaling_packet->packet_type);
|
||||
|
||||
if (offset == 0){
|
||||
if (signaling_packet->size <= mtu - 2){
|
||||
// printf(" AVDTP_SINGLE_PACKET\n");
|
||||
signaling_packet->packet_type = AVDTP_SINGLE_PACKET;
|
||||
out_buffer[pos++] = signaling_packet->signal_identifier;
|
||||
data_len = signaling_packet->size;
|
||||
} else {
|
||||
signaling_packet->packet_type = AVDTP_START_PACKET;
|
||||
out_buffer[pos++] = (mtu + signaling_packet->size)/ (mtu-1);
|
||||
out_buffer[pos++] = signaling_packet->signal_identifier;
|
||||
data_len = mtu - 3;
|
||||
signaling_packet->offset = data_len;
|
||||
// printf(" AVDTP_START_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset);
|
||||
}
|
||||
} else {
|
||||
int remaining_bytes = signaling_packet->size - offset;
|
||||
if (remaining_bytes <= mtu - 1){
|
||||
//signaling_packet->fragmentation = 1;
|
||||
signaling_packet->packet_type = AVDTP_END_PACKET;
|
||||
data_len = remaining_bytes;
|
||||
signaling_packet->offset = 0;
|
||||
// printf(" AVDTP_END_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset);
|
||||
} else{
|
||||
signaling_packet->packet_type = AVDTP_CONTINUE_PACKET;
|
||||
data_len = mtu - 1;
|
||||
signaling_packet->offset += data_len;
|
||||
// printf(" AVDTP_CONTINUE_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset);
|
||||
}
|
||||
}
|
||||
out_buffer[0] = avdtp_header(signaling_packet->transaction_label, signaling_packet->packet_type, signaling_packet->message_type);
|
||||
memcpy(out_buffer+pos, signaling_packet->command + offset, data_len);
|
||||
pos += data_len;
|
||||
return pos;
|
||||
}
|
||||
|
||||
static inline int avdtp_acceptor_send_fragmented_packet(uint16_t cid, avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, avdtp_acceptor_stream_endpoint_state_t acceptor_config_state){
|
||||
l2cap_reserve_packet_buffer();
|
||||
uint8_t * out_buffer = l2cap_get_outgoing_buffer();
|
||||
uint16_t pos = avdtp_acceptor_signaling_response_create_fragment(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->acceptor_config_state = acceptor_config_state;
|
||||
printf(" ACP: fragmented\n");
|
||||
}
|
||||
return l2cap_send_prepared(cid, pos);
|
||||
}
|
||||
|
||||
int avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint){
|
||||
if (!stream_endpoint) return 0;
|
||||
@ -402,17 +321,34 @@ int avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avdt
|
||||
avdtp_acceptor_stream_endpoint_state_t acceptor_config_state = stream_endpoint->acceptor_config_state;
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
|
||||
int sent = 1;
|
||||
uint8_t * out_buffer;
|
||||
uint16_t pos;
|
||||
|
||||
|
||||
switch (acceptor_config_state){
|
||||
case AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE:
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES:
|
||||
avdtp_acceptor_prepare_capabilities_response(&connection->signaling_packet, trid, stream_endpoint->sep, AVDTP_SI_GET_CAPABILITIES);
|
||||
avdtp_acceptor_send_fragmented_packet(cid, connection, stream_endpoint, acceptor_config_state);
|
||||
avdtp_prepare_capabilities(&connection->signaling_packet, trid, stream_endpoint->sep.registered_service_categories, stream_endpoint->sep.capabilities, AVDTP_SI_GET_CAPABILITIES);
|
||||
l2cap_reserve_packet_buffer();
|
||||
out_buffer = l2cap_get_outgoing_buffer();
|
||||
pos = avdtp_signaling_create_fragment(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->acceptor_config_state = acceptor_config_state;
|
||||
printf(" ACP: fragmented\n");
|
||||
}
|
||||
l2cap_send_prepared(cid, pos);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_GET_ALL_CAPABILITIES:
|
||||
avdtp_acceptor_prepare_capabilities_response(&connection->signaling_packet, trid, stream_endpoint->sep, AVDTP_SI_GET_ALL_CAPABILITIES);
|
||||
avdtp_acceptor_send_fragmented_packet(cid, connection, stream_endpoint, acceptor_config_state);
|
||||
avdtp_prepare_capabilities(&connection->signaling_packet, trid, stream_endpoint->sep.registered_service_categories, stream_endpoint->sep.capabilities, AVDTP_SI_GET_ALL_CAPABILITIES);
|
||||
l2cap_reserve_packet_buffer();
|
||||
out_buffer = l2cap_get_outgoing_buffer();
|
||||
pos = avdtp_signaling_create_fragment(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->acceptor_config_state = acceptor_config_state;
|
||||
printf(" ACP: fragmented\n");
|
||||
}
|
||||
l2cap_send_prepared(cid, pos);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION:
|
||||
printf(" ACP: DONE\n");
|
||||
@ -427,8 +363,15 @@ int avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avdt
|
||||
break;
|
||||
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION:
|
||||
avdtp_acceptor_prepare_capabilities_response(&connection->signaling_packet, trid, stream_endpoint->sep, AVDTP_SI_GET_CONFIGURATION);
|
||||
avdtp_acceptor_send_fragmented_packet(cid, connection, stream_endpoint, acceptor_config_state);
|
||||
avdtp_prepare_capabilities(&connection->signaling_packet, trid, stream_endpoint->sep.registered_service_categories, stream_endpoint->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);
|
||||
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
|
||||
stream_endpoint->acceptor_config_state = acceptor_config_state;
|
||||
printf(" ACP: fragmented\n");
|
||||
}
|
||||
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;
|
||||
|
@ -541,15 +541,35 @@ static void avdtp_sink_handle_can_send_now(avdtp_connection_t * connection, uint
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS:
|
||||
printf(" -> AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SEPS_DISCOVERED\n");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SEPS_DISCOVERED;
|
||||
connection->initiator_transaction_label++;
|
||||
avdtp_initiator_send_signaling_cmd(connection->l2cap_signaling_cid, AVDTP_SI_DISCOVER, connection->initiator_transaction_label);
|
||||
return;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES:
|
||||
printf(" -> AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES\n");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_CAPABILITIES;
|
||||
connection->initiator_transaction_label++;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CAPABILITIES, connection->initiator_transaction_label, connection->query_seid);
|
||||
return;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES:
|
||||
printf(" -> AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES\n");
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ALL_CAPABILITIES;
|
||||
avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_ALL_CAPABILITIES, connection->initiator_transaction_label, connection->query_seid);
|
||||
return;
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SET_CAPABILITIES:{
|
||||
printf(" -> AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SET_CAPABILITIES bitmap %02x\n", connection->remote_capabilities_bitmap);
|
||||
printf_hexdump( connection->remote_capabilities.media_codec.media_codec_information, connection->remote_capabilities.media_codec.media_codec_information_len);
|
||||
connection->signaling_packet.acp_seid = connection->query_seid;
|
||||
connection->signaling_packet.int_seid = connection->int_seid;
|
||||
|
||||
avdtp_prepare_capabilities(&connection->signaling_packet, connection->initiator_transaction_label, connection->remote_capabilities_bitmap, connection->remote_capabilities, AVDTP_SI_SET_CONFIGURATION);
|
||||
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);
|
||||
if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_SET_CAPABILITIES;
|
||||
printf(" ACP: fragmented\n");
|
||||
}
|
||||
l2cap_send_prepared(connection->l2cap_signaling_cid, pos);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -746,9 +766,10 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
|
||||
avdtp_signaling_emit_done(avdtp_sink_callback, connection->con_handle, 0);
|
||||
connection->initiator_transaction_label++;
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE;
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
case AVDTP_SI_GET_CAPABILITIES:{
|
||||
case AVDTP_SI_GET_CAPABILITIES:
|
||||
case AVDTP_SI_GET_ALL_CAPABILITIES:{
|
||||
avdtp_sep_t sep;
|
||||
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, packet+2, size-2);
|
||||
if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){
|
||||
@ -764,11 +785,14 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
|
||||
avdtp_signaling_emit_done(avdtp_sink_callback, connection->con_handle, 0);
|
||||
//avdtp_signaling_emit_done(avdtp_sink_callback, connection->con_handle, 0);
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE;
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
case AVDTP_SI_SET_CONFIGURATION:
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE;
|
||||
return 0;
|
||||
default:
|
||||
printf("AVDTP_RESPONSE_ACCEPT_MSG signal %d not implemented\n", connection->signaling_packet.signal_identifier);
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case AVDTP_RESPONSE_REJECT_MSG:
|
||||
@ -1060,6 +1084,7 @@ void avdtp_sink_discover_stream_endpoints(uint16_t con_handle){
|
||||
|
||||
switch (connection->initiator_connection_state){
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE:
|
||||
connection->initiator_transaction_label++;
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS;
|
||||
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
|
||||
break;
|
||||
@ -1078,6 +1103,7 @@ void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t seid){
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
|
||||
connection->initiator_transaction_label++;
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES;
|
||||
connection->query_seid = seid;
|
||||
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
|
||||
@ -1092,21 +1118,26 @@ void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t seid){
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
|
||||
connection->initiator_transaction_label++;
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES;
|
||||
connection->query_seid = seid;
|
||||
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
|
||||
void avdtp_sink_set_capabilities(uint16_t con_handle, uint8_t seid){
|
||||
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
|
||||
void avdtp_sink_set_capabilities(uint16_t con_handle, uint8_t acp_seid, uint8_t int_seid, uint16_t remote_capabilities_bitmap, avdtp_capabilities_t remote_capabilities){
|
||||
avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle);
|
||||
if (!connection){
|
||||
printf("avdtp_sink_discover_stream_endpoints: no connection for handle 0x%02x found\n", con_handle);
|
||||
return;
|
||||
}
|
||||
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
|
||||
avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid);
|
||||
if (!stream_endpoint || stream_endpoint->initiator_config_state != AVDTP_STREAM_ENDPOINT_IDLE) return;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SET_CONFIGURATION;
|
||||
avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
|
||||
connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_SET_CAPABILITIES;
|
||||
connection->initiator_transaction_label++;
|
||||
connection->query_seid = acp_seid;
|
||||
connection->int_seid = int_seid;
|
||||
connection->remote_capabilities = remote_capabilities;
|
||||
connection->remote_capabilities_bitmap = remote_capabilities_bitmap;
|
||||
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
@ -124,7 +124,8 @@ void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t seid);
|
||||
* @brief Set capabilities
|
||||
* @param con_handle
|
||||
*/
|
||||
void avdtp_sink_set_capabilities(uint16_t con_handle, uint8_t seid);
|
||||
void avdtp_sink_set_capabilities(uint16_t con_handle, uint8_t acp_seid, uint8_t int_seid, uint16_t remote_capabilities_bitmap, avdtp_capabilities_t remote_capabilities);
|
||||
|
||||
|
||||
/* API_END */
|
||||
|
||||
|
@ -159,7 +159,9 @@ static uint16_t con_handle = 0;
|
||||
static uint8_t sdp_avdtp_sink_service_buffer[150];
|
||||
static avdtp_sep_t sep;
|
||||
static adtvp_media_codec_information_sbc_t sbc;
|
||||
|
||||
static uint16_t remote_capabilities_bitmap;
|
||||
static avdtp_capabilities_t remote_capabilities;
|
||||
|
||||
typedef enum {
|
||||
AVDTP_APPLICATION_IDLE,
|
||||
AVDTP_APPLICATION_W2_DISCOVER_SEPS,
|
||||
@ -312,12 +314,12 @@ static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endp
|
||||
|
||||
static void dump_media_codec_sbc(adtvp_media_codec_information_sbc_t media_codec_sbc){
|
||||
printf("Received media codec capability:\n");
|
||||
printf(" - sampling_frequency: %02x\n", media_codec_sbc.sampling_frequency_bitmap);
|
||||
printf(" - channel_mode: %02x\n", media_codec_sbc.channel_mode_bitmap);
|
||||
printf(" - block_length: %02x\n", media_codec_sbc.block_length_bitmap);
|
||||
printf(" - subbands: %02x\n", media_codec_sbc.subbands_bitmap);
|
||||
printf(" - allocation_method: %x\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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -410,6 +412,11 @@ static void show_usage(void){
|
||||
printf("---\n");
|
||||
}
|
||||
|
||||
static const uint8_t media_sbc_codec_info[] = {
|
||||
(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
|
||||
(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
|
||||
2, 53
|
||||
};
|
||||
|
||||
static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
|
||||
if (app_state != AVDTP_APPLICATION_IDLE) {
|
||||
@ -442,7 +449,13 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
break;
|
||||
case 's':
|
||||
app_state = AVDTP_APPLICATION_W2_SET_CAPABILITIES;
|
||||
avdtp_sink_set_capabilities(con_handle, sep.seid);
|
||||
remote_capabilities_bitmap = store_bit16(remote_capabilities_bitmap, AVDTP_MEDIA_CODEC, 1);
|
||||
remote_capabilities.media_codec.media_type = AVDTP_AUDIO;
|
||||
remote_capabilities.media_codec.media_codec_type = AVDTP_CODEC_SBC;
|
||||
|
||||
remote_capabilities.media_codec.media_codec_information_len = sizeof(media_sbc_codec_info);
|
||||
remote_capabilities.media_codec.media_codec_information = media_sbc_codec_info;
|
||||
avdtp_sink_set_capabilities(con_handle, sep.seid, 1, remote_capabilities_bitmap, remote_capabilities);
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
@ -454,13 +467,6 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SMG_BI
|
||||
static const uint8_t media_sbc_codec_info[] = {
|
||||
0xFF, // (AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
|
||||
0xFF, // (AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
|
||||
2, 53
|
||||
};
|
||||
#endif
|
||||
|
||||
int btstack_main(int argc, const char * argv[]);
|
||||
int btstack_main(int argc, const char * argv[]){
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "btstack.h"
|
||||
#include "avdtp.h"
|
||||
#include "avdtp_util.h"
|
||||
|
||||
@ -274,4 +275,88 @@ uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdt
|
||||
}
|
||||
}
|
||||
return registered_service_categories;
|
||||
}
|
||||
}
|
||||
|
||||
void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uint8_t transaction_label, uint16_t registered_service_categories, avdtp_capabilities_t capabilities, uint8_t identifier){
|
||||
if (signaling_packet->offset) return;
|
||||
uint8_t pack_all_capabilities = 1;
|
||||
signaling_packet->size = 0;
|
||||
int i;
|
||||
switch (identifier) {
|
||||
case AVDTP_SI_GET_CAPABILITIES:
|
||||
pack_all_capabilities = 0;
|
||||
break;
|
||||
case AVDTP_SI_SET_CONFIGURATION:
|
||||
signaling_packet->command[signaling_packet->size++] = signaling_packet->acp_seid << 2;
|
||||
signaling_packet->command[signaling_packet->size++] = signaling_packet->int_seid << 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 1; i < 9; i++){
|
||||
if (get_bit16(registered_service_categories, i)){
|
||||
// service category
|
||||
signaling_packet->command[signaling_packet->size++] = i;
|
||||
signaling_packet->size += avdtp_pack_service_capabilities(signaling_packet->command+signaling_packet->size, sizeof(signaling_packet->command)-signaling_packet->size, capabilities, (avdtp_service_category_t)i, pack_all_capabilities);
|
||||
}
|
||||
}
|
||||
// signaling_packet->command[signaling_packet->size++] = 0x04;
|
||||
// signaling_packet->command[signaling_packet->size++] = 0x02;
|
||||
// signaling_packet->command[signaling_packet->size++] = 0x02;
|
||||
// signaling_packet->command[signaling_packet->size++] = 0x00;
|
||||
|
||||
signaling_packet->signal_identifier = identifier;
|
||||
signaling_packet->transaction_label = transaction_label;
|
||||
if (identifier == AVDTP_SI_SET_CONFIGURATION){
|
||||
signaling_packet->message_type = AVDTP_CMD_MSG;
|
||||
} else {
|
||||
signaling_packet->message_type = AVDTP_RESPONSE_ACCEPT_MSG;
|
||||
}
|
||||
}
|
||||
|
||||
int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * signaling_packet, uint8_t * out_buffer) {
|
||||
int mtu = l2cap_get_remote_mtu_for_local_cid(cid);
|
||||
// hack for test
|
||||
// int mtu = 6;
|
||||
int data_len = 0;
|
||||
|
||||
uint16_t offset = signaling_packet->offset;
|
||||
uint16_t pos = 1;
|
||||
// printf(" avdtp_signaling_create_fragment offset %d, packet type %d\n", signaling_packet->offset, signaling_packet->packet_type);
|
||||
|
||||
if (offset == 0){
|
||||
if (signaling_packet->size <= mtu - 2){
|
||||
// printf(" AVDTP_SINGLE_PACKET\n");
|
||||
signaling_packet->packet_type = AVDTP_SINGLE_PACKET;
|
||||
out_buffer[pos++] = signaling_packet->signal_identifier;
|
||||
data_len = signaling_packet->size;
|
||||
} else {
|
||||
signaling_packet->packet_type = AVDTP_START_PACKET;
|
||||
out_buffer[pos++] = (mtu + signaling_packet->size)/ (mtu-1);
|
||||
out_buffer[pos++] = signaling_packet->signal_identifier;
|
||||
data_len = mtu - 3;
|
||||
signaling_packet->offset = data_len;
|
||||
// printf(" AVDTP_START_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset);
|
||||
}
|
||||
} else {
|
||||
int remaining_bytes = signaling_packet->size - offset;
|
||||
if (remaining_bytes <= mtu - 1){
|
||||
//signaling_packet->fragmentation = 1;
|
||||
signaling_packet->packet_type = AVDTP_END_PACKET;
|
||||
data_len = remaining_bytes;
|
||||
signaling_packet->offset = 0;
|
||||
// printf(" AVDTP_END_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset);
|
||||
} else{
|
||||
signaling_packet->packet_type = AVDTP_CONTINUE_PACKET;
|
||||
data_len = mtu - 1;
|
||||
signaling_packet->offset += data_len;
|
||||
// printf(" AVDTP_CONTINUE_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset);
|
||||
}
|
||||
}
|
||||
out_buffer[0] = avdtp_header(signaling_packet->transaction_label, signaling_packet->packet_type, signaling_packet->message_type);
|
||||
memcpy(out_buffer+pos, signaling_packet->command + offset, data_len);
|
||||
pos += data_len;
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,8 @@ int get_bit16(uint16_t bitmap, int position);
|
||||
int avdtp_pack_service_capabilities(uint8_t * buffer, int size, avdtp_capabilities_t caps, avdtp_service_category_t category, uint8_t pack_all_capabilities);
|
||||
uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdtp_capabilities_t * caps, uint8_t * packet, uint16_t size);
|
||||
|
||||
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);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user