diff --git a/test/avdtp/avdtp.h b/test/avdtp/avdtp.h index 2b7e25046..e6e86dcd4 100644 --- a/test/avdtp/avdtp.h +++ b/test/avdtp/avdtp.h @@ -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; diff --git a/test/avdtp/avdtp_acceptor.c b/test/avdtp/avdtp_acceptor.c index 45066b88b..cfb58f39b 100644 --- a/test/avdtp/avdtp_acceptor.c +++ b/test/avdtp/avdtp_acceptor.c @@ -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 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; iremote_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"); diff --git a/test/avdtp/avdtp_initiator.c b/test/avdtp/avdtp_initiator.c index f8123a341..631149e23 100644 --- a/test/avdtp/avdtp_initiator.c +++ b/test/avdtp/avdtp_initiator.c @@ -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; diff --git a/test/avdtp/avdtp_sink.c b/test/avdtp/avdtp_sink.c index f6ce38692..4d881ee10 100644 --- a/test/avdtp/avdtp_sink.c +++ b/test/avdtp/avdtp_sink.c @@ -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); diff --git a/test/avdtp/avdtp_sink.h b/test/avdtp/avdtp_sink.h index a101aa8fe..3605bd280 100644 --- a/test/avdtp/avdtp_sink.h +++ b/test/avdtp/avdtp_sink.h @@ -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; diff --git a/test/avdtp/avdtp_test.c b/test/avdtp/avdtp_test.c index 4a0789f5f..e3a04e229 100644 --- a/test/avdtp/avdtp_test.c +++ b/test/avdtp/avdtp_test.c @@ -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");