diff --git a/test/avdtp/avdtp.h b/test/avdtp/avdtp.h index 136fd0ce7..ff3c6e38a 100644 --- a/test/avdtp/avdtp.h +++ b/test/avdtp/avdtp.h @@ -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; diff --git a/test/avdtp/avdtp_acceptor.c b/test/avdtp/avdtp_acceptor.c index 81b7c7bfa..d4f339f9e 100644 --- a/test/avdtp/avdtp_acceptor.c +++ b/test/avdtp/avdtp_acceptor.c @@ -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; diff --git a/test/avdtp/avdtp_sink.c b/test/avdtp/avdtp_sink.c index 90ff200d3..bc312326e 100644 --- a/test/avdtp/avdtp_sink.c +++ b/test/avdtp/avdtp_sink.c @@ -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); } diff --git a/test/avdtp/avdtp_sink.h b/test/avdtp/avdtp_sink.h index 2626706e5..ba76cc7b8 100644 --- a/test/avdtp/avdtp_sink.h +++ b/test/avdtp/avdtp_sink.h @@ -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 */ diff --git a/test/avdtp/avdtp_test.c b/test/avdtp/avdtp_test.c index a35251b6f..abba055e6 100644 --- a/test/avdtp/avdtp_test.c +++ b/test/avdtp/avdtp_test.c @@ -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[]){ diff --git a/test/avdtp/avdtp_util.c b/test/avdtp/avdtp_util.c index 82f1bae6e..e6c07e1d8 100644 --- a/test/avdtp/avdtp_util.c +++ b/test/avdtp/avdtp_util.c @@ -42,6 +42,7 @@ #include #include +#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; -} \ No newline at end of file +} + +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; +} + diff --git a/test/avdtp/avdtp_util.h b/test/avdtp/avdtp_util.h index c26afbdd2..c0bb96486 100644 --- a/test/avdtp/avdtp_util.h +++ b/test/avdtp/avdtp_util.h @@ -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 }