diff --git a/example/a2dp_sink_demo.c b/example/a2dp_sink_demo.c index 0402fc6c6..841cd9f5c 100644 --- a/example/a2dp_sink_demo.c +++ b/example/a2dp_sink_demo.c @@ -129,7 +129,7 @@ static uint8_t sbc_frame_size; static int sbc_samples_fix; #endif -// PortAdudio - live playback +// PortAudio - live playback #ifdef HAVE_PORTAUDIO #define PA_SAMPLE_TYPE paInt16 #define SAMPLE_RATE 48000 diff --git a/port/libusb/btstack_config.h b/port/libusb/btstack_config.h index d9732848f..6822316b1 100644 --- a/port/libusb/btstack_config.h +++ b/port/libusb/btstack_config.h @@ -25,7 +25,7 @@ #define ENABLE_SCO_OVER_HCI #define ENABLE_SDP_DES_DUMP -// #define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE +#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE // BTstack configuration. buffers, sizes, ... #define HCI_ACL_PAYLOAD_SIZE (1691 + 4) diff --git a/src/btstack_defines.h b/src/btstack_defines.h index a8799ff79..74ea24d3a 100644 --- a/src/btstack_defines.h +++ b/src/btstack_defines.h @@ -188,7 +188,8 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_CONNECTION_DOES_NOT_EXIST 0xC1 #define AVDTP_CONNECTION_IN_WRONG_STATE 0xC2 #define AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE 0xC3 -#define AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST 0xC4 +#define AVDTP_STREAM_ENDPOINT_DOES_NOT_EXIST 0xC4 +#define AVDTP_MEDIA_CONNECTION_DOES_NOT_EXIST 0xC5 /* ENUM_END */ // DAEMON COMMANDS diff --git a/src/classic/avdtp.c b/src/classic/avdtp.c index 38225c360..f8152878c 100644 --- a/src/classic/avdtp.c +++ b/src/classic/avdtp.c @@ -854,7 +854,6 @@ uint8_t avdtp_suspend_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_conte log_error("avdtp_suspend_stream: no connection for signaling cid 0x%02x found", avdtp_cid); return AVDTP_CONNECTION_DOES_NOT_EXIST; } - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(local_seid, context); if (!stream_endpoint) { log_error("avdtp_suspend_stream: no stream_endpoint with seid %d found", local_seid); @@ -873,92 +872,96 @@ uint8_t avdtp_suspend_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_conte return ERROR_CODE_SUCCESS; } -void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context){ - log_info("call avdtp_discover_stream_endpoints"); - +uint8_t avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context){ avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context); if (!connection){ log_error("avdtp_discover_stream_endpoints: no connection for signaling cid 0x%02x found", avdtp_cid); - return; + return AVDTP_CONNECTION_DOES_NOT_EXIST; } - - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; - - 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_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); - break; - default: - log_error("avdtp_discover_stream_endpoints: wrong state"); - break; + if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED || + connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) { + return AVDTP_CONNECTION_IN_WRONG_STATE; } + + connection->initiator_transaction_label++; + connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS; + return avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); } -void avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context){ +uint8_t avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context){ avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context); if (!connection){ - log_error("avdtp_get_capabilities: no connection for AVDTP cid 0x%02x found", avdtp_cid); - return; + log_error("avdtp: no connection for AVDTP cid 0x%02x found", avdtp_cid); + return AVDTP_CONNECTION_DOES_NOT_EXIST; } - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; - if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; + if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED || + connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) { + return AVDTP_CONNECTION_IN_WRONG_STATE; + } + connection->initiator_transaction_label++; connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES; connection->remote_seid = remote_seid; - avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); + return avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); } -void avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context){ +uint8_t avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context){ avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context); if (!connection){ - log_error("avdtp_get_all_capabilities: no connection for AVDTP cid 0x%02x found", avdtp_cid); - return; + log_error("avdtp: no connection for AVDTP cid 0x%02x found", avdtp_cid); + return AVDTP_CONNECTION_DOES_NOT_EXIST; } - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; - if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; + if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED || + connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) { + return AVDTP_CONNECTION_IN_WRONG_STATE; + } + connection->initiator_transaction_label++; connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES; connection->remote_seid = remote_seid; - avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); + return avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); } -void avdtp_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context){ +uint8_t avdtp_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context){ avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context); if (!connection){ - log_error("avdtp_get_configuration: no connection for AVDTP cid 0x%02x found", avdtp_cid); - return; + log_error("avdtp: no connection for AVDTP cid 0x%02x found", avdtp_cid); + return AVDTP_CONNECTION_DOES_NOT_EXIST; } - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; - if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; + if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED || + connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) { + return AVDTP_CONNECTION_IN_WRONG_STATE; + } + connection->initiator_transaction_label++; connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION; connection->remote_seid = remote_seid; - avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); + return avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); } -void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){ +uint8_t avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){ avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context); if (!connection){ - log_error("avdtp_set_configuration: no connection for AVDTP cid 0x%02x found", avdtp_cid); - return; + log_error("avdtp: no connection for AVDTP cid 0x%02x found", avdtp_cid); + return AVDTP_CONNECTION_DOES_NOT_EXIST; + } + if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED || + connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) { + return AVDTP_CONNECTION_IN_WRONG_STATE; } - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; - if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, context); if (!stream_endpoint) { - log_error("avdtp_set_configuration: no initiator stream endpoint for seid %d", local_seid); - return; - } + log_error("avdtp: no initiator stream endpoint for seid %d", local_seid); + return AVDTP_STREAM_ENDPOINT_DOES_NOT_EXIST; + } + connection->active_stream_endpoint = (void*) stream_endpoint; connection->is_configuration_initiated_locally = 1; connection->is_initiator = 1; - log_info("avdtp_set_configuration locally: role is_initiator %d", connection->is_initiator); - + connection->initiator_transaction_label++; connection->remote_seid = remote_seid; connection->local_seid = local_seid; @@ -972,37 +975,38 @@ void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t rem stream_endpoint->media_type = configuration.media_codec.media_type; memcpy(stream_endpoint->media_codec_sbc_info, configuration.media_codec.media_codec_information, 4); } - avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); + return avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); } -void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){ +uint8_t avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){ avdtp_connection_t * connection = avdtp_connection_for_avdtp_cid(avdtp_cid, context); if (!connection){ - log_error("avdtp_reconfigure: no connection for AVDTP cid 0x%02x found", avdtp_cid); - return; + log_error("avdtp: no connection for AVDTP cid 0x%02x found", avdtp_cid); + return AVDTP_CONNECTION_DOES_NOT_EXIST; } //TODO: if opened only app capabilities, enable reconfigure for not opened - if (connection->state < AVDTP_SIGNALING_CONNECTION_OPENED) return; - if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; + if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED || + connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) { + return AVDTP_CONNECTION_IN_WRONG_STATE; + } avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, context); if (!stream_endpoint) { log_error("avdtp_reconfigure: no initiator stream endpoint for seid %d", local_seid); - return; + return AVDTP_STREAM_ENDPOINT_DOES_NOT_EXIST; } if (stream_endpoint->remote_sep_index == 0xFF){ log_error("avdtp_reconfigure: no associated remote sep"); - return; + return AVDTP_STREAM_ENDPOINT_IN_WRONG_STATE; } - connection->initiator_transaction_label++; connection->remote_seid = remote_seid; connection->local_seid = local_seid; stream_endpoint->remote_configuration_bitmap = configured_services_bitmap; stream_endpoint->remote_configuration = configuration; stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID; - avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); + return avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); } uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context){ diff --git a/src/classic/avdtp.h b/src/classic/avdtp.h index 4f7afe7be..08499c66f 100644 --- a/src/classic/avdtp.h +++ b/src/classic/avdtp.h @@ -545,12 +545,12 @@ uint8_t avdtp_stop_stream (uint16_t avdtp_cid, uint8_t local_seid, avdtp_context uint8_t avdtp_abort_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context); uint8_t avdtp_suspend_stream(uint16_t avdtp_cid, uint8_t local_seid, avdtp_context_t * context); -void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context); -void avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context); -void avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context); -void avdtp_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context); -void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context); -void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context); +uint8_t avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context); +uint8_t avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context); +uint8_t avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context); +uint8_t avdtp_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid, avdtp_context_t * context); +uint8_t avdtp_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context); +uint8_t avdtp_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context); uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context); avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context); diff --git a/src/classic/avdtp_acceptor.c b/src/classic/avdtp_acceptor.c index 51120543d..fcf4a3aff 100644 --- a/src/classic/avdtp_acceptor.c +++ b/src/classic/avdtp_acceptor.c @@ -83,7 +83,6 @@ static int avdtp_acceptor_validate_msg_length(avdtp_signal_identifier_t signal_i void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t * packet, uint16_t size, int offset, avdtp_context_t * context){ avdtp_stream_endpoint_t * stream_endpoint; connection->acceptor_transaction_label = connection->signaling_packet.transaction_label; - if (!avdtp_acceptor_validate_msg_length(connection->signaling_packet.signal_identifier, size)) { connection->error_code = BAD_LENGTH; connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE; diff --git a/src/classic/avdtp_initiator.c b/src/classic/avdtp_initiator.c index a96098ed8..99c3a1769 100644 --- a/src/classic/avdtp_initiator.c +++ b/src/classic/avdtp_initiator.c @@ -284,7 +284,7 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_ } void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, avdtp_context_t * context){ -int sent = 1; + int sent = 1; switch (connection->initiator_connection_state){ case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS: log_info("INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS"); @@ -335,7 +335,7 @@ int sent = 1; } return; } - + if (stream_endpoint->stop_stream){ stream_endpoint->stop_stream = 0; if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_OPENED){ @@ -345,7 +345,7 @@ int sent = 1; return; } } - + if (stream_endpoint->abort_stream){ stream_endpoint->abort_stream = 0; switch (stream_endpoint->state){ @@ -362,7 +362,7 @@ int sent = 1; break; } } - + if (stream_endpoint->suspend_stream){ stream_endpoint->suspend_stream = 0; if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING){ @@ -371,7 +371,7 @@ int sent = 1; return; } } - + if (stream_endpoint->send_stream){ stream_endpoint->send_stream = 0; if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING){ @@ -381,17 +381,15 @@ int sent = 1; } } - switch (stream_endpoint_state){ case AVDTP_INITIATOR_W2_SET_CONFIGURATION: case AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID:{ - log_info("initiator SM prepare SET_CONFIGURATION cmd: role is_initiator %d", connection->is_initiator); - - if (!connection->is_initiator){ + if (stream_endpoint_state == AVDTP_INITIATOR_W2_SET_CONFIGURATION && !connection->is_initiator){ log_info("initiator SM stop sending SET_CONFIGURATION cmd: current role is acceptor"); connection->is_configuration_initiated_locally = 0; break; } + log_info("initiator SM prepare SET_CONFIGURATION cmd"); connection->is_configuration_initiated_locally = 1; log_info("INT: AVDTP_INITIATOR_W2_(RE)CONFIGURATION bitmap, int seid %d, acp seid %d", connection->local_seid, connection->remote_seid); // log_info_hexdump( connection->remote_capabilities.media_codec.media_codec_information, connection->remote_capabilities.media_codec.media_codec_information_len); diff --git a/src/classic/avdtp_sink.c b/src/classic/avdtp_sink.c index 0970eb80e..2c181391f 100644 --- a/src/classic/avdtp_sink.c +++ b/src/classic/avdtp_sink.c @@ -169,27 +169,27 @@ uint8_t avdtp_sink_suspend(uint16_t avdtp_cid, uint8_t local_seid){ return avdtp_suspend_stream(avdtp_cid, local_seid, avdtp_sink_context); } -void avdtp_sink_discover_stream_endpoints(uint16_t avdtp_cid){ - avdtp_discover_stream_endpoints(avdtp_cid, avdtp_sink_context); +uint8_t avdtp_sink_discover_stream_endpoints(uint16_t avdtp_cid){ + return avdtp_discover_stream_endpoints(avdtp_cid, avdtp_sink_context); } -void avdtp_sink_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){ - avdtp_get_capabilities(avdtp_cid, remote_seid, avdtp_sink_context); +uint8_t avdtp_sink_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){ + return avdtp_get_capabilities(avdtp_cid, remote_seid, avdtp_sink_context); } -void avdtp_sink_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){ - avdtp_get_all_capabilities(avdtp_cid, remote_seid, avdtp_sink_context); +uint8_t avdtp_sink_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){ + return avdtp_get_all_capabilities(avdtp_cid, remote_seid, avdtp_sink_context); } -void avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid){ - avdtp_get_configuration(avdtp_cid, remote_seid, avdtp_sink_context); +uint8_t avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid){ + return avdtp_get_configuration(avdtp_cid, remote_seid, avdtp_sink_context); } -void avdtp_sink_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ - avdtp_set_configuration(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_sink_context); +uint8_t avdtp_sink_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ + return avdtp_set_configuration(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_sink_context); } -void avdtp_sink_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ - avdtp_reconfigure(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_sink_context); +uint8_t avdtp_sink_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ + return avdtp_reconfigure(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_sink_context); } diff --git a/src/classic/avdtp_sink.h b/src/classic/avdtp_sink.h index e19a0f3d1..b9834fb52 100644 --- a/src/classic/avdtp_sink.h +++ b/src/classic/avdtp_sink.h @@ -98,38 +98,38 @@ uint8_t avdtp_sink_disconnect(uint16_t avdtp_cid); * @brief Discover stream endpoints * @param avdtp_cid */ -void avdtp_sink_discover_stream_endpoints(uint16_t avdtp_cid); +uint8_t avdtp_sink_discover_stream_endpoints(uint16_t avdtp_cid); /** * @brief Get capabilities * @param avdtp_cid */ -void avdtp_sink_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid); +uint8_t avdtp_sink_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid); /** * @brief Get all capabilities * @param avdtp_cid */ -void avdtp_sink_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid); +uint8_t avdtp_sink_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid); /** * @brief Set configuration * @param avdtp_cid */ -void avdtp_sink_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); +uint8_t avdtp_sink_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); /** * @brief Reconfigure stream * @param avdtp_cid * @param seid */ -void avdtp_sink_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); +uint8_t avdtp_sink_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); /** * @brief Get configuration * @param avdtp_cid */ -void avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid); +uint8_t avdtp_sink_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid); /** diff --git a/src/classic/avdtp_source.c b/src/classic/avdtp_source.c index 409c69eb8..e9511f551 100644 --- a/src/classic/avdtp_source.c +++ b/src/classic/avdtp_source.c @@ -133,28 +133,28 @@ uint8_t avdtp_source_suspend(uint16_t avdtp_cid, uint8_t local_seid){ return avdtp_suspend_stream(avdtp_cid, local_seid, avdtp_source_context); } -void avdtp_source_discover_stream_endpoints(uint16_t avdtp_cid){ - avdtp_discover_stream_endpoints(avdtp_cid, avdtp_source_context); +uint8_t avdtp_source_discover_stream_endpoints(uint16_t avdtp_cid){ + return avdtp_discover_stream_endpoints(avdtp_cid, avdtp_source_context); } -void avdtp_source_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){ - avdtp_get_capabilities(avdtp_cid, remote_seid, avdtp_source_context); +uint8_t avdtp_source_get_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){ + return avdtp_get_capabilities(avdtp_cid, remote_seid, avdtp_source_context); } -void avdtp_source_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){ - avdtp_get_all_capabilities(avdtp_cid, remote_seid, avdtp_source_context); +uint8_t avdtp_source_get_all_capabilities(uint16_t avdtp_cid, uint8_t remote_seid){ + return avdtp_get_all_capabilities(avdtp_cid, remote_seid, avdtp_source_context); } -void avdtp_source_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid){ - avdtp_get_configuration(avdtp_cid, remote_seid, avdtp_source_context); +uint8_t avdtp_source_get_configuration(uint16_t avdtp_cid, uint8_t remote_seid){ + return avdtp_get_configuration(avdtp_cid, remote_seid, avdtp_source_context); } -void avdtp_source_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ - avdtp_set_configuration(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_source_context); +uint8_t avdtp_source_set_configuration(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ + return avdtp_set_configuration(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_source_context); } -void avdtp_source_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ - avdtp_reconfigure(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_source_context); +uint8_t avdtp_source_reconfigure(uint16_t avdtp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ + return avdtp_reconfigure(avdtp_cid, local_seid, remote_seid, configured_services_bitmap, configuration, avdtp_source_context); } static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ diff --git a/src/classic/avdtp_source.h b/src/classic/avdtp_source.h index 44114cba0..6897a5541 100644 --- a/src/classic/avdtp_source.h +++ b/src/classic/avdtp_source.h @@ -84,38 +84,38 @@ uint8_t avdtp_source_disconnect(uint16_t avdtp_cid); * @brief Discover stream endpoints * @param avdtp_cid */ -void avdtp_source_discover_stream_endpoints(uint16_t avdtp_cid); +uint8_t avdtp_source_discover_stream_endpoints(uint16_t avdtp_cid); /** * @brief Get capabilities * @param avdtp_cid */ -void avdtp_source_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid); +uint8_t avdtp_source_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid); /** * @brief Get all capabilities * @param avdtp_cid */ -void avdtp_source_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid); +uint8_t avdtp_source_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid); /** * @brief Set configuration * @param avdtp_cid */ -void avdtp_source_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); +uint8_t avdtp_source_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); /** * @brief Reconfigure stream * @param avdtp_cid * @param seid */ -void avdtp_source_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); +uint8_t avdtp_source_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); /** * @brief Get configuration * @param avdtp_cid */ -void avdtp_source_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid); +uint8_t avdtp_source_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid); /** diff --git a/src/classic/avdtp_util.c b/src/classic/avdtp_util.c index ee125e24c..9fabba6fb 100644 --- a/src/classic/avdtp_util.c +++ b/src/classic/avdtp_util.c @@ -825,20 +825,25 @@ void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handl } -void avdtp_request_can_send_now_acceptor(avdtp_connection_t * connection, uint16_t l2cap_cid){ - if (!connection) return; +uint8_t avdtp_request_can_send_now_acceptor(avdtp_connection_t * connection, uint16_t l2cap_cid){ + if (!connection) return AVDTP_CONNECTION_DOES_NOT_EXIST; connection->wait_to_send_acceptor = 1; l2cap_request_can_send_now_event(l2cap_cid); + return ERROR_CODE_SUCCESS; } -void avdtp_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid){ - if (!connection) return; + +uint8_t avdtp_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid){ + if (!connection) return AVDTP_CONNECTION_DOES_NOT_EXIST; connection->wait_to_send_initiator = 1; l2cap_request_can_send_now_event(l2cap_cid); + return ERROR_CODE_SUCCESS; } -void avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l2cap_cid){ - if (!connection) return; + +uint8_t avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l2cap_cid){ + if (!connection) return AVDTP_CONNECTION_DOES_NOT_EXIST; connection->wait_to_send_self = 1; l2cap_request_can_send_now_event(l2cap_cid); + return ERROR_CODE_SUCCESS; } uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t seid){ diff --git a/src/classic/avdtp_util.h b/src/classic/avdtp_util.h index 22d8d1f80..5d4afab04 100644 --- a/src/classic/avdtp_util.h +++ b/src/classic/avdtp_util.h @@ -97,9 +97,9 @@ void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_media_type_t media_type, const uint8_t * media_codec_information); void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, adtvp_media_codec_capabilities_t media_codec); -void avdtp_request_can_send_now_acceptor(avdtp_connection_t * connection, uint16_t l2cap_cid); -void avdtp_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid); -void avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l2cap_cid); +uint8_t avdtp_request_can_send_now_acceptor(avdtp_connection_t * connection, uint16_t l2cap_cid); +uint8_t avdtp_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid); +uint8_t avdtp_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l2cap_cid); uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t acp_seid); diff --git a/src/classic/avrcp_browsing_controller.c b/src/classic/avrcp_browsing_controller.c index f7edff877..e870610e9 100644 --- a/src/classic/avrcp_browsing_controller.c +++ b/src/classic/avrcp_browsing_controller.c @@ -100,7 +100,6 @@ static void avrcp_emit_browsing_connection_established(btstack_packet_handler_t } static void avrcp_emit_incoming_browsing_connection(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr){ - printf("avrcp_emit_incoming_browsing_connection browsing_cid 0x%02x \n", browsing_cid); if (!callback) return; uint8_t event[11]; int pos = 0; @@ -190,14 +189,14 @@ void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t local_cid = l2cap_event_incoming_connection_get_local_cid(packet); avrcp_connection = get_avrcp_connection_for_bd_addr(event_addr, context); if (!avrcp_connection) { - printf("No previously created AVRCP controller connections"); + log_error("No previously created AVRCP controller connections"); l2cap_decline_connection(local_cid); break; } browsing_connection = avrcp_browsing_create_connection(avrcp_connection); browsing_connection->l2cap_browsing_cid = local_cid; browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION; - printf("Emit AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION browsing_cid 0x%02x, l2cap_signaling_cid 0x%02x\n", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid); + log_info("Emit AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION browsing_cid 0x%02x, l2cap_signaling_cid 0x%02x\n", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid); avrcp_emit_incoming_browsing_connection(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr); break; @@ -517,19 +516,18 @@ uint8_t avrcp_browsing_controller_disconnect(uint16_t avrcp_browsing_cid){ } uint8_t avrcp_avrcp_browsing_configure_incoming_connection(uint16_t avrcp_browsing_cid, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config){ - printf("avrcp_avrcp_browsing_configure_incoming_connection browsing cid 0x%02X\n", avrcp_browsing_cid); avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context); if (!avrcp_connection){ - printf("avrcp_avrcp_browsing_decline_incoming_connection: could not find a connection.\n"); + log_error("avrcp_avrcp_browsing_decline_incoming_connection: could not find a connection."); return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; } if (!avrcp_connection->browsing_connection){ - printf("avrcp_avrcp_browsing_decline_incoming_connection: no browsing connection.\n"); + log_error("avrcp_avrcp_browsing_decline_incoming_connection: no browsing connection."); return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; } if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_W4_ERTM_CONFIGURATION){ - printf("avrcp_avrcp_browsing_decline_incoming_connection: browsing connection in a wrong state.\n"); + log_error("avrcp_avrcp_browsing_decline_incoming_connection: browsing connection in a wrong state."); return ERROR_CODE_COMMAND_DISALLOWED; } @@ -537,7 +535,6 @@ uint8_t avrcp_avrcp_browsing_configure_incoming_connection(uint16_t avrcp_browsi avrcp_connection->browsing_connection->ertm_buffer = ertm_buffer; avrcp_connection->browsing_connection->ertm_buffer_size = size; memcpy(&avrcp_connection->browsing_connection->ertm_config, ertm_config, sizeof(l2cap_ertm_config_t)); - printf("accept ertm connection\n"); l2cap_accept_ertm_connection(avrcp_connection->browsing_connection->l2cap_browsing_cid, &avrcp_connection->browsing_connection->ertm_config, avrcp_connection->browsing_connection->ertm_buffer, avrcp_connection->browsing_connection->ertm_buffer_size); return ERROR_CODE_SUCCESS; } diff --git a/test/btstack_config.h b/test/btstack_config.h index 91c38a55d..5a6bbded9 100644 --- a/test/btstack_config.h +++ b/test/btstack_config.h @@ -29,7 +29,6 @@ // BTstack configuration. buffers, sizes, ... #define HCI_ACL_PAYLOAD_SIZE 1024 #define HCI_INCOMING_PRE_BUFFER_SIZE 6 - #define NVM_NUM_LINK_KEYS 2 #define NVM_NUM_DEVICE_DB_ENTRIES 4 diff --git a/test/pts/Makefile b/test/pts/Makefile index 0312ed2af..3d838bb81 100644 --- a/test/pts/Makefile +++ b/test/pts/Makefile @@ -2,6 +2,16 @@ BTSTACK_ROOT = ../.. +CLASSIC += \ + btstack_link_key_db_memory.c \ + sdp_util.c \ + spp_server.c \ + rfcomm.c \ + bnep.c \ + sdp_server.c \ + device_id_server.c \ + + CORE += \ btstack_memory.c \ btstack_linked_list.c \ @@ -67,6 +77,12 @@ AVDTP += \ btstack_ring_buffer.c \ # include ${BTSTACK_ROOT}/example/Makefile.inc + +HXCMOD_PLAYER = \ + ${BTSTACK_ROOT}/3rd-party/hxcmod-player/hxcmod.c \ + ${BTSTACK_ROOT}/3rd-party/hxcmod-player/mods/nao-deceased_by_disease.c \ + +include ${BTSTACK_ROOT}/example/Makefile.inc include ${BTSTACK_ROOT}/3rd-party/bluedroid/decoder/Makefile.inc include ${BTSTACK_ROOT}/3rd-party/bluedroid/encoder/Makefile.inc @@ -107,16 +123,22 @@ ATT_OBJ = $(ATT:.c=.o) SM_OBJ = $(SM:.c=.o) $(MICROECC:.c=.o) GATT_CLIENT_OBJ = $(GATT_CLIENT:.c=.o) GATT_SERVER_OBJ = $(GATT_SERVER:.c=.o) +CLASSIC_OBJ = $(CLASSIC:.c=.o) SBC_DECODER_OBJ = $(SBC_DECODER:.c=.o) SBC_ENCODER_OBJ = $(SBC_ENCODER:.c=.o) AVDTP_OBJ = $(AVDTP:.c=.o) +HXCMOD_PLAYER_OBJ = ${HXCMOD_PLAYER:.c=.o} EXAMPLES = iopt ble_peripheral_test ble_central_test l2cap_test classic_test bnep_test hsp_ag_test hsp_hs_test sco_loopback le_data_channel -EXAMPLES += avdtp_source_test avdtp_sink_test le_data_channel avrcp_controller_test +EXAMPLES += avdtp_source_test avdtp_sink_test le_data_channel avrcp_controller_test +# avrcp_target_test all: ${EXAMPLES} # compile .gatt descriptions +# avrcp_target_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_ENCODER_OBJ} ${SM_OBJ} ${AVDTP_OBJ} ${HXCMOD_PLAYER_OBJ} avrcp.o avrcp_target.o avrcp_target_test.c +# ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ + avrcp_controller_test: ${CORE_OBJ} ${COMMON_OBJ} ${SBC_DECODER_OBJ} ${SM_OBJ} ${SBC_ENCODER_OBJ} ${AVDTP_OBJ} sdp_client.o avrcp.o avrcp_media_item_iterator.o avrcp_controller.o avrcp_browsing_controller.o avrcp_controller_test.o ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ diff --git a/test/pts/avdtp_sink_test.c b/test/pts/avdtp_sink_test.c index 5b6352d35..120033875 100644 --- a/test/pts/avdtp_sink_test.c +++ b/test/pts/avdtp_sink_test.c @@ -46,11 +46,12 @@ #include "wav_util.h" #ifdef HAVE_PORTAUDIO -#include #include "btstack_ring_buffer.h" +#include #endif #ifdef HAVE_POSIX_FILE_IO +#include "wav_util.h" #define STORE_SBC_TO_SBC_FILE #define STORE_SBC_TO_WAV_FILE #endif @@ -60,27 +61,30 @@ #endif #define NUM_CHANNELS 2 -#define SAMPLE_RATE 44100 +#define BYTES_PER_FRAME (2*NUM_CHANNELS) +#define MAX_SBC_FRAME_SIZE 120 // SBC Decoder for WAV file or PortAudio #ifdef DECODE_SBC static btstack_sbc_decoder_state_t state; static btstack_sbc_mode_t mode = SBC_MODE_STANDARD; -static int total_num_samples = 0; #endif -// PortAdudio - live playback +#if defined(HAVE_PORTAUDIO) +#define PREBUFFER_MS 200 +static int audio_stream_started = 0; +static int audio_stream_paused = 0; +static btstack_ring_buffer_t ring_buffer; +#endif + +// PortAudio - live playback #ifdef HAVE_PORTAUDIO #define PA_SAMPLE_TYPE paInt16 +#define SAMPLE_RATE 48000 #define FRAMES_PER_BUFFER 128 -#define BYTES_PER_FRAME (2*NUM_CHANNELS) -#define PREBUFFER_MS 300 #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; static PaStream * stream; -static int pa_stream_started = 0; -static int pa_stream_paused = 0; +static uint8_t ring_buffer_storage[2*PREBUFFER_BYTES]; #endif // WAV File @@ -118,7 +122,6 @@ typedef struct { int frames_per_buffer; } avdtp_media_codec_configuration_sbc_t; -#ifdef HAVE_BTSTACK_STDIN // mac 2011: static const char * device_addr_string = "04:0C:CE:E4:85:D3"; // pts: static const char * device_addr_string = "00:1B:DC:08:0A:A5"; // mac 2013: @@ -127,13 +130,17 @@ static const char * device_addr_string = "84:38:35:65:d1:15"; // minijambox: static const char * device_addr_string = "00:21:3C:AC:F7:38"; // head phones: static const char * device_addr_string = "00:18:09:28:50:18"; // bt dongle: static const char * device_addr_string = "00:15:83:5F:9D:46"; -#endif static bd_addr_t device_addr; -static uint16_t avdtp_cid = 0; -static uint8_t sdp_avdtp_sink_service_buffer[150]; +static uint8_t is_cmd_triggered_localy = 0; +static uint8_t is_media_header_reported_once = 0; +static uint8_t is_media_initialized = 0; -static adtvp_media_codec_information_sbc_t sbc_capability; +static uint16_t avdtp_cid = 0; +static uint8_t local_seid = 0; +static uint8_t sdp_avdtp_sink_service_buffer[150]; + +static adtvp_media_codec_information_sbc_t sbc_capability; static avdtp_media_codec_configuration_sbc_t sbc_configuration; static uint8_t local_seid; static uint8_t remote_seid; @@ -144,100 +151,138 @@ static avdtp_capabilities_t remote_configuration; static avdtp_context_t a2dp_sink_context; static btstack_packet_callback_registration_t hci_event_callback_registration; - -static int media_initialized = 0; +#if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE) || defined(HAVE_AUDIO_DMA) +static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context); +#endif #ifdef HAVE_PORTAUDIO -static int patestCallback( const void *inputBuffer, void *outputBuffer, +static int portaudio_callback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ) { - /** patestCallback is called from different thread, don't use hci_dump / log_info here without additional checks */ + /** portaudio_callback is called from different thread, don't use hci_dump / log_info here without additional checks */ - (void) timeInfo; /* Prevent unused variable warnings. */ + // Prevent unused variable warnings. + (void) timeInfo; (void) statusFlags; (void) inputBuffer; (void) userData; int bytes_to_copy = framesPerBuffer * BYTES_PER_FRAME; - // fill with silence while paused - if (pa_stream_paused){ - + // fill ring buffer with silence while stream is paused + if (audio_stream_paused){ if (btstack_ring_buffer_bytes_available(&ring_buffer) < PREBUFFER_BYTES){ - // printf("PA: silence\n"); memset(outputBuffer, 0, bytes_to_copy); return 0; } else { // resume playback - pa_stream_paused = 0; + audio_stream_paused = 0; } } - // get data from ringbuffer + // get data from ring buffer uint32_t bytes_read = 0; btstack_ring_buffer_read(&ring_buffer, outputBuffer, bytes_to_copy, &bytes_read); bytes_to_copy -= bytes_read; - // fill with 0 if not enough + // fill ring buffer with silence if there are not enough bytes to copy if (bytes_to_copy){ memset(outputBuffer + bytes_read, 0, bytes_to_copy); - pa_stream_paused = 1; + audio_stream_paused = 1; } return 0; } #endif -#ifdef DECODE_SBC -static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ - UNUSED(sample_rate); - UNUSED(context); - -#ifdef STORE_SBC_TO_WAV_FILE - wav_writer_write_int16(num_samples*num_channels, data); - frame_count++; -#endif - - total_num_samples+=num_samples*num_channels; - -#ifdef HAVE_PORTAUDIO - if (!pa_stream_started){ - /* -- start stream -- */ - PaError err = Pa_StartStream(stream); - if (err != paNoError){ - printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); - return; - } - pa_stream_started = 1; - pa_stream_paused = 1; +#ifdef HAVE_AUDIO_DMA +static int next_buffer(int current){ + if (current == NUM_AUDIO_BUFFERS-1) return 0; + return current + 1; +} +static uint8_t * start_of_buffer(int num){ + return (uint8_t *) &audio_samples[num * DMA_AUDIO_FRAMES * 2]; +} +void hal_audio_dma_done(void){ + if (audio_stream_paused){ + hal_audio_dma_play((const uint8_t *) silent_buffer, DMA_AUDIO_FRAMES*4); + return; } - btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2); -#endif + // next buffer + int next_playback_buffer = next_buffer(playback_buffer); + uint8_t * playback_data; + if (next_playback_buffer == write_buffer){ + + // TODO: stop codec while playing silence when getting 'stream paused' + + // start playing silence + audio_stream_paused = 1; + hal_audio_dma_play((const uint8_t *) silent_buffer, DMA_AUDIO_FRAMES*4); + printf("%6u - paused - bytes in buffer %u\n", (int) btstack_run_loop_get_time_ms(), btstack_ring_buffer_bytes_available(&ring_buffer)); + return; + } + playback_buffer = next_playback_buffer; + playback_data = start_of_buffer(playback_buffer); + hal_audio_dma_play(playback_data, audio_samples_len[playback_buffer]); + // btstack_run_loop_embedded_trigger(); } #endif -static int init_media_processing(avdtp_media_codec_configuration_sbc_t configuration){ - int num_channels = configuration.num_channels; - int sample_rate = configuration.sampling_frequency; - + +#ifdef HAVE_AUDIO_DMA +static void hal_audio_dma_process(btstack_data_source_t * ds, btstack_data_source_callback_type_t callback_type){ + UNUSED(ds); + UNUSED(callback_type); + + if (!media_initialized) return; + + int trigger_resume = 0; + if (audio_stream_paused) { + if (sbc_frame_size && btstack_ring_buffer_bytes_available(&ring_buffer) >= OPTIMAL_FRAMES_MIN * sbc_frame_size){ + trigger_resume = 1; + // reset buffers + playback_buffer = NUM_AUDIO_BUFFERS - 1; + write_buffer = 0; + } else { + return; + } + } + + while (playback_buffer != write_buffer && btstack_ring_buffer_bytes_available(&ring_buffer) >= sbc_frame_size ){ + uint8_t frame[MAX_SBC_FRAME_SIZE]; + uint32_t bytes_read = 0; + btstack_ring_buffer_read(&ring_buffer, frame, sbc_frame_size, &bytes_read); + btstack_sbc_decoder_process_data(&state, 0, frame, sbc_frame_size); + } + + if (trigger_resume){ + printf("%6u - resume\n", (int) btstack_run_loop_get_time_ms()); + audio_stream_paused = 0; + } +} +#endif + +static int media_processing_init(avdtp_media_codec_configuration_sbc_t configuration){ + if (is_media_initialized) return 0; #ifdef DECODE_SBC btstack_sbc_decoder_init(&state, mode, handle_pcm_data, NULL); #endif #ifdef STORE_SBC_TO_WAV_FILE - wav_writer_open(wav_filename, num_channels, sample_rate); + wav_writer_open(wav_filename, configuration.num_channels, configuration.sampling_frequency); #endif #ifdef STORE_SBC_TO_SBC_FILE - sbc_file = fopen(sbc_filename, "wb"); + sbc_file = fopen(sbc_filename, "wb"); #endif #ifdef HAVE_PORTAUDIO // int frames_per_buffer = configuration.frames_per_buffer; PaError err; PaStreamParameters outputParameters; + const PaDeviceInfo *deviceInfo; /* -- initialize PortAudio -- */ err = Pa_Initialize(); @@ -247,126 +292,263 @@ static int init_media_processing(avdtp_media_codec_configuration_sbc_t configura } /* -- setup input and output -- */ outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ - outputParameters.channelCount = num_channels; + outputParameters.channelCount = configuration.num_channels; outputParameters.sampleFormat = PA_SAMPLE_TYPE; outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; + deviceInfo = Pa_GetDeviceInfo( outputParameters.device ); + printf("PortAudio: Output device: %s\n", deviceInfo->name); + log_info("PortAudio: Output device: %s", deviceInfo->name); /* -- setup stream -- */ err = Pa_OpenStream( &stream, NULL, /* &inputParameters */ &outputParameters, - sample_rate, + configuration.sampling_frequency, 0, paClipOff, /* we won't output out of range samples so don't bother clipping them */ - patestCallback, /* use callback */ + portaudio_callback, /* use callback */ NULL ); if (err != paNoError){ printf("Error initializing portaudio: \"%s\"\n", Pa_GetErrorText(err)); return err; } + log_info("PortAudio: stream opened"); + printf("PortAudio: stream opened\n"); +#endif +#ifdef HAVE_AUDIO_DMA + audio_stream_paused = 1; + hal_audio_dma_init(configuration.sampling_frequency); + hal_audio_dma_set_audio_played(&hal_audio_dma_done); + // start playing silence + hal_audio_dma_done(); +#endif + + #if defined(HAVE_PORTAUDIO) || defined (HAVE_AUDIO_DMA) memset(ring_buffer_storage, 0, sizeof(ring_buffer_storage)); btstack_ring_buffer_init(&ring_buffer, ring_buffer_storage, sizeof(ring_buffer_storage)); - pa_stream_started = 0; + audio_stream_started = 0; + audio_stream_paused = 0; #endif - media_initialized = 1; + is_media_initialized = 1; return 0; } -static void close_media_processing(void){ - if (!media_initialized) return; - media_initialized = 0; -#ifdef STORE_SBC_TO_WAV_FILE - printf(" Close wav writer.\n"); +static void media_processing_close(void){ + if (is_media_initialized) return; + is_media_initialized = 0; + +#ifdef STORE_SBC_TO_WAV_FILE wav_writer_close(); int total_frames_nr = state.good_frames_nr + state.bad_frames_nr + state.zero_frames_nr; - printf(" Decoding done. Processed totaly %d frames:\n - %d good\n - %d bad\n - %d zero frames\n", total_frames_nr, state.good_frames_nr, state.bad_frames_nr, state.zero_frames_nr); - printf(" Written %d frames to wav file: %s\n\n", frame_count, wav_filename); + printf("WAV Writer: Decoding done. Processed totaly %d frames:\n - %d good\n - %d bad\n - %d zero frames\n", total_frames_nr, state.good_frames_nr, state.bad_frames_nr, state.zero_frames_nr); + printf("WAV Writer: Written %d frames to wav file: %s\n", frame_count, wav_filename); #endif + #ifdef STORE_SBC_TO_SBC_FILE fclose(sbc_file); #endif +#if defined(HAVE_PORTAUDIO) || defined (HAVE_AUDIO_DMA) + audio_stream_started = 0; +#endif + #ifdef HAVE_PORTAUDIO + printf("PortAudio: Stream closed\n"); + log_info("PortAudio: Stream closed"); + PaError err = Pa_StopStream(stream); if (err != paNoError){ printf("Error stopping the stream: \"%s\"\n", Pa_GetErrorText(err)); + log_error("Error stopping the stream: \"%s\"", Pa_GetErrorText(err)); return; } - pa_stream_started = 0; err = Pa_CloseStream(stream); if (err != paNoError){ printf("Error closing the stream: \"%s\"\n", Pa_GetErrorText(err)); + log_error("Error closing the stream: \"%s\"", Pa_GetErrorText(err)); return; } - err = Pa_Terminate(); if (err != paNoError){ printf("Error terminating portaudio: \"%s\"\n", Pa_GetErrorText(err)); + log_error("Error terminating portaudio: \"%s\"", Pa_GetErrorText(err)); return; } #endif + +#ifdef HAVE_AUDIO_DMA + hal_audio_dma_close(); +#endif } + +/* @section Handle Media Data Packet + * + * @text Media data packets, in this case the audio data, are received through the handle_l2cap_media_data_packet callback. + * Currently, only the SBC media codec is supported. Hence, the media data consists of the media packet header and the SBC packet. + * The SBC data will be decoded using an SBC decoder if either HAVE_PORTAUDIO or STORE_SBC_TO_WAV_FILE directive is defined. + * The resulting PCM frames can be then captured through a PCM data callback registered during SBC decoder setup, i.e. the + * handle_pcm_data callback. + */ + +static int read_media_data_header(uint8_t * packet, int size, int * offset, avdtp_media_packet_header_t * media_header); +static int read_sbc_header(uint8_t * packet, int size, int * offset, avdtp_sbc_codec_header_t * sbc_header); + static void handle_l2cap_media_data_packet(uint8_t seid, uint8_t *packet, uint16_t size){ UNUSED(seid); - int pos = 0; avdtp_media_packet_header_t media_header; - media_header.version = packet[pos] & 0x03; - media_header.padding = get_bit16(packet[pos],2); - media_header.extension = get_bit16(packet[pos],3); - media_header.csrc_count = (packet[pos] >> 4) & 0x0F; - - pos++; - - media_header.marker = get_bit16(packet[pos],0); - media_header.payload_type = (packet[pos] >> 1) & 0x7F; - pos++; - - media_header.sequence_number = big_endian_read_16(packet, pos); - pos+=2; - - media_header.timestamp = big_endian_read_32(packet, pos); - pos+=4; - - media_header.synchronization_source = big_endian_read_32(packet, pos); - pos+=4; - - UNUSED(media_header); - - // TODO: read csrc list - - // printf_hexdump( packet, pos ); - // printf("MEDIA HEADER: %u timestamp, version %u, padding %u, extension %u, csrc_count %u\n", - // media_header.timestamp, media_header.version, media_header.padding, media_header.extension, media_header.csrc_count); - // printf("MEDIA HEADER: marker %02x, payload_type %02x, sequence_number %u, synchronization_source %u\n", - // media_header.marker, media_header.payload_type, media_header.sequence_number, media_header.synchronization_source); + if (!read_media_data_header(packet, size, &pos, &media_header)) return; avdtp_sbc_codec_header_t sbc_header; - sbc_header.fragmentation = get_bit16(packet[pos], 7); - sbc_header.starting_packet = get_bit16(packet[pos], 6); - sbc_header.last_packet = get_bit16(packet[pos], 5); - sbc_header.num_frames = packet[pos] & 0x0f; - pos++; + if (!read_sbc_header(packet, size, &pos, &sbc_header)) return; - UNUSED(sbc_header); - // 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 ); +#ifdef HAVE_AUDIO_DMA + // store sbc frame size for buffer management + sbc_frame_size = (size-pos)/ sbc_header.num_frames; +#endif -#ifdef DECODE_SBC +#if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE) btstack_sbc_decoder_process_data(&state, 0, packet+pos, size-pos); #endif +#ifdef HAVE_AUDIO_DMA + btstack_ring_buffer_write(&ring_buffer, packet+pos, size-pos); + + // decide on audio sync drift based on number of sbc frames in queue + int sbc_frames_in_buffer = btstack_ring_buffer_bytes_available(&ring_buffer) / sbc_frame_size; + if (sbc_frames_in_buffer < OPTIMAL_FRAMES_MIN){ + sbc_samples_fix = 1; // duplicate last sample + } else if (sbc_frames_in_buffer <= OPTIMAL_FRAMES_MAX){ + sbc_samples_fix = 0; // nothing to do + } else { + sbc_samples_fix = -1; // drop last sample + } + + // dump + printf("%6u %03u %d\n", (int) btstack_run_loop_get_time_ms(), sbc_frames_in_buffer, sbc_samples_fix); +#endif + #ifdef STORE_SBC_TO_SBC_FILE fwrite(packet+pos, size-pos, 1, sbc_file); #endif -#ifdef HAVE_PORTAUDIO - log_info("PA: bytes avail after recv: %d", btstack_ring_buffer_bytes_available(&ring_buffer)); +} + + /* @section Handle PCM Data + * + * @text In this example, we use the [PortAudio library](http://www.portaudio.com) to play the audio stream. + * The PCM data are bufferd in a ring buffer. + * Aditionally, tha audio data can be stored in the avdtp_sink.wav file. + */ +#if defined(HAVE_PORTAUDIO) || defined(STORE_SBC_TO_WAV_FILE) +static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){ + UNUSED(sample_rate); + UNUSED(context); + +#ifdef STORE_SBC_TO_WAV_FILE + wav_writer_write_int16(num_samples*num_channels, data); + frame_count++; #endif + +#ifdef HAVE_PORTAUDIO + // store pcm samples in ring buffer + btstack_ring_buffer_write(&ring_buffer, (uint8_t *)data, num_samples*num_channels*2); + + if (!audio_stream_started){ + audio_stream_paused = 1; + /* -- start stream -- */ + PaError err = Pa_StartStream(stream); + if (err != paNoError){ + printf("Error starting the stream: \"%s\"\n", Pa_GetErrorText(err)); + return; + } + audio_stream_started = 1; + } +#endif + +#ifdef HAVE_AUDIO_DMA + // store in ring buffer + uint8_t * write_data = start_of_buffer(write_buffer); + uint16_t len = num_samples*num_channels*2; + memcpy(write_data, data, len); + audio_samples_len[write_buffer] = len; + + // add/drop audio frame to fix drift + if (sbc_samples_fix > 0){ + memcpy(write_data + len, write_data + len - 4, 4); + audio_samples_len[write_buffer] += 4; + } + if (sbc_samples_fix < 0){ + audio_samples_len[write_buffer] -= 4; + } + + write_buffer = next_buffer(write_buffer); +#endif +} +#endif + +static int read_sbc_header(uint8_t * packet, int size, int * offset, avdtp_sbc_codec_header_t * sbc_header){ + int sbc_header_len = 12; // without crc + int pos = *offset; + + if (size - pos < sbc_header_len){ + printf("Not enough data to read SBC header, expected %d, received %d\n", sbc_header_len, size-pos); + return 0; + } + + sbc_header->fragmentation = get_bit16(packet[pos], 7); + sbc_header->starting_packet = get_bit16(packet[pos], 6); + sbc_header->last_packet = get_bit16(packet[pos], 5); + sbc_header->num_frames = packet[pos] & 0x0f; + pos++; + // 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); + *offset = pos; + return 1; +} + +static int read_media_data_header(uint8_t *packet, int size, int *offset, avdtp_media_packet_header_t *media_header){ + int media_header_len = 12; // without crc + int pos = *offset; + + if (size - pos < media_header_len){ + printf("Not enough data to read media packet header, expected %d, received %d\n", media_header_len, size-pos); + return 0; + } + + media_header->version = packet[pos] & 0x03; + media_header->padding = get_bit16(packet[pos],2); + media_header->extension = get_bit16(packet[pos],3); + media_header->csrc_count = (packet[pos] >> 4) & 0x0F; + pos++; + + media_header->marker = get_bit16(packet[pos],0); + media_header->payload_type = (packet[pos] >> 1) & 0x7F; + pos++; + + media_header->sequence_number = big_endian_read_16(packet, pos); + pos+=2; + + media_header->timestamp = big_endian_read_32(packet, pos); + pos+=4; + + media_header->synchronization_source = big_endian_read_32(packet, pos); + pos+=4; + *offset = pos; + // TODO: read csrc list + + // printf_hexdump( packet, pos ); + if (!is_media_header_reported_once){ + is_media_header_reported_once = 1; + printf("MEDIA HEADER: %u timestamp, version %u, padding %u, extension %u, csrc_count %u\n", + media_header->timestamp, media_header->version, media_header->padding, media_header->extension, media_header->csrc_count); + printf("MEDIA HEADER: marker %02x, payload_type %02x, sequence_number %u, synchronization_source %u\n", + media_header->marker, media_header->payload_type, media_header->sequence_number, media_header->synchronization_source); + } + return 1; } static void dump_sbc_capability(adtvp_media_codec_information_sbc_t media_codec_sbc){ @@ -393,20 +575,29 @@ static void dump_sbc_configuration(avdtp_media_codec_configuration_sbc_t configu static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ if (packet_type != HCI_EVENT_PACKET) return; + + if (hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST){ + // inform about pin code request + bd_addr_t event_addr; + printf("Pin code request - using '0000'\n"); + hci_event_pin_code_request_get_bd_addr(packet, event_addr); + gap_pin_code_response(event_addr, "0000"); + } + if (hci_event_packet_get_type(packet) != HCI_EVENT_AVDTP_META) return; UNUSED(channel); UNUSED(size); uint8_t status; - + switch (packet[2]){ case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED: avdtp_cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet); status = avdtp_subevent_signaling_connection_established_get_status(packet); if (status != ERROR_CODE_SUCCESS){ - printf("AVDTP connection establishment failed: status 0x%02x.\n", status); + printf("AVDTP connection failed with status 0x%02x.\n", status); break; } - printf("AVDTP connection established: avdtp_cid 0x%02x.\n", avdtp_cid); + printf("AVDTP Sink connected: avdtp_cid 0x%02x.\n", avdtp_cid); break; case AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: avdtp_cid = avdtp_subevent_signaling_connection_released_get_avdtp_cid(packet); @@ -419,7 +610,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe avdtp_subevent_signaling_sep_found_get_media_type(packet), avdtp_subevent_signaling_sep_found_get_sep_type(packet)); break; case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY: - printf("Received MEDIA_CODEC_SBC_CAPABILITY\n"); + printf("Received SBC codec capabilities\n"); sbc_capability.sampling_frequency_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet); sbc_capability.channel_mode_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet); sbc_capability.block_length_bitmap = avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet); @@ -430,7 +621,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe dump_sbc_capability(sbc_capability); break; case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{ - printf("Received MEDIA_CODEC_SBC_CONFIGURATION\n"); + printf("Received SBC codec configuration\n"); sbc_configuration.reconfigure = avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); sbc_configuration.num_channels = avdtp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(packet); sbc_configuration.sampling_frequency = avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet); @@ -444,22 +635,61 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe dump_sbc_configuration(sbc_configuration); if (sbc_configuration.reconfigure){ - close_media_processing(); - init_media_processing(sbc_configuration); - } else { - init_media_processing(sbc_configuration); + media_processing_close(); } + media_processing_init(sbc_configuration); break; } case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED: + printf("Streaming connection opened.\n"); + break; + + case AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED: + printf("Streaming connection released.\n"); + is_cmd_triggered_localy = 0; + is_media_header_reported_once = 0; + media_processing_close(); break; case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY: printf("Received non SBC codec, event not parsed.\n"); break; - case AVDTP_SUBEVENT_SIGNALING_ACCEPT: + + case AVDTP_SUBEVENT_SIGNALING_ACCEPT:{ + switch (avdtp_subevent_signaling_accept_get_signal_identifier(packet)){ + case AVDTP_SI_START: + printf("Stream started\n"); + media_processing_init(sbc_configuration); + break; + case AVDTP_SI_SUSPEND: + printf("Stream paused\n"); + media_processing_close(); + break; + case AVDTP_SI_ABORT: + case AVDTP_SI_CLOSE: + printf("Stream stoped\n"); + media_processing_close(); + break; + default: + break; + } + if (is_cmd_triggered_localy){ + is_cmd_triggered_localy = 0; + printf("AVDTP Sink command accepted\n"); + } + break; + } + case AVDTP_SUBEVENT_SIGNALING_REJECT: + case AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT: + if (is_cmd_triggered_localy){ + is_cmd_triggered_localy = 0; + printf("AVDTP Sink command rejected\n"); + } break; default: - printf("AVDTP Sink event not parsed\n"); + if (is_cmd_triggered_localy){ + is_cmd_triggered_localy = 0; + } + printf("AVDTP Sink event 0x%02x not parsed\n", packet[2]); break; } } @@ -506,31 +736,33 @@ static void show_usage(void){ } static void stdin_process(char cmd){ + uint8_t status = ERROR_CODE_SUCCESS; remote_seid = 1; + is_cmd_triggered_localy = 1; switch (cmd){ case 'c': printf("Establish AVDTP Sink connection to %s\n", device_addr_string); - avdtp_sink_connect(device_addr, &avdtp_cid); + status = avdtp_sink_connect(device_addr, &avdtp_cid); break; case 'C': printf("Disconnect AVDTP Sink\n"); - avdtp_sink_disconnect(avdtp_cid); + status = avdtp_sink_disconnect(avdtp_cid); break; case 'd': printf("Discover stream endpoints of %s\n", device_addr_string); - avdtp_sink_discover_stream_endpoints(avdtp_cid); + status = avdtp_sink_discover_stream_endpoints(avdtp_cid); break; case 'g': printf("Get capabilities of stream endpoint with seid %d\n", remote_seid); - avdtp_sink_get_capabilities(avdtp_cid, remote_seid); + status = avdtp_sink_get_capabilities(avdtp_cid, remote_seid); break; case 'a': printf("Get all capabilities of stream endpoint with seid %d\n", remote_seid); - avdtp_sink_get_all_capabilities(avdtp_cid, remote_seid); + status = avdtp_sink_get_all_capabilities(avdtp_cid, remote_seid); break; case 'f': printf("Get configuration of stream endpoint with seid %d\n", remote_seid); - avdtp_sink_get_configuration(avdtp_cid, remote_seid); + status = avdtp_sink_get_configuration(avdtp_cid, remote_seid); break; case 's': printf("Set configuration of stream endpoint with seid %d\n", remote_seid); @@ -539,7 +771,7 @@ static void stdin_process(char cmd){ remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC; remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_configuration); remote_configuration.media_codec.media_codec_information = media_sbc_codec_configuration; - avdtp_sink_set_configuration(avdtp_cid, local_seid, remote_seid, remote_configuration_bitmap, remote_configuration); + status = avdtp_sink_set_configuration(avdtp_cid, local_seid, remote_seid, remote_configuration_bitmap, remote_configuration); break; case 'R': printf("Reconfigure stream endpoint with seid %d\n", remote_seid); @@ -548,37 +780,42 @@ static void stdin_process(char cmd){ remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC; remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_reconfiguration); remote_configuration.media_codec.media_codec_information = media_sbc_codec_reconfiguration; - avdtp_sink_reconfigure(avdtp_cid, local_seid, remote_seid, remote_configuration_bitmap, remote_configuration); + status = avdtp_sink_reconfigure(avdtp_cid, local_seid, remote_seid, remote_configuration_bitmap, remote_configuration); break; case 'o': printf("Establish stream between local %d and remote %d seid\n", local_seid, remote_seid); - avdtp_sink_open_stream(avdtp_cid, local_seid, remote_seid); + status = avdtp_sink_open_stream(avdtp_cid, local_seid, remote_seid); break; case 'm': printf("Start stream between local %d and remote %d seid\n", local_seid, remote_seid); - avdtp_sink_start_stream(avdtp_cid, local_seid); + status = avdtp_sink_start_stream(avdtp_cid, local_seid); break; case 'A': printf("Abort stream between local %d and remote %d seid\n", local_seid, remote_seid); - avdtp_sink_abort_stream(avdtp_cid, local_seid); + status = avdtp_sink_abort_stream(avdtp_cid, local_seid); break; case 'S': printf("Release stream between local %d and remote %d seid\n", local_seid, remote_seid); - avdtp_sink_stop_stream(avdtp_cid, local_seid); + status = avdtp_sink_stop_stream(avdtp_cid, local_seid); break; case 'P': - printf("Susspend stream between local %d and remote %d seid\n", local_seid, remote_seid); - avdtp_sink_suspend(avdtp_cid, local_seid); + printf("Suspend stream between local %d and remote %d seid\n", local_seid, remote_seid); + status = avdtp_sink_suspend(avdtp_cid, local_seid); break; case '\n': case '\r': + is_cmd_triggered_localy = 0; break; default: + is_cmd_triggered_localy = 0; show_usage(); break; } + if (status != ERROR_CODE_SUCCESS){ + printf("AVDTP Sink cmd \'%c\' failed, status 0x%02x\n", cmd, status); + } } #endif @@ -613,7 +850,7 @@ int btstack_main(int argc, const char * argv[]){ 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 A2DP Sink PTS Test"); + gap_set_local_name("BTstack AVDTP Sink PTS 00:00:00:00:00:00"); gap_discoverable_control(1); gap_set_class_of_device(0x200408); diff --git a/test/pts/avdtp_source_test.c b/test/pts/avdtp_source_test.c index 374d10fc7..179b08456 100644 --- a/test/pts/avdtp_source_test.c +++ b/test/pts/avdtp_source_test.c @@ -690,7 +690,7 @@ int btstack_main(int argc, const char * argv[]){ a2dp_source_create_sdp_record(sdp_avdtp_source_service_buffer, 0x10002, 1, NULL, NULL); sdp_register_service(sdp_avdtp_source_service_buffer); - gap_set_local_name("BTstack PTS AVDTP Source Test 00:00:00:00:00:00"); + gap_set_local_name("BTstack AVDTP Source PTS 00:00:00:00:00:00"); gap_discoverable_control(1); gap_set_class_of_device(0x200408); sscanf_bd_addr(device_addr_string, device_addr); diff --git a/test/pts/avrcp_controller_test.c b/test/pts/avrcp_controller_test.c index d7103947f..c2d200d69 100644 --- a/test/pts/avrcp_controller_test.c +++ b/test/pts/avrcp_controller_test.c @@ -502,7 +502,7 @@ static uint8_t media_sbc_codec_capabilities[] = { #ifdef HAVE_BTSTACK_STDIN static void stdin_process(char cmd){ - uint8_t status; + uint8_t status = ERROR_CODE_SUCCESS; sep.seid = 1; switch (cmd){ case 'b': @@ -754,9 +754,11 @@ static void stdin_process(char cmd){ status = avrcp_browsing_controller_set_browsed_player(browsing_cid, players[0]); break; case 'p': - printf("AVRCP Browsing: get media players\n"); - player_index = -1; - status = avrcp_browsing_controller_get_media_players(browsing_cid, 0, 0xFFFFFFFF, AVRCP_MEDIA_ATTR_ALL); + players[next_player_index()] = 1; + + // printf("AVRCP Browsing: get media players. Brosing cid 0x%02X\n", browsing_cid); + // player_index = -1; + // status = avrcp_browsing_controller_get_media_players(browsing_cid, 0, 0xFFFFFFFF, AVRCP_MEDIA_ATTR_ALL); break; case 'Q': printf("AVRCP Browsing: browse folders\n"); @@ -792,6 +794,9 @@ static void stdin_process(char cmd){ break; } + if (status != ERROR_CODE_SUCCESS){ + printf("Could not complete cmd %c, status 0x%02X\n", cmd, status); + } } #endif @@ -839,7 +844,7 @@ int btstack_main(int argc, const char * argv[]){ avrcp_controller_create_sdp_record(sdp_avrcp_controller_service_buffer, 0x10001, AVRCP_BROWSING_ENABLED, 1, NULL, NULL); sdp_register_service(sdp_avrcp_controller_service_buffer); - gap_set_local_name("BTstack AVRCP PTS Test"); + gap_set_local_name("BTstack AVRCP Controller PTS 00:00:00:00:00:00"); gap_discoverable_control(1); gap_set_class_of_device(0x200408);