mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-29 04:20:20 +00:00
avdtp: get all capabilities, acceptor role
This commit is contained in:
parent
960a7f70ae
commit
ec2c446c4d
@ -111,14 +111,14 @@ typedef enum {
|
||||
AVDTP_SI_GET_CAPABILITIES,
|
||||
AVDTP_SI_SET_CONFIGURATION,
|
||||
AVDTP_SI_GET_CONFIGURATION,
|
||||
AVDTP_SI_RECONFIGURE,
|
||||
AVDTP_SI_RECONFIGURE, //5
|
||||
AVDTP_SI_OPEN,
|
||||
AVDTP_SI_START,
|
||||
AVDTP_SI_CLOSE,
|
||||
AVDTP_SI_SUSPEND,
|
||||
AVDTP_SI_ABORT,
|
||||
AVDTP_SI_ABORT, //10
|
||||
AVDTP_SI_SECURITY_CONTROL,
|
||||
AVDTP_SI_GET_ALL_CAPABILITIES,
|
||||
AVDTP_SI_GET_ALL_CAPABILITIES, //12
|
||||
AVDTP_SI_DELAYREPORT
|
||||
} avdtp_signal_identifier_t;
|
||||
|
||||
|
@ -47,14 +47,16 @@
|
||||
#include "avdtp_util.h"
|
||||
#include "avdtp_acceptor.h"
|
||||
|
||||
static int avdtp_pack_service_capabilities(uint8_t * buffer, int size, avdtp_capabilities_t caps, avdtp_service_category_t category){
|
||||
static int avdtp_pack_service_capabilities(uint8_t * buffer, int size, avdtp_capabilities_t caps, avdtp_service_category_t category, uint8_t pack_all_capabilities){
|
||||
int i;
|
||||
// pos = 0 reserved for length
|
||||
int pos = 1;
|
||||
switch(category){
|
||||
case AVDTP_MEDIA_TRANSPORT:
|
||||
case AVDTP_REPORTING:
|
||||
break;
|
||||
case AVDTP_DELAY_REPORTING:
|
||||
if (!pack_all_capabilities) break;
|
||||
break;
|
||||
case AVDTP_RECOVERY:
|
||||
buffer[pos++] = caps.recovery.recovery_type; // 0x01=RFC2733
|
||||
@ -64,9 +66,13 @@ static int avdtp_pack_service_capabilities(uint8_t * buffer, int size, avdtp_cap
|
||||
case AVDTP_CONTENT_PROTECTION:
|
||||
buffer[pos++] = caps.content_protection.cp_type_lsb;
|
||||
buffer[pos++] = caps.content_protection.cp_type_msb;
|
||||
// if (caps.content_protection.cp_type_value_len == 0){
|
||||
// buffer[pos++] = 0;
|
||||
// }
|
||||
for (i = 0; i<caps.content_protection.cp_type_value_len; i++){
|
||||
buffer[pos++] = caps.content_protection.cp_type_value[i];
|
||||
}
|
||||
printf("AVDTP_CONTENT_PROTECTION %d, %d \n", caps.content_protection.cp_type_lsb, caps.content_protection.cp_type_msb);
|
||||
break;
|
||||
case AVDTP_HEADER_COMPRESSION:
|
||||
buffer[pos++] = (caps.header_compression.back_ch << 7) | (caps.header_compression.media << 6) | (caps.header_compression.recovery << 5);
|
||||
@ -157,22 +163,42 @@ static int avdtp_acceptor_send_seps_response(uint16_t cid, uint8_t transaction_l
|
||||
return l2cap_send(cid, command, pos);
|
||||
}
|
||||
|
||||
static int avdtp_acceptor_send_capabilities_response(uint16_t cid, uint8_t transaction_label, avdtp_sep_t sep){
|
||||
static inline int avdtp_acceptor_send_capabilities(uint16_t cid, uint8_t transaction_label, avdtp_sep_t sep, uint8_t pack_all_capabilities){
|
||||
uint8_t command[100];
|
||||
uint8_t identifier = (uint8_t)AVDTP_SI_GET_CAPABILITIES;
|
||||
if (pack_all_capabilities){
|
||||
identifier = (uint8_t)AVDTP_SI_GET_ALL_CAPABILITIES;
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
command[pos++] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_RESPONSE_ACCEPT_MSG);
|
||||
command[pos++] = (uint8_t)AVDTP_SI_GET_CAPABILITIES;
|
||||
command[pos++] = identifier;
|
||||
int i = 0;
|
||||
for (i = 1; i < 9; i++){
|
||||
if (get_bit16(sep.registered_service_categories, i)){
|
||||
// service category
|
||||
command[pos++] = i;
|
||||
pos += avdtp_pack_service_capabilities(command+pos, sizeof(command)-pos, sep.capabilities, (avdtp_service_category_t)i);
|
||||
pos += avdtp_pack_service_capabilities(command+pos, sizeof(command)-pos, sep.capabilities, (avdtp_service_category_t)i, pack_all_capabilities);
|
||||
}
|
||||
}
|
||||
command[pos++] = 0x04;
|
||||
command[pos++] = 0x02;
|
||||
command[pos++] = 0x02;
|
||||
command[pos++] = 0x00;
|
||||
|
||||
printf(" avdtp_acceptor_send_capabilities_response: \n");
|
||||
printf_hexdump(command, pos);
|
||||
return l2cap_send(cid, command, pos);
|
||||
}
|
||||
|
||||
static int avdtp_acceptor_send_capabilities_response(uint16_t cid, uint8_t transaction_label, avdtp_sep_t sep){
|
||||
return avdtp_acceptor_send_capabilities(cid, transaction_label, sep, 0);
|
||||
}
|
||||
|
||||
static int avdtp_acceptor_send_all_capabilities_response(uint16_t cid, uint8_t transaction_label, avdtp_sep_t sep){
|
||||
return avdtp_acceptor_send_capabilities(cid, transaction_label, sep, 1);
|
||||
}
|
||||
|
||||
// static int avdtp_acceptor_send_configuration_reject_response(uint16_t cid, uint8_t transaction_label){
|
||||
// uint8_t command[3];
|
||||
// command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_RESPONSE_REJECT_MSG);
|
||||
@ -217,14 +243,18 @@ int avdtp_acceptor_stream_config_subsm(avdtp_sink_connection_t * connection, uin
|
||||
printf(" ACP -> AVDTP_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS\n");
|
||||
connection->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS;
|
||||
break;
|
||||
case AVDTP_SI_GET_ALL_CAPABILITIES:
|
||||
printf(" ACP -> AVDTP_SI_GET_ALL_CAPABILITIES\n");
|
||||
connection->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_ALL_CAPABILITIES;
|
||||
break;
|
||||
case AVDTP_SI_GET_CAPABILITIES:
|
||||
printf(" ACP -> AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES\n");
|
||||
connection->local_seid = packet[2] >> 2;
|
||||
connection->query_seid = packet[2] >> 2;
|
||||
connection->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES;
|
||||
break;
|
||||
case AVDTP_SI_SET_CONFIGURATION:
|
||||
printf(" ACP -> AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION\n");
|
||||
connection->local_seid = packet[2] >> 2;
|
||||
connection->query_seid = packet[2] >> 2;
|
||||
sep.seid = packet[3] >> 2;
|
||||
// find or add sep
|
||||
for (i=0; i<connection->remote_seps_num; i++){
|
||||
@ -236,9 +266,12 @@ int avdtp_acceptor_stream_config_subsm(avdtp_sink_connection_t * connection, uin
|
||||
connection->remote_seps[connection->remote_sep_index] = sep;
|
||||
connection->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf(" ACP -> NOT IMPLEMENTED\n");
|
||||
request_to_send = 0;
|
||||
printf(" ACP -> NOT IMPLEMENTED, Reject signal_identifier %02x\n", signaling_header.signal_identifier);
|
||||
connection->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_UNKNOWN_CMD;
|
||||
connection->unknown_signal_identifier = signaling_header.signal_identifier;
|
||||
request_to_send = 1;
|
||||
break;
|
||||
}
|
||||
l2cap_request_can_send_now_event(connection->l2cap_signaling_cid);
|
||||
@ -254,6 +287,13 @@ int avdtp_acceptor_stream_config_subsm(avdtp_sink_connection_t * connection, uin
|
||||
return request_to_send;
|
||||
}
|
||||
|
||||
static int avdtp_acceptor_send_response_reject(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t transaction_label){
|
||||
uint8_t command[2];
|
||||
command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_GENERAL_REJECT_MSG);
|
||||
command[1] = (uint8_t)identifier;
|
||||
return l2cap_send(cid, command, sizeof(command));
|
||||
}
|
||||
|
||||
int avdtp_acceptor_stream_config_subsm_run_for_connection(avdtp_sink_connection_t *connection, avdtp_sep_t * local_seps, uint8_t local_seps_num){
|
||||
int sent = 1;
|
||||
switch (connection->acceptor_config_state){
|
||||
@ -265,7 +305,16 @@ int avdtp_acceptor_stream_config_subsm_run_for_connection(avdtp_sink_connection_
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES:
|
||||
printf(" AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES -> AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE\n");
|
||||
connection->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
|
||||
avdtp_acceptor_send_capabilities_response(connection->l2cap_signaling_cid, connection->acceptor_transaction_label, local_seps[connection->local_seid]);
|
||||
avdtp_acceptor_send_capabilities_response(connection->l2cap_signaling_cid, connection->acceptor_transaction_label, local_seps[connection->query_seid]);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_GET_ALL_CAPABILITIES:
|
||||
printf(" AVDTP_ACCEPTOR_W2_ANSWER_GET_ALL_CAPABILITIES -> AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE\n");
|
||||
connection->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
|
||||
avdtp_acceptor_send_all_capabilities_response(connection->l2cap_signaling_cid, connection->acceptor_transaction_label, local_seps[connection->query_seid]);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_REJECT_UNKNOWN_CMD:
|
||||
connection->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
|
||||
avdtp_acceptor_send_response_reject(connection->l2cap_signaling_cid, connection->unknown_signal_identifier, connection->acceptor_transaction_label);
|
||||
break;
|
||||
case AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION:
|
||||
printf(" AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION -> AVDTP_ACCEPTOR_STREAM_CONFIG_DONE\n");
|
||||
|
@ -54,9 +54,20 @@ static int avdtp_initiator_send_signaling_cmd(uint16_t cid, avdtp_signal_identif
|
||||
return l2cap_send(cid, command, sizeof(command));
|
||||
}
|
||||
|
||||
static int avdtp_initiator_send_get_capabilities_cmd(uint16_t cid, uint8_t sep_id){
|
||||
printf("TODO: avdtp_initiator_send_get_capabilities_cmd not implemented\n");
|
||||
return 0;
|
||||
static int avdtp_initiator_send_get_all_capabilities_cmd(uint16_t cid, uint8_t transaction_label, uint8_t sep_id){
|
||||
uint8_t command[3];
|
||||
command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_CMD_MSG);
|
||||
command[1] = AVDTP_SI_GET_ALL_CAPABILITIES;
|
||||
command[2] = sep_id << 2;
|
||||
return l2cap_send(cid, command, sizeof(command));
|
||||
}
|
||||
|
||||
static int avdtp_initiator_send_get_capabilities_cmd(uint16_t cid, uint8_t transaction_label, uint8_t sep_id){
|
||||
uint8_t command[3];
|
||||
command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_CMD_MSG);
|
||||
command[1] = AVDTP_SI_GET_CAPABILITIES;
|
||||
command[2] = sep_id << 2;
|
||||
return l2cap_send(cid, command, sizeof(command));
|
||||
}
|
||||
|
||||
void avdtp_initiator_stream_config_subsm_init(avdtp_sink_connection_t * connection){
|
||||
@ -68,6 +79,7 @@ int avdtp_initiator_stream_config_subsm_is_done(avdtp_sink_connection_t * connec
|
||||
}
|
||||
|
||||
int avdtp_initiator_stream_config_subsm(avdtp_sink_connection_t * connection, uint8_t *packet, uint16_t size){
|
||||
return 0;
|
||||
if (avdtp_initiator_stream_config_subsm_run_for_connection(connection)) return 1;
|
||||
int i;
|
||||
int responded = 1;
|
||||
@ -115,8 +127,13 @@ int avdtp_initiator_stream_config_subsm(avdtp_sink_connection_t * connection, ui
|
||||
responded = 1;
|
||||
break;
|
||||
case AVDTP_INITIATOR_W4_CAPABILITIES:
|
||||
printf(" AVDTP_INITIATOR_W4_CAPABILITIES -> NOT IMPLEMENTED\n");
|
||||
|
||||
printf(" Received basic capabilities -> NOT IMPLEMENTED\n");
|
||||
responded = 0;
|
||||
break;
|
||||
case AVDTP_INITIATOR_W4_ALL_CAPABILITIES:
|
||||
printf(" Received all capabilities -> NOT IMPLEMENTED\n");
|
||||
responded = 0;
|
||||
break;
|
||||
default:
|
||||
printf(" INT : NOT IMPLEMENTED sig. ID %02x\n", signaling_header.signal_identifier);
|
||||
//printf_hexdump( packet, size );
|
||||
@ -127,6 +144,7 @@ int avdtp_initiator_stream_config_subsm(avdtp_sink_connection_t * connection, ui
|
||||
}
|
||||
|
||||
int avdtp_initiator_stream_config_subsm_run_for_connection(avdtp_sink_connection_t *connection){
|
||||
return 0;
|
||||
int sent = 1;
|
||||
switch (connection->initiator_config_state){
|
||||
case AVDTP_INITIATOR_STREAM_CONFIG_IDLE:
|
||||
@ -136,9 +154,14 @@ int avdtp_initiator_stream_config_subsm_run_for_connection(avdtp_sink_connection
|
||||
avdtp_initiator_send_signaling_cmd(connection->l2cap_signaling_cid, AVDTP_SI_DISCOVER, connection->initiator_transaction_label);
|
||||
break;
|
||||
case AVDTP_INITIATOR_W2_GET_CAPABILITIES:
|
||||
printf(" AVDTP_INitiator_W2_GET_CAPABILITIES -> AVDTP_INitiator_W4_CAPABILITIES\n");
|
||||
printf(" AVDTP_INITIATOR_W2_GET_CAPABILITIES -> AVDTP_INITIATOR_W4_CAPABILITIES\n");
|
||||
connection->initiator_config_state = AVDTP_INITIATOR_W4_CAPABILITIES;
|
||||
avdtp_initiator_send_get_capabilities_cmd(connection->l2cap_signaling_cid, 0);
|
||||
avdtp_initiator_send_get_capabilities_cmd(connection->l2cap_signaling_cid, connection->initiator_transaction_label, connection->query_seid);
|
||||
break;
|
||||
case AVDTP_INITIATOR_W2_GET_ALL_CAPABILITIES:
|
||||
printf(" AVDTP_INITIATOR_W2_GET_ALL_CAPABILITIES -> AVDTP_INITIATOR_W4_ALL_CAPABILITIES\n");
|
||||
connection->initiator_config_state = AVDTP_INITIATOR_W4_ALL_CAPABILITIES;
|
||||
avdtp_initiator_send_get_all_capabilities_cmd(connection->l2cap_signaling_cid, connection->initiator_transaction_label, connection->query_seid);
|
||||
break;
|
||||
default:
|
||||
sent = 0;
|
||||
|
@ -331,7 +331,7 @@ static void handle_l2cap_signaling_data_packet(avdtp_sink_connection_t * connect
|
||||
switch (signaling_header.signal_identifier){
|
||||
case AVDTP_SI_OPEN:
|
||||
printf("AVDTP_CONFIGURED -> AVDTP_W2_ANSWER_OPEN_STREAM %d\n", signaling_header.transaction_label);
|
||||
connection->local_seid = packet[2] >> 2;
|
||||
connection->active_seid = packet[2] >> 2;
|
||||
connection->avdtp_state = AVDTP_W2_ANSWER_OPEN_STREAM;
|
||||
connection->acceptor_transaction_label = signaling_header.transaction_label;
|
||||
l2cap_request_can_send_now_event(connection->l2cap_signaling_cid);
|
||||
@ -345,7 +345,7 @@ static void handle_l2cap_signaling_data_packet(avdtp_sink_connection_t * connect
|
||||
switch (signaling_header.signal_identifier){
|
||||
case AVDTP_SI_START:
|
||||
printf("AVDTP_OPEN -> AVDTP_W2_ANSWER_START_SINGLE_STREAM\n");
|
||||
connection->local_seid = packet[2] >> 2;
|
||||
connection->active_seid = packet[2] >> 2;
|
||||
connection->avdtp_state = AVDTP_W2_ANSWER_START_SINGLE_STREAM;
|
||||
connection->acceptor_transaction_label = signaling_header.transaction_label;
|
||||
l2cap_request_can_send_now_event(connection->l2cap_signaling_cid);
|
||||
|
@ -82,6 +82,8 @@ typedef enum {
|
||||
AVDTP_INITIATOR_W4_SEPS_DISCOVERED,
|
||||
AVDTP_INITIATOR_W2_GET_CAPABILITIES,
|
||||
AVDTP_INITIATOR_W4_CAPABILITIES,
|
||||
AVDTP_INITIATOR_W2_GET_ALL_CAPABILITIES,
|
||||
AVDTP_INITIATOR_W4_ALL_CAPABILITIES,
|
||||
AVDTP_INITIATOR_W2_SET_CONFIGURATION,
|
||||
AVDTP_INITIATOR_W4_CONFIGURATION_SET,
|
||||
AVDTP_INITIATOR_W2_GET_CONFIGURATION,
|
||||
@ -93,7 +95,9 @@ typedef enum {
|
||||
AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE,
|
||||
AVDTP_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS,
|
||||
AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES,
|
||||
AVDTP_ACCEPTOR_W2_ANSWER_GET_ALL_CAPABILITIES,
|
||||
AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION,
|
||||
AVDTP_ACCEPTOR_W2_REJECT_UNKNOWN_CMD,
|
||||
AVDTP_ACCEPTOR_STREAM_CONFIG_DONE
|
||||
} avdtp_acceptor_stream_config_state_t;
|
||||
|
||||
@ -115,13 +119,16 @@ typedef struct avdtp_sink_connection {
|
||||
|
||||
uint8_t initiator_transaction_label;
|
||||
uint8_t acceptor_transaction_label;
|
||||
avdtp_signal_identifier_t unknown_signal_identifier;
|
||||
|
||||
// store remote seps
|
||||
avdtp_sep_t remote_seps[MAX_NUM_SEPS];
|
||||
uint8_t remote_seps_num;
|
||||
|
||||
// currently active local_seid
|
||||
uint8_t local_seid;
|
||||
// currently active seid - stream opened
|
||||
uint8_t active_seid;
|
||||
uint8_t query_seid;
|
||||
|
||||
// currently active remote seid
|
||||
uint8_t remote_sep_index;
|
||||
|
||||
|
@ -302,9 +302,9 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
}
|
||||
|
||||
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, 250
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
@ -323,13 +323,16 @@ int btstack_main(int argc, const char * argv[]){
|
||||
uint8_t seid = avdtp_sink_register_stream_end_point(AVDTP_SINK, AVDTP_AUDIO);
|
||||
avdtp_sink_register_media_transport_category(seid);
|
||||
avdtp_sink_register_media_codec_category(seid, AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_info, sizeof(media_sbc_codec_info));
|
||||
|
||||
// uint8_t cp_type_lsb, uint8_t cp_type_msb, const uint8_t * cp_type_value, uint8_t cp_type_value_len
|
||||
// avdtp_sink_register_content_protection_category(seid, 2, 2, NULL, 0);
|
||||
|
||||
avdtp_sink_register_media_handler(&handle_l2cap_media_data_packet);
|
||||
|
||||
// Initialize SDP
|
||||
sdp_init();
|
||||
memset(sdp_avdtp_sink_service_buffer, 0, sizeof(sdp_avdtp_sink_service_buffer));
|
||||
a2dp_sink_create_sdp_record(sdp_avdtp_sink_service_buffer, 0x10001, 0, NULL, NULL);
|
||||
a2dp_sink_create_sdp_record(sdp_avdtp_sink_service_buffer, 0x10001, 1, NULL, NULL);
|
||||
sdp_register_service(sdp_avdtp_sink_service_buffer);
|
||||
|
||||
gap_set_local_name("BTstack AVDTP Test");
|
||||
|
Loading…
x
Reference in New Issue
Block a user