diff --git a/test/avdtp/avdtp.h b/test/avdtp/avdtp.h deleted file mode 100644 index 341d26a33..000000000 --- a/test/avdtp/avdtp.h +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - -/* - * avdtp.h - * - * Audio/Video Distribution Transport Protocol - * - * This protocol defines A/V stream negotiation, establishment, and transmission - * procedures. Also specified are the message formats that are exchanged between - * such devices to transport their A/V streams in A/V distribution applications. - * - * Media packets are unidirectional, they travel downstream from AVDTP Source to AVDTP Sink. - */ - -#ifndef __AVDTP_H -#define __AVDTP_H - -#include -#include "hci.h" - -#if defined __cplusplus -extern "C" { -#endif - -#define MAX_NUM_SEPS 10 - -// protocols -#define PSM_AVCTP 0x0017 -#define PSM_AVDTP 0x0019 - -// service classes -#define AUDIO_SOURCE_GROUP 0x110A -#define AUDIO_SINK_GROUP 0x110B -#define AV_REMOTE_CONTROL_TARGET 0X110C -#define ADVANCED_AUDIO_DISTRIBUTION 0X110D -#define AV_REMOTE_CONTROL 0X110E -#define AV_REMOTE_CONTROL_CONTROLER 0X110F - -#define MAX_CSRC_NUM 15 - -// Supported Features -#define AVDTP_SOURCE_SF_Player 0x0001 -#define AVDTP_SOURCE_SF_Microphone 0x0002 -#define AVDTP_SOURCE_SF_Tuner 0x0004 -#define AVDTP_SOURCE_SF_Mixer 0x0008 - -#define AVDTP_SINK_SF_Headphone 0x0001 -#define AVDTP_SINK_SF_Speaker 0x0002 -#define AVDTP_SINK_SF_Recorder 0x0004 -#define AVDTP_SINK_SF_Amplifier 0x0008 - -// ACP to INT, Signal Response Header Error Codes -#define BAD_HEADER_FORMAT 0x01 - -// ACP to INT, Signal Response Payload Format Error Codes -#define BAD_LENGTH 0x11 -#define BAD_ACP_SEID 0x12 -#define SEP_IN_USE 0x13 -#define SEP_NOT_IN_USE 0x14 -#define BAD_SERV_CATEGORY 0x17 -#define BAD_PAYLOAD_FORMAT 0x18 -#define NOT_SUPPORTED_COMMAND 0x19 -#define INVALID_CAPABILITIES 0x1A - -// ACP to INT, Signal Response Transport Service Capabilities Error Codes -#define BAD_RECOVERY_TYPE 0x22 -#define BAD_MEDIA_TRANSPORT_FORMAT 0x23 -#define BAD_RECOVERY_FORMAT 0x25 -#define BAD_ROHC_FORMAT 0x26 -#define BAD_CP_FORMAT 0x27 -#define BAD_MULTIPLEXING_FORMAT 0x28 -#define UNSUPPORTED_CONFIGURATION 0x29 - -// ACP to INT, Procedure Error Codes -#define BAD_STATE 0x31 -// Signal Identifier fields -typedef enum { - AVDTP_SI_DISCOVER = 0x01, - AVDTP_SI_GET_CAPABILITIES, - AVDTP_SI_SET_CONFIGURATION, - AVDTP_SI_GET_CONFIGURATION, - AVDTP_SI_RECONFIGURE, //5 - AVDTP_SI_OPEN, //6 - AVDTP_SI_START, //7 - AVDTP_SI_CLOSE, - AVDTP_SI_SUSPEND, - AVDTP_SI_ABORT, //10 - AVDTP_SI_SECURITY_CONTROL, - AVDTP_SI_GET_ALL_CAPABILITIES, //12 - AVDTP_SI_DELAYREPORT -} avdtp_signal_identifier_t; - -typedef enum { - AVDTP_SINGLE_PACKET= 0, - AVDTP_START_PACKET , - AVDTP_CONTINUE_PACKET , - AVDTP_END_PACKET -} avdtp_packet_type_t; - -typedef enum { - AVDTP_CMD_MSG = 0, - AVDTP_GENERAL_REJECT_MSG , - AVDTP_RESPONSE_ACCEPT_MSG , - AVDTP_RESPONSE_REJECT_MSG -} avdtp_message_type_t; - -typedef enum{ - AVDTP_AUDIO = 0, - AVDTP_VIDEO, - AVDTP_MULTIMEDIA -} avdtp_media_type_t; - -typedef enum{ - AVDTP_CODEC_SBC = 0x00, - AVDTP_CODEC_MPEG_1_2_AUDIO = 0x01, - AVDTP_CODEC_MPEG_2_4_AAC = 0x02, - AVDTP_CODEC_ATRAC_FAMILY = 0x04, - AVDTP_CODEC_NON_A2DP = 0xFF -} avdtp_media_codec_type_t; - -typedef enum{ - AVDTP_CONTENT_PROTECTION_DTCP = 0x0001, - AVDTP_CONTENT_PROTECTION_SCMS_T = 0x0002 -} avdtp_content_protection_type_t; - -typedef enum{ - AVDTP_SOURCE = 0, - AVDTP_SINK -} avdtp_sep_type_t; - -typedef enum { - AVDTP_SERVICE_CATEGORY_INVALID_0 = 0x00, - AVDTP_MEDIA_TRANSPORT = 0X01, - AVDTP_REPORTING, - AVDTP_RECOVERY, - AVDTP_CONTENT_PROTECTION, //4 - AVDTP_HEADER_COMPRESSION, //5 - AVDTP_MULTIPLEXING, //6 - AVDTP_MEDIA_CODEC, //7 - AVDTP_DELAY_REPORTING, //8 - AVDTP_SERVICE_CATEGORY_INVALID_FF = 0xFF -} avdtp_service_category_t; - -typedef struct { - uint8_t recovery_type; // 0x01 = RFC2733 - uint8_t maximum_recovery_window_size; // 0x01 to 0x18, for a Transport Packet - uint8_t maximum_number_media_packets; // 0x01 to 0x18, The maximum number of media packets a specific parity code covers -} avdtp_recovery_capabilities_t; - -typedef struct { - avdtp_media_type_t media_type; - avdtp_media_codec_type_t media_codec_type; - uint16_t media_codec_information_len; - const uint8_t * media_codec_information; -} adtvp_media_codec_capabilities_t; - -typedef struct { - uint16_t cp_type; - uint16_t cp_type_value_len; - const uint8_t * cp_type_value; -} adtvp_content_protection_t; - -typedef struct{ - uint8_t back_ch; // byte0 - bit 8; 0=Not Available/Not Used; 1=Available/In Use - uint8_t media; // byte0 - bit 7 - uint8_t recovery; // byte0 - bit 6 -} avdtp_header_compression_capabilities_t; - -typedef struct{ - uint8_t fragmentation; // byte0 - bit 8, Allow Adaptation Layer Fragmentation, 0 no, 1 yes - // Request/indicate value of the Transport Session Identifier for a media, reporting, or recovery transport sessions, respectively - uint8_t transport_identifiers_num; - uint8_t transport_session_identifiers[3]; // byte1, upper 5bits, 0x01 to 0x1E - // Request/indicate value for TCID for a media, reporting, or transport session - uint8_t tcid[3]; // byte2 0x01 to 0x1E -} avdtp_multiplexing_mode_capabilities_t; - -typedef struct{ - avdtp_recovery_capabilities_t recovery; - adtvp_media_codec_capabilities_t media_codec; - adtvp_content_protection_t content_protection; - avdtp_header_compression_capabilities_t header_compression; - avdtp_multiplexing_mode_capabilities_t multiplexing_mode; -} avdtp_capabilities_t; - -typedef enum{ - AVDTP_SBC_48000 = 1, - AVDTP_SBC_44100 = 2, - AVDTP_SBC_32000 = 4, - AVDTP_SBC_16000 = 8 -} avdtp_sbc_sampling_frequency_t; - -typedef enum{ - AVDTP_SBC_JOINT_STEREO = 1, - AVDTP_SBC_STEREO = 2, - AVDTP_SBC_DUAL_CHANNEL = 4, - AVDTP_SBC_MONO = 8 -} avdtp_sbc_channel_mode_t; - -typedef enum{ - AVDTP_SBC_BLOCK_LENGTH_16 = 1, - AVDTP_SBC_BLOCK_LENGTH_12 = 2, - AVDTP_SBC_BLOCK_LENGTH_8 = 4, - AVDTP_SBC_BLOCK_LENGTH_4 = 8 -} avdtp_sbc_block_length_t; - -typedef enum{ - AVDTP_SBC_SUBBANDS_8 = 1, - AVDTP_SBC_SUBBANDS_4 = 2 -} avdtp_sbc_subbands_t; - -typedef enum{ - AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS = 1, - AVDTP_SBC_ALLOCATION_METHOD_SNR = 2 -} avdtp_sbc_allocation_method_t; - -typedef struct { - uint8_t fragmentation; - uint8_t starting_packet; // of fragmented SBC frame - uint8_t last_packet; // of fragmented SBC frame - uint8_t num_frames; -} avdtp_sbc_codec_header_t; - -// typedef struct { -// uint8_t transaction_label; -// avdtp_packet_type_t packet_type; -// avdtp_message_type_t message_type; -// uint8_t signal_identifier; -// } avdtp_signaling_packet_header_t; - -typedef struct { - uint8_t version; - uint8_t padding; - uint8_t extension; - uint8_t csrc_count; - uint8_t marker; - uint8_t payload_type; - - uint16_t sequence_number; - uint32_t timestamp; - uint32_t synchronization_source; - - uint32_t csrc_list[MAX_CSRC_NUM]; -} avdtp_media_packet_header_t; - -typedef enum { - AVDTP_BASIC_SERVICE_MODE, - AVDTP_MULTIPLEXING_SERVICE_MODE -} avdtp_service_mode_t; - -typedef enum { - AVDTP_STREAM_ENDPOINT_IDLE, - AVDTP_STREAM_ENDPOINT_CONFIGURATION_SUBSTATEMACHINE, - AVDTP_STREAM_ENDPOINT_CONFIGURED, - AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED, - AVDTP_STREAM_ENDPOINT_OPENED, - AVDTP_STREAM_ENDPOINT_STREAMING, - AVDTP_STREAM_ENDPOINT_CLOSING, - AVDTP_STREAM_ENDPOINT_ABORTING, - AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_DISCONNECTED -} avdtp_stream_endpoint_state_t; - -typedef enum { - AVDTP_INITIATOR_STREAM_CONFIG_IDLE, - AVDTP_INITIATOR_W2_SET_CONFIGURATION, - AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID, - AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID, - AVDTP_INITIATOR_W2_MEDIA_CONNECT, - AVDTP_INITIATOR_W2_STREAMING_START, - AVDTP_INITIATOR_W2_STREAMING_STOP, - AVDTP_INITIATOR_W2_STREAMING_ABORT, - AVDTP_INITIATOR_FRAGMENTATED_COMMAND, - AVDTP_INITIATOR_W4_ANSWER -} avdtp_initiator_stream_endpoint_state_t; - -typedef enum { - AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE, - AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES, - AVDTP_ACCEPTOR_W2_ANSWER_GET_ALL_CAPABILITIES, - AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION, - AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE, - AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION, - AVDTP_ACCEPTOR_W2_ANSWER_OPEN_STREAM, - - AVDTP_ACCEPTOR_W4_L2CAP_FOR_MEDIA_CONNECTED, - - AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM, - AVDTP_ACCEPTOR_W2_ANSWER_CLOSE_STREAM, - AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM, - AVDTP_ACCEPTOR_W2_SUSPEND_STREAM_WITH_SEID, - AVDTP_ACCEPTOR_W2_ANSWER_SUSPEND_STREAM, - AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE, - AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE, - AVDTP_ACCEPTOR_W2_REJECT_UNKNOWN_CMD, - AVDTP_ACCEPTOR_STREAMING -} avdtp_acceptor_stream_endpoint_state_t; - -typedef struct { - uint8_t seid; // 0x01 – 0x3E, 6bit - uint8_t in_use; // 1 bit, 0 - not in use, 1 - in use - avdtp_media_type_t media_type; // 4 bit - avdtp_sep_type_t type; // 1 bit, 0 - SRC, 1 - SNK - - uint16_t registered_service_categories; - avdtp_capabilities_t capabilities; - - uint16_t configured_service_categories; - avdtp_capabilities_t configuration; -} avdtp_sep_t; - - -typedef enum { - AVDTP_SIGNALING_CONNECTION_IDLE, - AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED, - AVDTP_SIGNALING_CONNECTION_OPENED, - AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED -} avdtp_connection_state_t; - -typedef enum { - AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE, - AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS, - AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE, - AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE, - AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_GENERAL_REJECT_WITH_ERROR_CODE -} avdtp_acceptor_connection_state_t; - -typedef enum { - AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE, - AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS, - AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES, - AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES, - AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION, - AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER -} avdtp_initiator_connection_state_t; - -typedef struct { - uint8_t command[200]; - uint16_t size; - uint16_t offset; - 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; - -typedef struct { - btstack_linked_item_t item; - - bd_addr_t remote_addr; - hci_con_handle_t con_handle; - uint16_t l2cap_signaling_cid; - avdtp_service_mode_t service_mode; - - avdtp_connection_state_t state; - avdtp_acceptor_connection_state_t acceptor_connection_state; - avdtp_initiator_connection_state_t initiator_connection_state; - - // used for fragmentation - // avdtp_signaling_packet_header_t signaling_header; - avdtp_signaling_packet_t signaling_packet; - - uint8_t disconnect; - uint8_t initiator_transaction_label; - uint8_t acceptor_transaction_label; - uint8_t query_seid; - uint8_t int_seid; - uint8_t acp_seid; - - avdtp_capabilities_t remote_capabilities; - uint16_t remote_capabilities_bitmap; - - uint8_t wait_to_send_acceptor; - uint8_t wait_to_send_initiator; - uint8_t wait_to_send_self; - - uint8_t suspended_seids[MAX_NUM_SEPS]; - uint8_t num_suspended_seids; - - uint8_t reject_service_category; - avdtp_signal_identifier_t reject_signal_identifier; - uint8_t error_code; -} avdtp_connection_t; - - -typedef struct avdtp_stream_endpoint { - btstack_linked_item_t item; - - // original capabilities - avdtp_sep_t sep; - uint16_t l2cap_media_cid; - uint16_t l2cap_reporting_cid; - uint16_t l2cap_recovery_cid; - - avdtp_stream_endpoint_state_t state; - avdtp_acceptor_stream_endpoint_state_t acceptor_config_state; - avdtp_initiator_stream_endpoint_state_t initiator_config_state; - - // active connection - avdtp_connection_t * connection; - // store configurations with remote seps - avdtp_sep_t remote_seps[MAX_NUM_SEPS]; - uint8_t remote_seps_num; - - // currently active remote seid - uint8_t remote_sep_index; - // register request for media L2cap connection release - uint8_t media_disconnect; - uint8_t media_connect; -} avdtp_stream_endpoint_t; - -#if defined __cplusplus -} -#endif - -#endif // __AVDTP_H \ No newline at end of file diff --git a/test/avdtp/avdtp_acceptor.c b/test/avdtp/avdtp_acceptor.c deleted file mode 100644 index a840565c2..000000000 --- a/test/avdtp/avdtp_acceptor.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - - -#include -#include -#include -#include -#include - -#include "btstack.h" -#include "avdtp.h" -#include "avdtp_util.h" -#include "avdtp_acceptor.h" - - -static int avdtp_acceptor_send_accept_response(uint16_t cid, uint8_t transaction_label, avdtp_signal_identifier_t identifier){ - uint8_t command[2]; - command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_RESPONSE_ACCEPT_MSG); - command[1] = (uint8_t)identifier; - return l2cap_send(cid, command, sizeof(command)); -} - -static int avdtp_acceptor_process_chunk(avdtp_signaling_packet_t * signaling_packet, uint8_t * packet, uint16_t size){ - memcpy(signaling_packet->command + signaling_packet->size, packet, size); - signaling_packet->size += size; - return signaling_packet->packet_type == AVDTP_SINGLE_PACKET || signaling_packet->packet_type == AVDTP_END_PACKET; -} - -static int avdtp_acceptor_validate_msg_length(avdtp_signal_identifier_t signal_identifier, uint16_t msg_size){ - int minimal_msg_lenght = 2; - switch (signal_identifier){ - case AVDTP_SI_GET_CAPABILITIES: - case AVDTP_SI_GET_ALL_CAPABILITIES: - case AVDTP_SI_SET_CONFIGURATION: - case AVDTP_SI_GET_CONFIGURATION: - case AVDTP_SI_START: - case AVDTP_SI_CLOSE: - case AVDTP_SI_ABORT: - case AVDTP_SI_RECONFIGURE: - case AVDTP_SI_OPEN: - minimal_msg_lenght = 3; - break; - default: - break; - } - return msg_size >= minimal_msg_lenght; -} - -void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t * packet, uint16_t size, int offset){ - 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; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid); - return; - } - - switch (connection->signaling_packet.signal_identifier){ - case AVDTP_SI_DISCOVER: - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; - printf(" ACP: AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS\n"); - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS; - avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid); - return; - case AVDTP_SI_GET_CAPABILITIES: - case AVDTP_SI_GET_ALL_CAPABILITIES: - case AVDTP_SI_SET_CONFIGURATION: - case AVDTP_SI_GET_CONFIGURATION: - case AVDTP_SI_START: - case AVDTP_SI_CLOSE: - case AVDTP_SI_ABORT: - case AVDTP_SI_OPEN: - case AVDTP_SI_RECONFIGURE: - connection->query_seid = packet[offset++] >> 2; - stream_endpoint = get_avdtp_stream_endpoint_with_seid(connection->query_seid); - if (!stream_endpoint){ - printf(" ACP: cmd %d - RESPONSE REJECT\n", connection->signaling_packet.signal_identifier); - connection->error_code = BAD_ACP_SEID; - if (connection->signaling_packet.signal_identifier == AVDTP_SI_OPEN){ - connection->error_code = BAD_STATE; - } - - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE; - if (connection->signaling_packet.signal_identifier == AVDTP_SI_RECONFIGURE){ - connection->reject_service_category = connection->query_seid; - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; - } - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid); - return; - } - break; - - case AVDTP_SI_SUSPEND:{ - int i; - printf(" ACP: AVDTP_SI_SUSPEND seids: "); - connection->num_suspended_seids = 0; - - for (i = offset; i < size; i++){ - connection->suspended_seids[connection->num_suspended_seids] = packet[i] >> 2; - offset++; - printf("%d, \n", connection->suspended_seids[connection->num_suspended_seids]); - connection->num_suspended_seids++; - } - - if (connection->num_suspended_seids == 0) { - printf(" ACP: CATEGORY RESPONSE REJECT BAD_ACP_SEID\n"); - connection->error_code = BAD_ACP_SEID; - connection->reject_service_category = connection->query_seid; - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid); - return; - } - // deal with first susspended seid - connection->query_seid = connection->suspended_seids[0]; - stream_endpoint = get_avdtp_stream_endpoint_with_seid(connection->query_seid); - if (!stream_endpoint){ - printf(" ACP: stream_endpoint not found, CATEGORY RESPONSE REJECT BAD_ACP_SEID\n"); - connection->error_code = BAD_ACP_SEID; - connection->reject_service_category = connection->query_seid; - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - connection->num_suspended_seids = 0; - avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid); - return; - } - break; - } - default: - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_GENERAL_REJECT_WITH_ERROR_CODE; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - printf("AVDTP_CMD_MSG signal %d not implemented, general reject\n", connection->signaling_packet.signal_identifier); - avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid); - return; - } - - if (!stream_endpoint) { - return; - } - - if (!avdtp_acceptor_process_chunk(&connection->signaling_packet, packet, size)) return; - - uint16_t packet_size = connection->signaling_packet.size; - connection->signaling_packet.size = 0; - - int request_to_send = 1; - switch (stream_endpoint->acceptor_config_state){ - case AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE: - switch (connection->signaling_packet.signal_identifier){ - case AVDTP_SI_GET_ALL_CAPABILITIES: - printf(" ACP: AVDTP_SI_GET_ALL_CAPABILITIES\n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_ALL_CAPABILITIES; - break; - case AVDTP_SI_GET_CAPABILITIES: - printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES\n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES; - break; - case AVDTP_SI_SET_CONFIGURATION:{ - printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION \n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION; - connection->reject_service_category = 0; - - avdtp_sep_t sep; - sep.seid = connection->signaling_packet.command[offset++] >> 2; - sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+offset, packet_size-offset); - sep.in_use = 1; - - if (connection->error_code){ - printf("fire configuration parsing errors \n"); - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; - break; - } - // find or add sep - int i; - stream_endpoint->remote_sep_index = 0xFF; - for (i=0; i < stream_endpoint->remote_seps_num; i++){ - if (stream_endpoint->remote_seps[i].seid == sep.seid){ - stream_endpoint->remote_sep_index = i; - } - } - printf(" ACP .. seid %d, index %d\n", sep.seid, stream_endpoint->remote_sep_index); - - if (stream_endpoint->remote_sep_index != 0xFF){ - if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].in_use){ - // reject if already configured - connection->error_code = SEP_IN_USE; - // find first registered category and fire the error - connection->reject_service_category = 0; - for (i = 1; i < 9; i++){ - if (get_bit16(sep.configured_service_categories, i)){ - connection->reject_service_category = i; - break; - } - } - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; - } else { - stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep; - printf(" ACP: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); - } - } else { - // add new - printf(" ACP: seid %d not found in %p\n", sep.seid, stream_endpoint); - stream_endpoint->remote_sep_index = stream_endpoint->remote_seps_num; - stream_endpoint->remote_seps_num++; - stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep; - printf(" ACP: add seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); - } - - if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){ - switch (sep.configuration.media_codec.media_codec_type){ - case AVDTP_CODEC_SBC: - avdtp_signaling_emit_media_codec_sbc_configuration(avdtp_sink_callback, connection->con_handle, sep.configuration.media_codec); - break; - default: - avdtp_signaling_emit_media_codec_other_configuration(avdtp_sink_callback, connection->con_handle, sep.configuration.media_codec); - break; - } - } - avdtp_signaling_emit_accept(avdtp_sink_callback, connection->con_handle, connection->signaling_packet.signal_identifier, 0); - break; - } - case AVDTP_SI_RECONFIGURE:{ - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE; - connection->reject_service_category = 0; - - avdtp_sep_t sep; - sep.seid = connection->query_seid; - printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE seid %d\n", sep.seid); - // printf_hexdump(connection->signaling_packet.command, packet_size); - - sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+offset, packet_size-offset); - - if (connection->error_code){ - // fire configuration parsing errors - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; - break; - } - - // find sep or raise error - int i; - stream_endpoint->remote_sep_index = 0xFF; - for (i = 0; i < stream_endpoint->remote_seps_num; i++){ - if (stream_endpoint->remote_seps[i].seid == sep.seid){ - stream_endpoint->remote_sep_index = i; - } - } - - if (stream_endpoint->remote_sep_index == 0xFF){ - printf(" ACP: REJECT AVDTP_SI_RECONFIGURE, BAD_ACP_SEID\n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; - connection->error_code = BAD_ACP_SEID; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - break; - } - stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep; - printf(" ACP: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); - - if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){ - switch (sep.capabilities.media_codec.media_codec_type){ - case AVDTP_CODEC_SBC: - avdtp_signaling_emit_media_codec_sbc_reconfiguration(avdtp_sink_callback, connection->con_handle, sep.capabilities.media_codec); - break; - default: - avdtp_signaling_emit_media_codec_other_reconfiguration(avdtp_sink_callback, connection->con_handle, sep.capabilities.media_codec); - break; - } - } - avdtp_signaling_emit_accept(avdtp_sink_callback, connection->con_handle, connection->signaling_packet.signal_identifier, 0); - break; - } - - case AVDTP_SI_GET_CONFIGURATION: - printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION\n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION; - break; - case AVDTP_SI_OPEN: - if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_CONFIGURED){ - printf(" ACP: REJECT AVDTP_SI_OPEN, BAD_STATE\n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE; - connection->error_code = BAD_STATE; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - break; - } - printf(" ACP: AVDTP_STREAM_ENDPOINT_W2_ANSWER_OPEN_STREAM\n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_OPEN_STREAM; - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED; - break; - case AVDTP_SI_START: - if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_OPENED){ - printf(" ACP: REJECT AVDTP_SI_OPEN, BAD_STATE\n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; - connection->error_code = BAD_STATE; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - break; - } - printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM\n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM; - break; - case AVDTP_SI_CLOSE: - switch (stream_endpoint->state){ - case AVDTP_STREAM_ENDPOINT_OPENED: - case AVDTP_STREAM_ENDPOINT_STREAMING: - printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_CLOSE_STREAM\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CLOSING; - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_CLOSE_STREAM; - break; - default: - printf(" ACP: AVDTP_SI_CLOSE, bad state %d \n", stream_endpoint->state); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE; - connection->error_code = BAD_STATE; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - break; - } - break; - case AVDTP_SI_ABORT: - switch (stream_endpoint->state){ - case AVDTP_STREAM_ENDPOINT_CONFIGURED: - case AVDTP_STREAM_ENDPOINT_CLOSING: - case AVDTP_STREAM_ENDPOINT_OPENED: - case AVDTP_STREAM_ENDPOINT_STREAMING: - printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING; - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM; - break; - default: - printf(" ACP: AVDTP_SI_ABORT, bad state %d \n", stream_endpoint->state); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE; - connection->error_code = BAD_STATE; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - break; - } - break; - case AVDTP_SI_SUSPEND: - printf(" entering AVDTP_SI_SUSPEND\n"); - switch (stream_endpoint->state){ - case AVDTP_STREAM_ENDPOINT_OPENED: - case AVDTP_STREAM_ENDPOINT_STREAMING: - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED; - connection->num_suspended_seids--; - if (connection->num_suspended_seids <= 0){ - printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_SUSPEND_STREAM\n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SUSPEND_STREAM; - } - break; - default: - printf(" ACP: AVDTP_SI_SUSPEND, bad state \n"); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE; - connection->error_code = BAD_STATE; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - break; - } - - //stream_endpoint->state = AVDTP_STREAM_ENDPOINT_SUSPENDING; - //stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_SUSPEND_STREAM; - break; - default: - printf(" ACP: NOT IMPLEMENTED, Reject signal_identifier %02x\n", connection->signaling_packet.signal_identifier); - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_UNKNOWN_CMD; - connection->reject_signal_identifier = connection->signaling_packet.signal_identifier; - break; - } - break; - default: - return; - } - - if (!request_to_send){ - printf(" ACP: NOT IMPLEMENTED\n"); - } - avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid); -} - -static int avdtp_acceptor_send_seps_response(uint16_t cid, uint8_t transaction_label, avdtp_stream_endpoint_t * endpoints){ - uint8_t command[2+2*MAX_NUM_SEPS]; - int pos = 0; - command[pos++] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_RESPONSE_ACCEPT_MSG); - command[pos++] = (uint8_t)AVDTP_SI_DISCOVER; - - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) endpoints); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); - command[pos++] = (stream_endpoint->sep.seid << 2) | (stream_endpoint->sep.in_use<<1); - command[pos++] = (stream_endpoint->sep.media_type << 4) | (stream_endpoint->sep.type << 3); - } - return l2cap_send(cid, command, pos); -} - -static int avdtp_acceptor_send_response_reject_service_category(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t category, uint8_t error_code, uint8_t transaction_label){ - uint8_t command[4]; - command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_RESPONSE_REJECT_MSG); - command[1] = (uint8_t)identifier; - command[2] = category; - command[3] = error_code; - return l2cap_send(cid, command, sizeof(command)); -} - -static int avdtp_acceptor_send_response_general_reject(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t transaction_label){ - uint8_t command[2]; - command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_GENERAL_REJECT_MSG); - command[1] = (uint8_t)identifier; - return l2cap_send(cid, command, sizeof(command)); -} - -static int avdtp_acceptor_send_response_reject(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t transaction_label){ - uint8_t command[2]; - command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_RESPONSE_REJECT_MSG); - command[1] = (uint8_t)identifier; - return l2cap_send(cid, command, sizeof(command)); -} - -static int avdtp_acceptor_send_response_reject_with_error_code(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t error_code, uint8_t transaction_label){ - uint8_t command[3]; - command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_RESPONSE_REJECT_MSG); - command[1] = (uint8_t)identifier; - command[2] = error_code; - return l2cap_send(cid, command, sizeof(command)); -} - -void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection){ - int sent = 1; - - switch (connection->acceptor_connection_state){ - case AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS: - printf(" -> AVDTP_SIGNALING_CONNECTION_OPENED\n"); - connection->state = AVDTP_SIGNALING_CONNECTION_OPENED; - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE; - avdtp_acceptor_send_seps_response(connection->l2cap_signaling_cid, connection->acceptor_transaction_label, (avdtp_stream_endpoint_t *)&stream_endpoints); - break; - case AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE: - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE; - avdtp_acceptor_send_response_reject_with_error_code(connection->l2cap_signaling_cid, connection->reject_signal_identifier, connection->error_code, connection->acceptor_transaction_label); - break; - case AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE: - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE; - avdtp_acceptor_send_response_reject_service_category(connection->l2cap_signaling_cid, connection->reject_signal_identifier, connection->reject_service_category, connection->error_code, connection->acceptor_transaction_label); - break; - case AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_GENERAL_REJECT_WITH_ERROR_CODE: - connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE; - avdtp_acceptor_send_response_general_reject(connection->l2cap_signaling_cid, connection->reject_signal_identifier, connection->acceptor_transaction_label); - default: - sent = 0; - break; - } - if (sent) return; - - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(connection->query_seid); - if (!stream_endpoint) return; - - uint8_t reject_service_category = connection->reject_service_category; - avdtp_signal_identifier_t reject_signal_identifier = connection->reject_signal_identifier; - uint8_t error_code = connection->error_code; - uint16_t cid = stream_endpoint->connection ? stream_endpoint->connection->l2cap_signaling_cid : connection->l2cap_signaling_cid; - uint8_t trid = stream_endpoint->connection ? stream_endpoint->connection->acceptor_transaction_label : connection->acceptor_transaction_label; - - avdtp_acceptor_stream_endpoint_state_t acceptor_config_state = stream_endpoint->acceptor_config_state; - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE; - uint8_t * out_buffer; - uint16_t pos; - - int status = 0; - switch (acceptor_config_state){ - case AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE: - break; - case AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES: - 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_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"); - printf(" -> AVDTP_STREAM_ENDPOINT_CONFIGURED\n"); - stream_endpoint->connection = connection; - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED; - avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_SET_CONFIGURATION); - break; - case AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE: - printf(" ACP: DONE \n"); - avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_RECONFIGURE); - break; - - case AVDTP_ACCEPTOR_W2_ANSWER_GET_CONFIGURATION:{ - avdtp_sep_t sep = stream_endpoint->remote_seps[stream_endpoint->remote_sep_index]; - avdtp_prepare_capabilities(&connection->signaling_packet, trid, sep.configured_service_categories, sep.configuration, 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; - break; - case AVDTP_ACCEPTOR_W2_ANSWER_OPEN_STREAM: - printf(" ACP: DONE\n"); - avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_OPEN); - break; - case AVDTP_ACCEPTOR_W2_ANSWER_START_STREAM: - printf(" ACP: DONE \n"); - printf(" -> AVDTP_STREAM_ENDPOINT_STREAMING \n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING; - avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_START); - break; - case AVDTP_ACCEPTOR_W2_ANSWER_CLOSE_STREAM: - printf(" ACP: DONE\n"); - avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_CLOSE); - break; - case AVDTP_ACCEPTOR_W2_ANSWER_ABORT_STREAM: - printf(" ACP: DONE\n"); - avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_ABORT); - break; - case AVDTP_ACCEPTOR_W2_ANSWER_SUSPEND_STREAM: - printf(" ACP: DONE\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED; - avdtp_acceptor_send_accept_response(cid, trid, AVDTP_SI_SUSPEND); - break; - case AVDTP_ACCEPTOR_W2_REJECT_UNKNOWN_CMD: - status = 1; - printf(" ACP: DONE REJECT\n"); - connection->reject_signal_identifier = 0; - avdtp_acceptor_send_response_reject(cid, reject_signal_identifier, trid); - break; - case AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE: - status = 1; - printf(" ACP: DONE REJECT CATEGORY\n"); - connection->reject_service_category = 0; - avdtp_acceptor_send_response_reject_service_category(cid, reject_signal_identifier, reject_service_category, error_code, trid); - break; - - case AVDTP_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE: - status = 1; - printf(" ACP: DONE REJECT\n"); - connection->reject_signal_identifier = 0; - connection->error_code = 0; - avdtp_acceptor_send_response_reject_with_error_code(cid, reject_signal_identifier, error_code, trid); - break; - default: - status = 0; - printf(" ACP: NOT IMPLEMENTED\n"); - sent = 0; - } - avdtp_signaling_emit_accept(avdtp_sink_callback, connection->con_handle, connection->signaling_packet.signal_identifier, status); - - // check fragmentation - if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){ - avdtp_sink_request_can_send_now_acceptor(connection, connection->l2cap_signaling_cid); - } -} diff --git a/test/avdtp/avdtp_acceptor.h b/test/avdtp/avdtp_acceptor.h deleted file mode 100644 index 80d703020..000000000 --- a/test/avdtp/avdtp_acceptor.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - -/* - * avdtp_acp.h - * - * Audio/Video Distribution Transport Protocol - Acceptor Role - * - */ - -#ifndef __AVDTP_ACP_H -#define __AVDTP_ACP_H - -#include - -#if defined __cplusplus -extern "C" { -#endif - -void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t *packet, uint16_t size, int offset); -void avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection); - -#if defined __cplusplus -} -#endif - -#endif // __AVDTP_ACP_H \ No newline at end of file diff --git a/test/avdtp/avdtp_initiator.c b/test/avdtp/avdtp_initiator.c deleted file mode 100644 index 61b5da2e0..000000000 --- a/test/avdtp/avdtp_initiator.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - - -#include -#include -#include -#include -#include - -#include "btstack.h" -#include "avdtp.h" -#include "avdtp_util.h" -#include "avdtp_initiator.h" - - -static int avdtp_initiator_send_signaling_cmd(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t transaction_label){ - uint8_t command[2]; - command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_CMD_MSG); - command[1] = (uint8_t)identifier; - return l2cap_send(cid, command, sizeof(command)); -} - -static int avdtp_initiator_send_signaling_cmd_with_seid(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t transaction_label, uint8_t sep_id){ - uint8_t command[3]; - command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_CMD_MSG); - command[1] = (uint8_t)identifier; - command[2] = sep_id << 2; - return l2cap_send(cid, command, sizeof(command)); -} - -static void avdtp_signaling_emit_media_codec_capability(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){ - if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){ - switch (sep.capabilities.media_codec.media_codec_type){ - case AVDTP_CODEC_SBC: - avdtp_signaling_emit_media_codec_sbc_capability(callback, con_handle, sep.capabilities.media_codec); - break; - default: - avdtp_signaling_emit_media_codec_other_capability(callback, con_handle, sep.capabilities.media_codec); - break; - } - } -} - -static void avdtp_signaling_emit_media_codec_configuration(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){ - if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC)){ - switch (sep.capabilities.media_codec.media_codec_type){ - case AVDTP_CODEC_SBC: - avdtp_signaling_emit_media_codec_sbc_configuration(callback, con_handle, sep.capabilities.media_codec); - break; - default: - avdtp_signaling_emit_media_codec_other_configuration(callback, con_handle, sep.capabilities.media_codec); - break; - } - } -} - -void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_t *packet, uint16_t size, int offset){ - int status = 0; - avdtp_stream_endpoint_t * stream_endpoint = NULL; - uint8_t remote_sep_index; - avdtp_sep_t sep; - if (connection->initiator_connection_state == AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER) { - connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE; - } else { - stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(connection->acp_seid); - if (!stream_endpoint){ - stream_endpoint = get_avdtp_stream_endpoint_with_seid(connection->int_seid); - } - if (!stream_endpoint) return; - sep.seid = connection->acp_seid; - - printf("avdtp_initiator_stream_config_subsm int seid %d, acp seid %d, ident %d \n", connection->int_seid, connection->acp_seid, connection->signaling_packet.signal_identifier); - if (stream_endpoint->initiator_config_state != AVDTP_INITIATOR_W4_ANSWER) return; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE; - } - - switch (connection->signaling_packet.message_type){ - case AVDTP_RESPONSE_ACCEPT_MSG: - printf(" INT: AVDTP_RESPONSE_ACCEPT_MSG: "); - switch (connection->signaling_packet.signal_identifier){ - case AVDTP_SI_DISCOVER:{ - printf("AVDTP_SI_DISCOVER\n"); - if (connection->signaling_packet.transaction_label != connection->initiator_transaction_label){ - printf(" unexpected transaction label, got %d, expected %d\n", connection->signaling_packet.transaction_label, connection->initiator_transaction_label); - status = BAD_HEADER_FORMAT; - break; - } - - if (size == 3){ - printf(" ERROR code %02x\n", packet[offset]); - status = packet[offset]; - break; - } - - int i; - for (i = offset; i < size; i += 2){ - sep.seid = packet[i] >> 2; - offset++; - if (sep.seid < 0x01 || sep.seid > 0x3E){ - printf(" invalid sep id\n"); - status = BAD_ACP_SEID; - break; - } - sep.in_use = (packet[i] >> 1) & 0x01; - sep.media_type = (avdtp_media_type_t)(packet[i+1] >> 4); - sep.type = (avdtp_sep_type_t)((packet[i+1] >> 3) & 0x01); - avdtp_signaling_emit_sep(avdtp_sink_callback, connection->con_handle, sep); - } - break; - } - - case AVDTP_SI_GET_CAPABILITIES: - case AVDTP_SI_GET_ALL_CAPABILITIES: - printf("AVDTP_SI_GET(_ALL)_CAPABILITIES\n"); - sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, packet+offset, size-offset); - avdtp_signaling_emit_media_codec_capability(avdtp_sink_callback, connection->con_handle, sep); - break; - - case AVDTP_SI_GET_CONFIGURATION: - printf("AVDTP_SI_GET_CONFIGURATION\n"); - sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, packet+offset, size-offset); - - avdtp_signaling_emit_media_codec_configuration(avdtp_sink_callback, connection->con_handle, sep); - break; - - case AVDTP_SI_RECONFIGURE: - printf("AVDTP_SI_RECONFIGURE\n"); - sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+4, connection->signaling_packet.size-4); - // TODO check if configuration is supported - - remote_sep_index = avdtp_get_index_of_remote_stream_endpoint_with_seid(stream_endpoint, sep.seid); - if (remote_sep_index != 0xFF){ - stream_endpoint->remote_sep_index = remote_sep_index; - stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep; - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED; - printf(" INT: update seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); - } - break; - - case AVDTP_SI_SET_CONFIGURATION:{ - printf("AVDTP_SI_SET_CONFIGURATION\n"); - sep.configured_service_categories = connection->remote_capabilities_bitmap; - sep.configuration = connection->remote_capabilities; - sep.in_use = 1; - // TODO check if configuration is supported - - // find or add sep - remote_sep_index = avdtp_get_index_of_remote_stream_endpoint_with_seid(stream_endpoint, sep.seid); - if (remote_sep_index != 0xFF){ - stream_endpoint->remote_sep_index = remote_sep_index; - } else { - stream_endpoint->remote_sep_index = stream_endpoint->remote_seps_num; - stream_endpoint->remote_seps_num++; - } - stream_endpoint->remote_seps[stream_endpoint->remote_sep_index] = sep; - printf(" INT: configured seid %d, to %p\n", stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CONFIGURED; - break; - } - - case AVDTP_SI_OPEN: - printf("AVDTP_SI_OPEN\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED; - break; - case AVDTP_SI_START: - printf("AVDTP_SI_START\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING; - break; - case AVDTP_SI_SUSPEND: - printf("AVDTP_SI_SUSPEND\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED; - break; - case AVDTP_SI_CLOSE: - printf("AVDTP_SI_CLOSE\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_CLOSING; - break; - case AVDTP_SI_ABORT: - printf("AVDTP_SI_ABORT\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING; - break; - default: - status = 1; - printf(" AVDTP_RESPONSE_ACCEPT_MSG, signal %d not implemented\n", connection->signaling_packet.signal_identifier); - break; - } - break; - case AVDTP_RESPONSE_REJECT_MSG: - printf(" AVDTP_RESPONSE_REJECT_MSG signal %d\n", connection->signaling_packet.signal_identifier); - avdtp_signaling_emit_reject(avdtp_sink_callback, connection->con_handle, connection->signaling_packet.signal_identifier); - return; - case AVDTP_GENERAL_REJECT_MSG: - printf(" AVDTP_GENERAL_REJECT_MSG signal %d\n", connection->signaling_packet.signal_identifier); - avdtp_signaling_emit_general_reject(avdtp_sink_callback, connection->con_handle, connection->signaling_packet.signal_identifier); - return; - default: - break; - } - connection->initiator_transaction_label++; - connection->int_seid = 0; - connection->acp_seid = 0; - avdtp_signaling_emit_accept(avdtp_sink_callback, connection->con_handle, connection->signaling_packet.signal_identifier, status); -} - -void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection){ - int sent = 1; - switch (connection->initiator_connection_state){ - case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS: - printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS\n"); - connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER; - avdtp_initiator_send_signaling_cmd(connection->l2cap_signaling_cid, AVDTP_SI_DISCOVER, connection->initiator_transaction_label); - break; - case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES: - printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES\n"); - connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER; - avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CAPABILITIES, connection->initiator_transaction_label, connection->acp_seid); - break; - case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES: - printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES\n"); - connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER; - avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_ALL_CAPABILITIES, connection->initiator_transaction_label, connection->acp_seid); - break; - case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION: - printf(" INT: AVDTP_INITIATOR_W4_GET_CONFIGURATION\n"); - connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W4_ANSWER; - avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_GET_CONFIGURATION, connection->initiator_transaction_label, connection->acp_seid); - break; - default: - sent = 0; - break; - } - - if (sent) return; - sent = 1; - avdtp_stream_endpoint_t * stream_endpoint = NULL; - - printf(" run int seid %d, acp seid %d\n", connection->int_seid, connection->acp_seid); - - stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(connection->acp_seid); - if (!stream_endpoint){ - stream_endpoint = get_avdtp_stream_endpoint_with_seid(connection->int_seid); - } - if (!stream_endpoint) return; - - avdtp_initiator_stream_endpoint_state_t stream_endpoint_state = stream_endpoint->initiator_config_state; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W4_ANSWER; - - switch (stream_endpoint_state){ - case AVDTP_INITIATOR_W2_SET_CONFIGURATION: - case AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID:{ - printf(" INT: AVDTP_INITIATOR_W2_(RE)CONFIGURATION bitmap, int seid %d, acp seid %d\n", connection->int_seid, connection->acp_seid); - 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->acp_seid; - connection->signaling_packet.int_seid = connection->int_seid; - - connection->signaling_packet.signal_identifier = AVDTP_SI_SET_CONFIGURATION; - - if (stream_endpoint_state == AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID){ - connection->signaling_packet.signal_identifier = AVDTP_SI_RECONFIGURE; - } - - avdtp_prepare_capabilities(&connection->signaling_packet, connection->initiator_transaction_label, connection->remote_capabilities_bitmap, connection->remote_capabilities, connection->signaling_packet.signal_identifier); - 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){ - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_FRAGMENTATED_COMMAND; - printf(" INT: fragmented\n"); - } - l2cap_send_prepared(connection->l2cap_signaling_cid, pos); - break; - } - case AVDTP_INITIATOR_FRAGMENTATED_COMMAND:{ - 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){ - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_FRAGMENTATED_COMMAND; - printf(" INT: fragmented\n"); - } - l2cap_send_prepared(connection->l2cap_signaling_cid, pos); - break; - } - case AVDTP_INITIATOR_W2_MEDIA_CONNECT: - printf(" INT: AVDTP_INITIATOR_W4_L2CAP_FOR_MEDIA_CONNECTED\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED; - avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_OPEN, connection->initiator_transaction_label, connection->acp_seid); - break; - case AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID: - printf(" INT: AVDTP_INITIATOR_W4_SUSPEND_STREAM_WITH_SEID\n"); - avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_SUSPEND, connection->initiator_transaction_label, connection->acp_seid); - break; - case AVDTP_INITIATOR_W2_STREAMING_START: - printf(" INT: AVDTP_INITIATOR_W4_STREAMING_START\n"); - avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_START, connection->initiator_transaction_label, connection->acp_seid); - break; - case AVDTP_INITIATOR_W2_STREAMING_STOP: - printf(" INT: AVDTP_INITIATOR_W4_STREAMING_STOP\n"); - avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_CLOSE, connection->initiator_transaction_label, connection->acp_seid); - break; - case AVDTP_INITIATOR_W2_STREAMING_ABORT: - printf(" INT: AVDTP_INITIATOR_W4_STREAMING_ABORT\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_ABORTING; - avdtp_initiator_send_signaling_cmd_with_seid(connection->l2cap_signaling_cid, AVDTP_SI_ABORT, connection->initiator_transaction_label, connection->acp_seid); - break; - default: - break; - } - - // check fragmentation - if (connection->signaling_packet.packet_type != AVDTP_SINGLE_PACKET && connection->signaling_packet.packet_type != AVDTP_END_PACKET){ - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); - } -} diff --git a/test/avdtp/avdtp_initiator.h b/test/avdtp/avdtp_initiator.h deleted file mode 100644 index 1ad211be7..000000000 --- a/test/avdtp/avdtp_initiator.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - -/* - * avdtp_int.h - * - * Audio/Video Distribution Transport Protocol - Initiator Role - * - */ - -#ifndef __AVDTP_INT_H -#define __AVDTP_INT_H - -#include - -#if defined __cplusplus -extern "C" { -#endif - -void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_t *packet, uint16_t size, int offset); -void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection); - -#if defined __cplusplus -} -#endif - -#endif // __AVDTP_INT_H \ No newline at end of file diff --git a/test/avdtp/avdtp_sink.c b/test/avdtp/avdtp_sink.c deleted file mode 100644 index e724ab086..000000000 --- a/test/avdtp/avdtp_sink.c +++ /dev/null @@ -1,901 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - - -#include -#include -#include -#include -#include - -#include "btstack.h" -#include "avdtp.h" -#include "avdtp_sink.h" -#include "avdtp_util.h" -#include "avdtp_initiator.h" -#include "avdtp_acceptor.h" - -static const char * default_avdtp_sink_service_name = "BTstack AVDTP Sink Service"; -static const char * default_avdtp_sink_service_provider_name = "BTstack AVDTP Sink Service Provider"; - -// TODO list of devices -static btstack_linked_list_t avdtp_connections; -static uint16_t stream_endpoints_id_counter; - -btstack_linked_list_t stream_endpoints; -btstack_packet_handler_t avdtp_sink_callback; - - -static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); - -static void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size); - -void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){ - uint8_t* attribute; - de_create_sequence(service); - - // 0x0000 "Service Record Handle" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); - de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle); - - // 0x0001 "Service Class ID List" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); - attribute = de_push_sequence(service); - { - de_add_number(attribute, DE_UUID, DE_SIZE_16, AUDIO_SINK_GROUP); - } - de_pop_sequence(service, attribute); - - // 0x0004 "Protocol Descriptor List" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); - attribute = de_push_sequence(service); - { - uint8_t* l2cpProtocol = de_push_sequence(attribute); - { - de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, SDP_L2CAPProtocol); - de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, PSM_AVDTP); - } - de_pop_sequence(attribute, l2cpProtocol); - - uint8_t* avProtocol = de_push_sequence(attribute); - { - de_add_number(avProtocol, DE_UUID, DE_SIZE_16, PSM_AVDTP); // avProtocol_service - de_add_number(avProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version - } - de_pop_sequence(attribute, avProtocol); - } - de_pop_sequence(service, attribute); - - // 0x0005 "Public Browse Group" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); // public browse group - attribute = de_push_sequence(service); - { - de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_PublicBrowseGroup); - } - de_pop_sequence(service, attribute); - - // 0x0009 "Bluetooth Profile Descriptor List" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); - attribute = de_push_sequence(service); - { - uint8_t *a2dProfile = de_push_sequence(attribute); - { - de_add_number(a2dProfile, DE_UUID, DE_SIZE_16, ADVANCED_AUDIO_DISTRIBUTION); - de_add_number(a2dProfile, DE_UINT, DE_SIZE_16, 0x0103); - } - de_pop_sequence(attribute, a2dProfile); - } - de_pop_sequence(service, attribute); - - - // 0x0100 "Service Name" - de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); - if (service_name){ - de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name); - } else { - de_add_data(service, DE_STRING, strlen(default_avdtp_sink_service_name), (uint8_t *) default_avdtp_sink_service_name); - } - - // 0x0100 "Provider Name" - de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102); - if (service_provider_name){ - de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name); - } else { - de_add_data(service, DE_STRING, strlen(default_avdtp_sink_service_provider_name), (uint8_t *) default_avdtp_sink_service_provider_name); - } - - // 0x0311 "Supported Features" - de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311); - de_add_number(service, DE_UINT, DE_SIZE_16, supported_features); -} - - -static avdtp_connection_t * avdtp_sink_create_connection(bd_addr_t remote_addr){ - avdtp_connection_t * connection = btstack_memory_avdtp_connection_get(); - memset(connection, 0, sizeof(avdtp_connection_t)); - connection->state = AVDTP_SIGNALING_CONNECTION_IDLE; - connection->initiator_transaction_label++; - memcpy(connection->remote_addr, remote_addr, 6); - btstack_linked_list_add(&avdtp_connections, (btstack_linked_item_t *) connection); - return connection; -} - -avdtp_stream_endpoint_t * avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type){ - avdtp_stream_endpoint_t * stream_endpoint = btstack_memory_avdtp_stream_endpoint_get(); - memset(stream_endpoint, 0, sizeof(avdtp_stream_endpoint_t)); - stream_endpoints_id_counter++; - stream_endpoint->sep.seid = stream_endpoints_id_counter; - stream_endpoint->sep.media_type = media_type; - stream_endpoint->sep.type = sep_type; - btstack_linked_list_add(&stream_endpoints, (btstack_linked_item_t *) stream_endpoint); - return stream_endpoint; -} - -void avdtp_sink_register_media_transport_category(uint8_t seid){ - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid); - if (!stream_endpoint){ - log_error("avdtp_sink_register_media_transport_category: stream endpoint with seid %d is not registered", seid); - return; - } - uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_TRANSPORT, 1); - stream_endpoint->sep.registered_service_categories = bitmap; - printf("registered services AVDTP_MEDIA_TRANSPORT(%d) %02x\n", AVDTP_MEDIA_TRANSPORT, stream_endpoint->sep.registered_service_categories); -} - -void avdtp_sink_register_reporting_category(uint8_t seid){ - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid); - if (!stream_endpoint){ - log_error("avdtp_sink_register_media_transport_category: stream endpoint with seid %d is not registered", seid); - return; - } - uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_REPORTING, 1); - stream_endpoint->sep.registered_service_categories = bitmap; -} - -void avdtp_sink_register_delay_reporting_category(uint8_t seid){ - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid); - if (!stream_endpoint){ - log_error("avdtp_sink_register_media_transport_category: stream endpoint with seid %d is not registered", seid); - return; - } - uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_DELAY_REPORTING, 1); - stream_endpoint->sep.registered_service_categories = bitmap; -} - -void avdtp_sink_register_recovery_category(uint8_t seid, uint8_t maximum_recovery_window_size, uint8_t maximum_number_media_packets){ - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid); - if (!stream_endpoint){ - log_error("avdtp_sink_register_media_transport_category: stream endpoint with seid %d is not registered", seid); - return; - } - uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_RECOVERY, 1); - stream_endpoint->sep.registered_service_categories = bitmap; - stream_endpoint->sep.capabilities.recovery.recovery_type = 0x01; // 0x01 = RFC2733 - stream_endpoint->sep.capabilities.recovery.maximum_recovery_window_size = maximum_recovery_window_size; - stream_endpoint->sep.capabilities.recovery.maximum_number_media_packets = maximum_number_media_packets; -} - -void avdtp_sink_register_content_protection_category(uint8_t seid, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len){ - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid); - if (!stream_endpoint){ - log_error("avdtp_sink_register_media_transport_category: stream endpoint with seid %d is not registered", seid); - return; - } - uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_CONTENT_PROTECTION, 1); - stream_endpoint->sep.registered_service_categories = bitmap; - stream_endpoint->sep.capabilities.content_protection.cp_type = cp_type; - stream_endpoint->sep.capabilities.content_protection.cp_type_value = cp_type_value; - stream_endpoint->sep.capabilities.content_protection.cp_type_value_len = cp_type_value_len; -} - -void avdtp_sink_register_header_compression_category(uint8_t seid, uint8_t back_ch, uint8_t media, uint8_t recovery){ - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid); - if (!stream_endpoint){ - log_error("avdtp_sink_register_media_transport_category: stream endpoint with seid %d is not registered", seid); - return; - } - uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_HEADER_COMPRESSION, 1); - stream_endpoint->sep.registered_service_categories = bitmap; - stream_endpoint->sep.capabilities.header_compression.back_ch = back_ch; - stream_endpoint->sep.capabilities.header_compression.media = media; - stream_endpoint->sep.capabilities.header_compression.recovery = recovery; -} - -void avdtp_sink_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, const uint8_t * media_codec_info, uint16_t media_codec_info_len){ - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid); - if (!stream_endpoint){ - log_error("avdtp_sink_register_media_transport_category: stream endpoint with seid %d is not registered", seid); - return; - } - uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_CODEC, 1); - stream_endpoint->sep.registered_service_categories = bitmap; - printf("registered services AVDTP_MEDIA_CODEC(%d) %02x\n", AVDTP_MEDIA_CODEC, stream_endpoint->sep.registered_service_categories); - stream_endpoint->sep.capabilities.media_codec.media_type = media_type; - stream_endpoint->sep.capabilities.media_codec.media_codec_type = media_codec_type; - stream_endpoint->sep.capabilities.media_codec.media_codec_information = media_codec_info; - stream_endpoint->sep.capabilities.media_codec.media_codec_information_len = media_codec_info_len; -} - -void avdtp_sink_register_multiplexing_category(uint8_t seid, uint8_t fragmentation){ - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_for_seid(seid); - if (!stream_endpoint){ - log_error("avdtp_sink_register_media_transport_category: stream endpoint with seid %d is not registered", seid); - return; - } - uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MULTIPLEXING, 1); - stream_endpoint->sep.registered_service_categories = bitmap; - stream_endpoint->sep.capabilities.multiplexing_mode.fragmentation = fragmentation; -} - -// // media, reporting. recovery -// void avdtp_sink_register_media_transport_identifier_for_multiplexing_category(uint8_t seid, uint8_t fragmentation){ - -// } - - -static avdtp_connection_t * get_avdtp_connection_for_bd_addr(bd_addr_t addr){ - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &avdtp_connections); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_connection_t * connection = (avdtp_connection_t *)btstack_linked_list_iterator_next(&it); - if (memcmp(addr, connection->remote_addr, 6) != 0) continue; - return connection; - } - return NULL; -} - -static avdtp_connection_t * get_avdtp_connection_for_con_handle(hci_con_handle_t con_handle){ - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &avdtp_connections); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_connection_t * connection = (avdtp_connection_t *)btstack_linked_list_iterator_next(&it); - if (connection->con_handle != con_handle) continue; - return connection; - } - return NULL; -} - -static avdtp_connection_t * get_avdtp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid){ - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &avdtp_connections); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_connection_t * connection = (avdtp_connection_t *)btstack_linked_list_iterator_next(&it); - if (connection->l2cap_signaling_cid != l2cap_cid) continue; - return connection; - } - return NULL; -} - -static avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_for_l2cap_cid(uint16_t l2cap_cid){ - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &stream_endpoints); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); - if (stream_endpoint->l2cap_media_cid == l2cap_cid){ - return stream_endpoint; - } - if (stream_endpoint->l2cap_reporting_cid == l2cap_cid){ - return stream_endpoint; - } - if (stream_endpoint->l2cap_recovery_cid == l2cap_cid){ - return stream_endpoint; - } - } - return NULL; -} - -/* START: tracking can send now requests pro l2cap cid */ -static void avdtp_sink_handle_can_send_now(avdtp_connection_t * connection, uint16_t l2cap_cid){ - if (connection->wait_to_send_acceptor){ - connection->wait_to_send_acceptor = 0; - avdtp_acceptor_stream_config_subsm_run(connection); - } else if (connection->wait_to_send_initiator){ - connection->wait_to_send_initiator = 0; - avdtp_initiator_stream_config_subsm_run(connection); - } else if (connection->wait_to_send_self){ - connection->wait_to_send_self = 0; - if (connection->disconnect){ - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &stream_endpoints); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); - if (stream_endpoint->connection == connection){ - if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_OPENED && stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_DISCONNECTED){ - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_DISCONNECTED; - avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid); - l2cap_disconnect(stream_endpoint->l2cap_media_cid, 0); - return; - } - } - } - connection->disconnect = 0; - connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED; - l2cap_disconnect(connection->l2cap_signaling_cid, 0); - return; - } - } - - // re-register - int more_to_send = connection->wait_to_send_acceptor || connection->wait_to_send_initiator || connection->wait_to_send_self; - if (more_to_send){ - l2cap_request_can_send_now_event(l2cap_cid); - } -} - - -/* END: tracking can send now requests pro l2cap cid */ -// TODO remove -static void handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t * connection, uint8_t *packet, uint16_t size){ - int offset = avdtp_read_signaling_header(&connection->signaling_packet, packet, size); - switch (connection->signaling_packet.message_type){ - case AVDTP_CMD_MSG: - avdtp_acceptor_stream_config_subsm(connection, packet, size, offset); - break; - default: - avdtp_initiator_stream_config_subsm(connection, packet, size, offset); - break; - } -} - -static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t packet_type, uint8_t event, uint8_t *packet, uint16_t size){ - uint16_t local_cid; - switch (packet_type){ - case L2CAP_DATA_PACKET:{ - int offset = avdtp_read_signaling_header(&connection->signaling_packet, packet, size); - if (connection->signaling_packet.message_type == AVDTP_CMD_MSG){ - avdtp_acceptor_stream_config_subsm(connection, packet, size, offset); - } else { - avdtp_initiator_stream_config_subsm(connection, packet, size, offset); - } - break; - } - case HCI_EVENT_PACKET: - switch (event){ - case L2CAP_EVENT_CHANNEL_OPENED: - if (stream_endpoint->l2cap_media_cid == 0){ - if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED) return; - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED; - stream_endpoint->connection = connection; - stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet);; - printf(" -> AVDTP_STREAM_ENDPOINT_OPENED, stream endpoint %p, connection %p\n", stream_endpoint, connection); - break; - } - break; - case L2CAP_EVENT_CHANNEL_CLOSED: - local_cid = l2cap_event_channel_closed_get_local_cid(packet); - if (stream_endpoint->l2cap_media_cid == local_cid){ - stream_endpoint->l2cap_media_cid = 0; - printf(" -> L2CAP_EVENT_CHANNEL_CLOSED: AVDTP_STREAM_ENDPOINT_IDLE\n"); - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE; - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE; - stream_endpoint->remote_seps_num = 0; - memset(stream_endpoint->remote_seps, 0, sizeof(avdtp_sep_t)*MAX_NUM_SEPS); - stream_endpoint->remote_sep_index = 0; - break; - } - if (stream_endpoint->l2cap_recovery_cid == local_cid){ - log_info(" -> L2CAP_EVENT_CHANNEL_CLOSED recovery cid 0x%0x", local_cid); - stream_endpoint->l2cap_recovery_cid = 0; - break; - } - - if (stream_endpoint->l2cap_reporting_cid == local_cid){ - log_info("L2CAP_EVENT_CHANNEL_CLOSED reporting cid 0x%0x", local_cid); - stream_endpoint->l2cap_reporting_cid = 0; - break; - } - break; - default: - break; - } - break; - default: - break; - } -} - -static void avdtp_initialize_stream_endpoint(avdtp_stream_endpoint_t * stream_endpoint){ - stream_endpoint->connection = NULL; - stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE; - stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE; - stream_endpoint->remote_sep_index = 0; - stream_endpoint->media_disconnect = 0; - stream_endpoint->remote_seps_num = 0; - stream_endpoint->sep.in_use = 0; - memset(stream_endpoint->remote_seps, 0, sizeof(stream_endpoint->remote_seps)); - stream_endpoint->remote_sep_index = 0; -} - -static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ - bd_addr_t event_addr; - hci_con_handle_t con_handle; - uint16_t psm; - uint16_t local_cid; - avdtp_stream_endpoint_t * stream_endpoint = NULL; - avdtp_connection_t * connection = NULL; - - switch (packet_type) { - case L2CAP_DATA_PACKET: - connection = get_avdtp_connection_for_l2cap_signaling_cid(channel); - if (connection){ - handle_l2cap_data_packet_for_signaling_connection(connection, packet, size); - break; - } - - stream_endpoint = get_avdtp_stream_endpoint_for_l2cap_cid(channel); - if (!stream_endpoint){ - if (!connection) break; - handle_l2cap_data_packet_for_signaling_connection(connection, packet, size); - break; - } - - if (channel == stream_endpoint->connection->l2cap_signaling_cid){ - stream_endpoint_state_machine(stream_endpoint->connection, stream_endpoint, L2CAP_DATA_PACKET, 0, packet, size); - break; - } - - if (channel == stream_endpoint->l2cap_media_cid){ - (*handle_media_data)(stream_endpoint, packet, size); - break; - } - - if (channel == stream_endpoint->l2cap_reporting_cid){ - // TODO - printf("L2CAP_DATA_PACKET for reporting: NOT IMPLEMENTED\n"); - } else if (channel == stream_endpoint->l2cap_recovery_cid){ - // TODO - printf("L2CAP_DATA_PACKET for recovery: NOT IMPLEMENTED\n"); - } else { - log_error("avdtp packet handler L2CAP_DATA_PACKET: local cid 0x%02x not found", channel); - } - break; - - case HCI_EVENT_PACKET: - switch (hci_event_packet_get_type(packet)) { - case L2CAP_EVENT_INCOMING_CONNECTION: - l2cap_event_incoming_connection_get_address(packet, event_addr); - local_cid = l2cap_event_incoming_connection_get_local_cid(packet); - - connection = get_avdtp_connection_for_bd_addr(event_addr); - if (!connection){ - connection = avdtp_sink_create_connection(event_addr); - connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED; - l2cap_accept_connection(local_cid); - break; - } - - stream_endpoint = get_avdtp_stream_endpoint_for_seid(connection->query_seid); - if (!stream_endpoint) { - printf("L2CAP_EVENT_INCOMING_CONNECTION no streamendpoint found for seid %d\n", connection->query_seid); - break; - } - - if (stream_endpoint->l2cap_media_cid == 0){ - if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED) break; - l2cap_accept_connection(local_cid); - break; - } - break; - - case L2CAP_EVENT_CHANNEL_OPENED: - // inform about new l2cap connection - l2cap_event_channel_opened_get_address(packet, event_addr); - - if (l2cap_event_channel_opened_get_status(packet)){ - log_error("L2CAP connection to connection %s failed. status code 0x%02x", - bd_addr_to_str(event_addr), l2cap_event_channel_opened_get_status(packet)); - break; - } - psm = l2cap_event_channel_opened_get_psm(packet); - if (psm != PSM_AVDTP){ - log_error("unexpected PSM - Not implemented yet, avdtp sink: L2CAP_EVENT_CHANNEL_OPENED"); - return; - } - - con_handle = l2cap_event_channel_opened_get_handle(packet); - local_cid = l2cap_event_channel_opened_get_local_cid(packet); - - // printf("L2CAP_EVENT_CHANNEL_OPENED: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n", - // bd_addr_to_str(event_addr), con_handle, psm, local_cid, l2cap_event_channel_opened_get_remote_cid(packet)); - - if (psm != PSM_AVDTP) break; - - connection = get_avdtp_connection_for_bd_addr(event_addr); - if (!connection) break; - - if (connection->l2cap_signaling_cid == 0) { - if (connection->state != AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED) break; - connection->l2cap_signaling_cid = local_cid; - connection->con_handle = con_handle; - connection->query_seid = 0; - connection->state = AVDTP_SIGNALING_CONNECTION_OPENED; - printf(" -> AVDTP_SIGNALING_CONNECTION_OPENED, connection %p\n", connection); - avdtp_signaling_emit_connection_established(avdtp_sink_callback, con_handle, event_addr, 0); - break; - } - - stream_endpoint = get_avdtp_stream_endpoint_for_seid(connection->query_seid); - if (!stream_endpoint){ - printf("L2CAP_EVENT_CHANNEL_OPENED: stream_endpoint not found"); - return; - } - stream_endpoint_state_machine(connection, stream_endpoint, HCI_EVENT_PACKET, L2CAP_EVENT_CHANNEL_OPENED, packet, size); - break; - - case L2CAP_EVENT_CHANNEL_CLOSED: - // data: event (8), len(8), channel (16) - local_cid = l2cap_event_channel_closed_get_local_cid(packet); - connection = get_avdtp_connection_for_l2cap_signaling_cid(local_cid); - printf(" -> L2CAP_EVENT_CHANNEL_CLOSED signaling cid 0x%0x\n", local_cid); - - if (connection){ - printf(" -> AVDTP_STREAM_ENDPOINT_IDLE, connection closed\n"); - btstack_linked_list_remove(&avdtp_connections, (btstack_linked_item_t*) connection); - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &stream_endpoints); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_stream_endpoint_t * _stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); - avdtp_initialize_stream_endpoint(_stream_endpoint); - } - break; - } - - stream_endpoint = get_avdtp_stream_endpoint_for_l2cap_cid(local_cid); - if (!stream_endpoint) return; - - stream_endpoint_state_machine(connection, stream_endpoint, HCI_EVENT_PACKET, L2CAP_EVENT_CHANNEL_CLOSED, packet, size); - break; - - case HCI_EVENT_DISCONNECTION_COMPLETE: - break; - - case L2CAP_EVENT_CAN_SEND_NOW: - connection = get_avdtp_connection_for_l2cap_signaling_cid(channel); - if (!connection) { - stream_endpoint = get_avdtp_stream_endpoint_for_l2cap_cid(channel); - if (!stream_endpoint->connection) break; - connection = stream_endpoint->connection; - } - avdtp_sink_handle_can_send_now(connection, channel); - break; - default: - printf("unknown HCI event type %02x\n", hci_event_packet_get_type(packet)); - break; - } - break; - - default: - // other packet type - break; - } -} - -// TODO: find out which security level is needed, and replace LEVEL_0 in avdtp_sink_init -void avdtp_sink_init(void){ - stream_endpoints = NULL; - avdtp_connections = NULL; - stream_endpoints_id_counter = 0; - l2cap_register_service(&packet_handler, PSM_AVDTP, 0xffff, LEVEL_0); -} - -void avdtp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size)){ - if (callback == NULL){ - log_error("avdtp_sink_register_media_handler called with NULL callback"); - return; - } - handle_media_data = callback; -} - -void avdtp_sink_register_packet_handler(btstack_packet_handler_t callback){ - if (callback == NULL){ - log_error("avdtp_sink_register_packet_handler called with NULL callback"); - return; - } - avdtp_sink_callback = callback; -} - -void avdtp_sink_connect(bd_addr_t bd_addr){ - avdtp_connection_t * connection = get_avdtp_connection_for_bd_addr(bd_addr); - if (!connection){ - connection = avdtp_sink_create_connection(bd_addr); - } - if (connection->state != AVDTP_SIGNALING_CONNECTION_IDLE) return; - connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED; - l2cap_create_channel(packet_handler, connection->remote_addr, PSM_AVDTP, 0xffff, NULL); -} - -void avdtp_sink_disconnect(uint16_t con_handle){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (connection->state == AVDTP_SIGNALING_CONNECTION_IDLE) return; - if (connection->state == AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED) return; - - connection->disconnect = 1; - avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid); -} - -void avdtp_sink_open_stream(uint16_t con_handle, uint8_t acp_seid){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_media_connect: no connection for handle 0x%02x found\n", con_handle); - return; - } - - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) { - printf("avdtp_sink_media_connect: wrong connection state %d\n", connection->state); - return; - } - - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid); - if (!stream_endpoint) { - printf("avdtp_sink_media_connect: no stream_endpoint with acp seid %d found\n", acp_seid); - return; - } - - if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED) return; - if (stream_endpoint->remote_sep_index == 0xFF) return; - - printf(" AVDTP_INITIATOR_W2_MEDIA_CONNECT \n"); - connection->initiator_transaction_label++; - connection->acp_seid = acp_seid; - connection->int_seid = stream_endpoint->sep.seid; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_MEDIA_CONNECT; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); -} - -void avdtp_sink_start_stream(uint16_t con_handle, uint8_t acp_seid){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_media_connect: no connection for handle 0x%02x found\n", con_handle); - return; - } - - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) { - printf("avdtp_sink_media_connect: wrong connection state %d\n", connection->state); - return; - } - - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid); - if (!stream_endpoint) { - printf("avdtp_sink_media_connect: no stream_endpoint with acp_seid %d found\n", acp_seid); - return; - } - if (stream_endpoint->remote_sep_index == 0xFF) return; - if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_OPENED) return; - printf(" AVDTP_INITIATOR_W2_STREAMING_START \n"); - connection->initiator_transaction_label++; - connection->acp_seid = acp_seid; - connection->int_seid = stream_endpoint->sep.seid; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_START; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); -} - -void avdtp_sink_stop_stream(uint16_t con_handle, uint8_t acp_seid){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_stop_stream: no connection for handle 0x%02x found\n", con_handle); - return; - } - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) { - printf("avdtp_sink_stop_stream: wrong connection state %d\n", connection->state); - return; - } - - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid); - if (!stream_endpoint) { - printf("avdtp_sink_stop_stream: no stream_endpoint with acp seid %d found\n", acp_seid); - return; - } - if (stream_endpoint->remote_sep_index == 0xFF) return; - switch (stream_endpoint->state){ - case AVDTP_STREAM_ENDPOINT_OPENED: - case AVDTP_STREAM_ENDPOINT_STREAMING: - printf(" AVDTP_INITIATOR_W2_STREAMING_STOP \n"); - connection->initiator_transaction_label++; - connection->acp_seid = acp_seid; - connection->int_seid = stream_endpoint->sep.seid; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_STOP; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); - break; - default: - break; - } -} - -void avdtp_sink_abort_stream(uint16_t con_handle, uint8_t acp_seid){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_abort_stream: no connection for handle 0x%02x found\n", con_handle); - return; - } - - if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) { - printf("avdtp_sink_abort_stream: wrong connection state %d\n", connection->state); - return; - } - - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid); - if (!stream_endpoint) { - printf("avdtp_sink_abort_stream: no stream_endpoint for seid %d found\n", acp_seid); - return; - } - if (stream_endpoint->remote_sep_index == 0xFF) return; - switch (stream_endpoint->state){ - case AVDTP_STREAM_ENDPOINT_CONFIGURED: - case AVDTP_STREAM_ENDPOINT_CLOSING: - case AVDTP_STREAM_ENDPOINT_OPENED: - case AVDTP_STREAM_ENDPOINT_STREAMING: - printf(" AVDTP_INITIATOR_W2_STREAMING_ABORT \n"); - connection->initiator_transaction_label++; - connection->acp_seid = acp_seid; - connection->int_seid = stream_endpoint->sep.seid; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_ABORT; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); - break; - default: - break; - } -} - -void avdtp_sink_discover_stream_endpoints(uint16_t con_handle){ - 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; - - 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_initiator(connection, connection->l2cap_signaling_cid); - break; - default: - printf("avdtp_sink_discover_stream_endpoints: wrong state\n"); - break; - } -} - - -void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t acp_seid){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_get_capabilities: no connection for handle 0x%02x found\n", con_handle); - return; - } - 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->acp_seid = acp_seid; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); -} - - -void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_get_all_capabilities: no connection for handle 0x%02x found\n", con_handle); - return; - } - 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->acp_seid = acp_seid; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); -} - -void avdtp_sink_get_configuration(uint16_t con_handle, uint8_t acp_seid){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_get_configuration: no connection for handle 0x%02x found\n", con_handle); - return; - } - 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_CONFIGURATION; - connection->acp_seid = acp_seid; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); -} - -void avdtp_sink_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_set_configuration: no connection for handle 0x%02x found\n", con_handle); - return; - } - 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 = get_avdtp_stream_endpoint_for_seid(int_seid); - if (!stream_endpoint) { - printf("avdtp_sink_set_configuration: no initiator stream endpoint for seid %d\n", int_seid); - return; - } - printf("avdtp_sink_set_configuration int seid %d, acp seid %d\n", int_seid, acp_seid); - - connection->initiator_transaction_label++; - connection->acp_seid = acp_seid; - connection->int_seid = int_seid; - connection->remote_capabilities_bitmap = configured_services_bitmap; - connection->remote_capabilities = configuration; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SET_CONFIGURATION; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); -} - -void avdtp_sink_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_reconfigure: no connection for handle 0x%02x found\n", con_handle); - return; - } - //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; - avdtp_stream_endpoint_t * stream_endpoint = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid); - if (!stream_endpoint) return; - if (stream_endpoint->remote_sep_index == 0xFF) return; - connection->initiator_transaction_label++; - connection->acp_seid = acp_seid; - connection->int_seid = stream_endpoint->sep.seid; - connection->remote_capabilities_bitmap = configured_services_bitmap; - connection->remote_capabilities = configuration; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); -} - -void avdtp_sink_suspend(uint16_t con_handle, uint8_t acp_seid){ - avdtp_connection_t * connection = get_avdtp_connection_for_con_handle(con_handle); - if (!connection){ - printf("avdtp_sink_suspend: no connection for handle 0x%02x found\n", con_handle); - return; - } - 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 = get_avdtp_stream_endpoint_associated_with_acp_seid(acp_seid); - if (!stream_endpoint) return; - if (stream_endpoint->remote_sep_index == 0xFF) return; - connection->initiator_transaction_label++; - connection->acp_seid = acp_seid; - connection->int_seid = stream_endpoint->sep.seid; - stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID; - avdtp_sink_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); -} \ No newline at end of file diff --git a/test/avdtp/avdtp_sink.h b/test/avdtp/avdtp_sink.h deleted file mode 100644 index 6048e7145..000000000 --- a/test/avdtp/avdtp_sink.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - -/* - * avdtp_sink.h - * - * Audio/Video Distribution Transport Protocol (AVDTP) Sink - * - * AVDTP Sink is a device that accepts streamed media data. - */ - -#ifndef __AVDTP_SINK_H -#define __AVDTP_SINK_H - -#include -#include "hci.h" -#include "avdtp.h" - -#if defined __cplusplus -extern "C" { -#endif - -/* API_START */ -/** - * @brief AVDTP Sink service record. - * @param service - * @param service_record_handle - * @param supported_features 16-bit bitmap, see AVDTP_SINK_SF_* values in avdtp.h - * @param service_name - * @param service_provider_name - */ -void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name); - -/** - * @brief Set up AVDTP Sink device. - */ -void avdtp_sink_init(void); - -// returns avdtp_stream_endpoint_t * -avdtp_stream_endpoint_t * avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type); - -void avdtp_sink_register_media_transport_category(uint8_t seid); -void avdtp_sink_register_reporting_category(uint8_t seid); -void avdtp_sink_register_delay_reporting_category(uint8_t seid); -void avdtp_sink_register_recovery_category(uint8_t seid, uint8_t maximum_recovery_window_size, uint8_t maximum_number_media_packets); -void avdtp_sink_register_header_compression_category(uint8_t seid, uint8_t back_ch, uint8_t media, uint8_t recovery); -void avdtp_sink_register_multiplexing_category(uint8_t seid, uint8_t fragmentation); - -void avdtp_sink_register_media_codec_category(uint8_t seid, avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type, const uint8_t * media_codec_info, uint16_t media_codec_info_len); -void avdtp_sink_register_content_protection_category(uint8_t seid, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len); - -/** - * @brief Register callback for the AVDTP Sink client. - * @param callback - */ -void avdtp_sink_register_packet_handler(btstack_packet_handler_t callback); - -/** - * @brief Connect to device with a bluetooth address. (and perform configuration?) - * @param bd_addr - */ -void avdtp_sink_connect(bd_addr_t bd_addr); - -void avdtp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size)); -/** - * @brief Disconnect from device with connection handle. - * @param con_handle - */ -void avdtp_sink_disconnect(uint16_t con_handle); - -/** - * @brief Discover stream endpoints - * @param con_handle - */ -void avdtp_sink_discover_stream_endpoints(uint16_t con_handle); - -/** - * @brief Get capabilities - * @param con_handle - */ -void avdtp_sink_get_capabilities(uint16_t con_handle, uint8_t acp_seid); - -/** - * @brief Get all capabilities - * @param con_handle - */ -void avdtp_sink_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid); - -/** - * @brief Set configuration - * @param con_handle - */ -void avdtp_sink_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); - -/** - * @brief Reconfigure stream - * @param con_handle - * @param seid - */ -void avdtp_sink_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration); - -/** - * @brief Get configuration - * @param con_handle - */ -void avdtp_sink_get_configuration(uint16_t con_handle, uint8_t acp_seid); - -/** - * @brief Suspend stream - * @param con_handle - * @param seid - */ -void avdtp_sink_suspend(uint16_t con_handle, uint8_t acp_seid); - - -/** - * @brief Open stream - * @param con_handle - * @param seid - */ -void avdtp_sink_open_stream(uint16_t con_handle, uint8_t acp_seid); - -/** - * @brief Start stream - * @param con_handle - * @param seid - */ -void avdtp_sink_start_stream(uint16_t con_handle, uint8_t acp_seid); - -/** - * @brief Start stream - * @param con_handle - * @param seid - */ -void avdtp_sink_abort_stream(uint16_t con_handle, uint8_t acp_seid); - -/** - * @brief Start stream - * @param con_handle - * @param seid - */ -void avdtp_sink_stop_stream(uint16_t con_handle, uint8_t acp_seid); - -/* API_END */ - -extern btstack_packet_handler_t avdtp_sink_callback; -extern btstack_linked_list_t stream_endpoints; - -#if defined __cplusplus -} -#endif - -#endif // __AVDTP_SINK_H \ No newline at end of file diff --git a/test/avdtp/avdtp_source.c b/test/avdtp/avdtp_source.c deleted file mode 100644 index 6242947bd..000000000 --- a/test/avdtp/avdtp_source.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - - -#include -#include -#include -#include -#include - -#include "btstack.h" -#include "avdtp.h" -#include "avdtp_source.h" - - -static const char * default_avdtp_sink_service_name = "BTstack AVDTP Sink Service"; -static const char * default_avdtp_sink_service_provider_name = "BTstack AVDTP Sink Service Provider"; - -void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){ - uint8_t* attribute; - de_create_sequence(service); - - // 0x0000 "Service Record Handle" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); - de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle); - - // 0x0001 "Service Class ID List" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); - attribute = de_push_sequence(service); - { - de_add_number(attribute, DE_UUID, DE_SIZE_16, AUDIO_SOURCE_GROUP); - } - de_pop_sequence(service, attribute); - - // 0x0004 "Protocol Descriptor List" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); - attribute = de_push_sequence(service); - { - uint8_t* l2cpProtocol = de_push_sequence(attribute); - { - de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, SDP_L2CAPProtocol); - de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, PSM_AVDTP); - } - de_pop_sequence(attribute, l2cpProtocol); - - uint8_t* avProtocol = de_push_sequence(attribute); - { - de_add_number(avProtocol, DE_UUID, DE_SIZE_16, PSM_AVDTP); // avProtocol_service - de_add_number(avProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version - } - de_pop_sequence(attribute, avProtocol); - } - de_pop_sequence(service, attribute); - - // 0x0005 "Public Browse Group" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); // public browse group - attribute = de_push_sequence(service); - { - de_add_number(attribute, DE_UUID, DE_SIZE_16, SDP_PublicBrowseGroup); - } - de_pop_sequence(service, attribute); - - // 0x0009 "Bluetooth Profile Descriptor List" - de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); - attribute = de_push_sequence(service); - { - uint8_t *a2dProfile = de_push_sequence(attribute); - { - de_add_number(a2dProfile, DE_UUID, DE_SIZE_16, ADVANCED_AUDIO_DISTRIBUTION); - de_add_number(a2dProfile, DE_UINT, DE_SIZE_16, 0x0103); - } - de_pop_sequence(attribute, a2dProfile); - } - de_pop_sequence(service, attribute); - - - // 0x0100 "Service Name" - de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); - if (service_name){ - de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name); - } else { - de_add_data(service, DE_STRING, strlen(default_avdtp_sink_service_name), (uint8_t *) default_avdtp_sink_service_name); - } - - // 0x0100 "Provider Name" - de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102); - if (service_provider_name){ - de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name); - } else { - de_add_data(service, DE_STRING, strlen(default_avdtp_sink_service_provider_name), (uint8_t *) default_avdtp_sink_service_provider_name); - } - - // 0x0311 "Supported Features" - de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311); - de_add_number(service, DE_UINT, DE_SIZE_16, supported_features); -} - - - - diff --git a/test/avdtp/avdtp_source.h b/test/avdtp/avdtp_source.h deleted file mode 100644 index 24de81549..000000000 --- a/test/avdtp/avdtp_source.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - -/* - * avdtp_source.h - * - * Audio/Video Distribution Transport Protocol Source - * - * AVDTP Source is a device that streames media data. - */ - -#ifndef __AVDTP_SOURCE_H -#define __AVDTP_SOURCE_H - -#include - -#if defined __cplusplus -extern "C" { -#endif - -/* API_START */ - -/** - * @brief AVDTP Source service record. - * @param service - * @param service_record_handle - * @param supported_features 16-bit bitmap, see AVDTP_SOURCE_SF_* values in avdtp.h - * @param service_name - * @param service_provider_name - */ -void a2dp_source_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name); -/* API_END */ - -#if defined __cplusplus -} -#endif - -#endif // __AVDTP_SOURCE_H \ No newline at end of file diff --git a/test/avdtp/avdtp_util.c b/test/avdtp/avdtp_util.c deleted file mode 100644 index 18c41aeb0..000000000 --- a/test/avdtp/avdtp_util.c +++ /dev/null @@ -1,694 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - - -#include -#include -#include -#include -#include - -#include "btstack.h" -#include "avdtp.h" -#include "avdtp_util.h" - -inline uint8_t avdtp_header(uint8_t tr_label, avdtp_packet_type_t packet_type, avdtp_message_type_t msg_type){ - return (tr_label<<4) | ((uint8_t)packet_type<<2) | (uint8_t)msg_type; -} - -avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_with_seid(uint8_t seid){ - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &stream_endpoints); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); - if (stream_endpoint->sep.seid == seid){ - return stream_endpoint; - } - } - return NULL; -} - -avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_associated_with_acp_seid(uint16_t acp_seid){ - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &stream_endpoints); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); - if (stream_endpoint->remote_sep_index >= 0 && stream_endpoint->remote_sep_index < MAX_NUM_SEPS){ - if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid == acp_seid){ - return stream_endpoint; - } - } - } - return NULL; -} - -int get_bit16(uint16_t bitmap, int position){ - return (bitmap >> position) & 1; -} - -uint8_t store_bit16(uint16_t bitmap, int position, uint8_t value){ - if (value){ - bitmap |= 1 << position; - } else { - bitmap &= ~ (1 << position); - } - return bitmap; -} - -int avdtp_read_signaling_header(avdtp_signaling_packet_t * signaling_header, uint8_t * packet, uint16_t size){ - int pos = 0; - if (size < 2) return pos; - signaling_header->transaction_label = packet[pos] >> 4; - signaling_header->packet_type = (avdtp_packet_type_t)((packet[pos] >> 2) & 0x03); - signaling_header->message_type = (avdtp_message_type_t) (packet[pos] & 0x03); - pos++; - memset(signaling_header->command, 0, sizeof(signaling_header->command)); - switch (signaling_header->packet_type){ - case AVDTP_SINGLE_PACKET: - signaling_header->num_packets = 0; - signaling_header->offset = 0; - signaling_header->size = 0; - break; - case AVDTP_END_PACKET: - signaling_header->num_packets = 0; - break; - case AVDTP_START_PACKET: - signaling_header->num_packets = packet[pos++]; - signaling_header->size = 0; - signaling_header->offset = 0; - break; - case AVDTP_CONTINUE_PACKET: - if (signaling_header->num_packets <= 0) { - printf(" ERROR: wrong num fragmented packets\n"); - break; - } - signaling_header->num_packets--; - break; - } - signaling_header->signal_identifier = packet[pos++] & 0x3f; - return pos; -} - -int avdtp_pack_service_capabilities(uint8_t * buffer, int size, avdtp_capabilities_t caps, avdtp_service_category_t category, uint8_t pack_all_capabilities){ - UNUSED(size); - - int i; - // pos = 0 reserved for length - int pos = 1; - switch(category){ - case AVDTP_MEDIA_TRANSPORT: - case AVDTP_REPORTING: - break; - case AVDTP_DELAY_REPORTING: - if (!pack_all_capabilities) break; - break; - case AVDTP_RECOVERY: - buffer[pos++] = caps.recovery.recovery_type; // 0x01=RFC2733 - buffer[pos++] = caps.recovery.maximum_recovery_window_size; - buffer[pos++] = caps.recovery.maximum_number_media_packets; - break; - case AVDTP_CONTENT_PROTECTION: - buffer[pos++] = caps.content_protection.cp_type_value_len + 2; - big_endian_store_16(buffer, pos, caps.content_protection.cp_type); - pos += 2; - memcpy(buffer+pos, caps.content_protection.cp_type_value, caps.content_protection.cp_type_value_len); - break; - case AVDTP_HEADER_COMPRESSION: - buffer[pos++] = (caps.header_compression.back_ch << 7) | (caps.header_compression.media << 6) | (caps.header_compression.recovery << 5); - break; - case AVDTP_MULTIPLEXING: - buffer[pos++] = caps.multiplexing_mode.fragmentation << 7; - for (i=0; ierror_code = 0; - - if (category == AVDTP_SERVICE_CATEGORY_INVALID_0 || - (category == AVDTP_SERVICE_CATEGORY_INVALID_FF && connection->signaling_packet.signal_identifier == AVDTP_SI_RECONFIGURE)){ - printf(" ERROR: BAD SERVICE CATEGORY %d\n", category); - connection->reject_service_category = category; - connection->error_code = BAD_SERV_CATEGORY; - return 1; - } - - if (connection->signaling_packet.signal_identifier == AVDTP_SI_RECONFIGURE){ - if (category != AVDTP_CONTENT_PROTECTION && category != AVDTP_MEDIA_CODEC){ - printf(" ERROR: REJECT CATEGORY, INVALID_CAPABILITIES\n"); - connection->reject_service_category = category; - connection->error_code = INVALID_CAPABILITIES; - return 1; - } - } - - switch(category){ - case AVDTP_MEDIA_TRANSPORT: - if (cap_len != 0){ - printf(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n"); - connection->reject_service_category = category; - connection->error_code = BAD_MEDIA_TRANSPORT_FORMAT; - return 1; - } - break; - case AVDTP_REPORTING: - case AVDTP_DELAY_REPORTING: - if (cap_len != 0){ - printf(" ERROR: REJECT CATEGORY, BAD_LENGTH\n"); - connection->reject_service_category = category; - connection->error_code = BAD_LENGTH; - return 1; - } - break; - case AVDTP_RECOVERY: - if (cap_len < 3){ - printf(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n"); - connection->reject_service_category = category; - connection->error_code = BAD_RECOVERY_FORMAT; - return 1; - } - break; - case AVDTP_CONTENT_PROTECTION: - if (cap_len < 2){ - printf(" ERROR: REJECT CATEGORY, BAD_CP_FORMAT\n"); - connection->reject_service_category = category; - connection->error_code = BAD_CP_FORMAT; - return 1; - } - break; - case AVDTP_HEADER_COMPRESSION: - break; - case AVDTP_MULTIPLEXING: - break; - case AVDTP_MEDIA_CODEC: - break; - default: - break; - } - return 0; -} - -uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdtp_capabilities_t * caps, uint8_t * packet, uint16_t size){ - if (size == 0) return 0; - - uint16_t registered_service_categories = 0; - int pos = 0; - int i; - avdtp_service_category_t category = (avdtp_service_category_t)packet[pos++]; - uint8_t cap_len = packet[pos++]; - - if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0; - int processed_cap_len = 0; - int rfa = 0; - //printf(" size %d, cat size %d\n", size, cap_len); - - while (pos < size){ - if (cap_len > size - pos){ - connection->reject_service_category = category; - connection->error_code = BAD_LENGTH; - return 0; - } - rfa = 0; - processed_cap_len = pos; - switch(category){ - case AVDTP_RECOVERY: - caps->recovery.recovery_type = packet[pos++]; - caps->recovery.maximum_recovery_window_size = packet[pos++]; - caps->recovery.maximum_number_media_packets = packet[pos++]; - break; - case AVDTP_CONTENT_PROTECTION: - caps->content_protection.cp_type = big_endian_read_16(packet, pos); - pos+=2; - - caps->content_protection.cp_type_value_len = cap_len - 2; - pos += caps->content_protection.cp_type_value_len; - - // connection->reject_service_category = category; - // connection->error_code = UNSUPPORTED_CONFIGURATION; - // support for content protection goes here - break; - - case AVDTP_HEADER_COMPRESSION: - caps->header_compression.back_ch = packet[pos] >> 7; - caps->header_compression.media = packet[pos] >> 6; - caps->header_compression.recovery = packet[pos] >> 5; - pos++; - break; - case AVDTP_MULTIPLEXING: - caps->multiplexing_mode.fragmentation = packet[pos++] >> 7; - // read [tsid, tcid] for media, reporting. recovery respectively - caps->multiplexing_mode.transport_identifiers_num = 3; - for (i=0; imultiplexing_mode.transport_identifiers_num; i++){ - caps->multiplexing_mode.transport_session_identifiers[i] = packet[pos++] >> 7; - caps->multiplexing_mode.tcid[i] = packet[pos++] >> 7; - } - break; - case AVDTP_MEDIA_CODEC: - caps->media_codec.media_type = packet[pos++] >> 4; - caps->media_codec.media_codec_type = packet[pos++]; - caps->media_codec.media_codec_information_len = cap_len - 2; - caps->media_codec.media_codec_information = &packet[pos]; - pos += caps->media_codec.media_codec_information_len; - break; - case AVDTP_MEDIA_TRANSPORT: - case AVDTP_REPORTING: - case AVDTP_DELAY_REPORTING: - pos += cap_len; - break; - default: - pos += cap_len; - rfa = 1; - break; - } - processed_cap_len = pos - processed_cap_len; - - if (cap_len == processed_cap_len){ - if (!rfa) { - registered_service_categories = store_bit16(registered_service_categories, category, 1); - } - if (pos < size-2){ - //int old_pos = pos; - category = (avdtp_service_category_t)packet[pos++]; - cap_len = packet[pos++]; - if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0; - //printf("category %d, pos %d + 2 + %d -> %d\n", category, old_pos, cap_len, pos + cap_len); - //printf_hexdump(packet+old_pos, size-old_pos); - } - } - } - return registered_service_categories; -} - -void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uint8_t transaction_label, uint16_t registered_service_categories, avdtp_capabilities_t capabilities, uint8_t identifier){ - if (signaling_packet->offset) return; - uint8_t pack_all_capabilities = 1; - signaling_packet->message_type = AVDTP_RESPONSE_ACCEPT_MSG; - signaling_packet->size = 0; - int i; - signaling_packet->command[signaling_packet->size++] = signaling_packet->acp_seid << 2; - - switch (identifier) { - case AVDTP_SI_GET_CAPABILITIES: - pack_all_capabilities = 0; - break; - case AVDTP_SI_GET_ALL_CAPABILITIES: - pack_all_capabilities = 1; - break; - case AVDTP_SI_SET_CONFIGURATION: - signaling_packet->command[signaling_packet->size++] = signaling_packet->int_seid << 2; - signaling_packet->message_type = AVDTP_CMD_MSG; - break; - case AVDTP_SI_RECONFIGURE: - signaling_packet->message_type = AVDTP_CMD_MSG; - break; - default: - log_error("avdtp_prepare_capabilities wrong identifier %d", identifier); - 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; -} - -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; -} - - -void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, bd_addr_t addr, uint8_t status){ - if (!callback) return; - uint8_t event[12]; - int pos = 0; - event[pos++] = HCI_EVENT_AVDTP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED; - little_endian_store_16(event, pos, con_handle); - pos += 2; - reverse_bd_addr(addr,&event[pos]); - pos += 6; - event[pos++] = status; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - -void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){ - if (!callback) return; - uint8_t event[9]; - int pos = 0; - event[pos++] = HCI_EVENT_AVDTP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = AVDTP_SUBEVENT_SIGNALING_SEP_FOUND; - little_endian_store_16(event, pos, con_handle); - pos += 2; - event[pos++] = sep.seid; - event[pos++] = sep.in_use; - event[pos++] = sep.media_type; - event[pos++] = sep.type; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - -void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier, uint8_t status){ - if (!callback) return; - uint8_t event[7]; - int pos = 0; - event[pos++] = HCI_EVENT_AVDTP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = AVDTP_SUBEVENT_SIGNALING_ACCEPT; - little_endian_store_16(event, pos, con_handle); - pos += 2; - event[pos++] = identifier; - event[pos++] = status; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - -void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier){ - if (!callback) return; - uint8_t event[6]; - int pos = 0; - event[pos++] = HCI_EVENT_AVDTP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = AVDTP_SUBEVENT_SIGNALING_REJECT; - little_endian_store_16(event, pos, con_handle); - pos += 2; - event[pos++] = identifier; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - -void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier){ - if (!callback) return; - uint8_t event[6]; - int pos = 0; - event[pos++] = HCI_EVENT_AVDTP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT; - little_endian_store_16(event, pos, con_handle); - pos += 2; - event[pos++] = identifier; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - -void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ - if (!callback) return; - uint8_t event[13]; - int pos = 0; - event[pos++] = HCI_EVENT_AVDTP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY; - little_endian_store_16(event, pos, con_handle); - pos += 2; - event[pos++] = media_codec.media_type; - event[pos++] = media_codec.media_codec_information[0] >> 4; - event[pos++] = media_codec.media_codec_information[0] & 0x0F; - event[pos++] = media_codec.media_codec_information[1] >> 4; - event[pos++] = (media_codec.media_codec_information[1] & 0x0F) >> 2; - event[pos++] = media_codec.media_codec_information[1] & 0x03; - event[pos++] = media_codec.media_codec_information[2]; - event[pos++] = media_codec.media_codec_information[3]; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - -void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ - if (!callback) return; - uint8_t event[109]; - int pos = 0; - event[pos++] = HCI_EVENT_AVDTP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY; - little_endian_store_16(event, pos, con_handle); - pos += 2; - event[pos++] = media_codec.media_type; - little_endian_store_16(event, pos, media_codec.media_codec_type); - pos += 2; - little_endian_store_16(event, pos, media_codec.media_codec_information_len); - pos += 2; - if (media_codec.media_codec_information_len < 100){ - memcpy(event+pos, media_codec.media_codec_information, media_codec.media_codec_information_len); - } else { - memcpy(event+pos, media_codec.media_codec_information, 100); - } - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - -static inline void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){ - if (!callback) return; - uint8_t event[14+2]; - int pos = 0; - event[pos++] = HCI_EVENT_AVDTP_META; - event[pos++] = sizeof(event) - 2; - - event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION; - little_endian_store_16(event, pos, con_handle); - pos += 2; - event[pos++] = reconfigure; - - uint8_t num_channels = 0; - uint16_t sampling_frequency = 0; - uint8_t subbands = 0; - uint8_t block_length = 0; - - uint8_t sampling_frequency_bitmap = media_codec.media_codec_information[0] >> 4; - uint8_t channel_mode_bitmap = media_codec.media_codec_information[0] & 0x0F; - uint8_t block_length_bitmap = media_codec.media_codec_information[1] >> 4; - uint8_t subbands_bitmap = (media_codec.media_codec_information[1] & 0x0F) >> 2; - - if (channel_mode_bitmap & AVDTP_SBC_MONO){ - num_channels = 1; - } - if ( (channel_mode_bitmap & AVDTP_SBC_JOINT_STEREO) || - (channel_mode_bitmap & AVDTP_SBC_STEREO) || - (channel_mode_bitmap & AVDTP_SBC_DUAL_CHANNEL) ){ - num_channels = 2; - } - - if (sampling_frequency_bitmap & AVDTP_SBC_16000){ - sampling_frequency = 16000; - } - if (sampling_frequency_bitmap & AVDTP_SBC_32000){ - sampling_frequency = 32000; - } - if (sampling_frequency_bitmap & AVDTP_SBC_44100){ - sampling_frequency = 44100; - } - if (sampling_frequency_bitmap & AVDTP_SBC_48000){ - sampling_frequency = 48000; - } - - if (subbands_bitmap & AVDTP_SBC_SUBBANDS_4){ - subbands = 4; - } - if (subbands_bitmap & AVDTP_SBC_SUBBANDS_8){ - subbands = 8; - } - - if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_4){ - block_length = 4; - } - if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_8){ - block_length = 8; - } - if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_12){ - block_length = 12; - } - if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_16){ - block_length = 16; - } - - event[pos++] = media_codec.media_type; - little_endian_store_16(event, pos, sampling_frequency); - pos += 2; - - event[pos++] = channel_mode_bitmap; - event[pos++] = num_channels; - event[pos++] = block_length; - event[pos++] = subbands; - event[pos++] = media_codec.media_codec_information[1] & 0x03; - event[pos++] = media_codec.media_codec_information[2]; - event[pos++] = media_codec.media_codec_information[3]; - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - -void avdtp_signaling_emit_media_codec_sbc_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ - if (!callback) return; - avdtp_signaling_emit_media_codec_sbc(callback, con_handle, media_codec, 0); -} - -void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ - if (!callback) return; - avdtp_signaling_emit_media_codec_sbc(callback, con_handle, media_codec, 1); -} - -static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){ - uint8_t event[110]; - int pos = 0; - event[pos++] = HCI_EVENT_AVDTP_META; - event[pos++] = sizeof(event) - 2; - event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION; - little_endian_store_16(event, pos, con_handle); - pos += 2; - - event[pos++] = reconfigure; - - event[pos++] = media_codec.media_type; - little_endian_store_16(event, pos, media_codec.media_codec_type); - pos += 2; - little_endian_store_16(event, pos, media_codec.media_codec_information_len); - pos += 2; - - if (media_codec.media_codec_information_len < 100){ - memcpy(event+pos, media_codec.media_codec_information, media_codec.media_codec_information_len); - } else { - memcpy(event+pos, media_codec.media_codec_information, 100); - } - (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); -} - -void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ - if (!callback) return; - avdtp_signaling_emit_media_codec_other(callback, con_handle, media_codec, 0); -} - -void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ - if (!callback) return; - avdtp_signaling_emit_media_codec_other(callback, con_handle, media_codec, 1); -} - - -void avdtp_sink_request_can_send_now_acceptor(avdtp_connection_t * connection, uint16_t l2cap_cid){ - connection->wait_to_send_acceptor = 1; - l2cap_request_can_send_now_event(l2cap_cid); -} -void avdtp_sink_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid){ - connection->wait_to_send_initiator = 1; - l2cap_request_can_send_now_event(l2cap_cid); -} -void avdtp_sink_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l2cap_cid){ - connection->wait_to_send_self = 1; - l2cap_request_can_send_now_event(l2cap_cid); -} - -avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_for_seid(uint16_t seid){ - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &stream_endpoints); - while (btstack_linked_list_iterator_has_next(&it)){ - avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); - if (stream_endpoint->sep.seid == seid){ - return stream_endpoint; - } - } - return NULL; -} - -uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t seid){ - if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid == seid){ - return stream_endpoint->remote_sep_index; - } - int i; - for (i=0; i < stream_endpoint->remote_seps_num; i++){ - if (stream_endpoint->remote_seps[i].seid == seid){ - return i; - } - } - return 0xFF; -} diff --git a/test/avdtp/avdtp_util.h b/test/avdtp/avdtp_util.h deleted file mode 100644 index 55bf723d7..000000000 --- a/test/avdtp/avdtp_util.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2016 BlueKitchen GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * 4. Any redistribution, use, or modification is done solely for - * personal benefit and not for any commercial purpose or for - * monetary gain. - * - * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS - * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Please inquire about commercial licensing options at - * contact@bluekitchen-gmbh.com - * - */ - -/* - * avdtp_util.h - * - * Audio/Video Distribution Transport Protocol - Utils - * - */ - -#ifndef __AVDTP_UITL_H -#define __AVDTP_UITL_H - -#include -#include "avdtp.h" - -#if defined __cplusplus -extern "C" { -#endif - -avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_with_seid(uint8_t seid); -avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_associated_with_acp_seid(uint16_t acp_seid); - -uint8_t avdtp_header(uint8_t tr_label, avdtp_packet_type_t packet_type, avdtp_message_type_t msg_type); -int avdtp_read_signaling_header(avdtp_signaling_packet_t * signaling_header, uint8_t * packet, uint16_t size); - -uint8_t store_bit16(uint16_t bitmap, int position, uint8_t value); -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); - -void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, bd_addr_t addr, uint8_t status); -void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep); -void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier, uint8_t status); -void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier); -void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier); - - -void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec); -void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec); -void avdtp_signaling_emit_media_codec_sbc_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec); -void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec); -void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec); -void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec); - -void avdtp_sink_request_can_send_now_acceptor(avdtp_connection_t * connection, uint16_t l2cap_cid); -void avdtp_sink_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid); -void avdtp_sink_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); - -avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_for_seid(uint16_t seid); - -#if defined __cplusplus -} -#endif - -#endif // __AVDTP_UITL_H \ No newline at end of file