/* * 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_pack_service_capabilities(uint8_t * buffer, int size, avdtp_capabilities_t caps, avdtp_service_category_t category){ int i; // pos = 0 reserved for length int pos = 1; switch(category){ case AVDTP_MEDIA_TRANSPORT: case AVDTP_REPORTING: case AVDTP_DELAY_REPORTING: 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_lsb; buffer[pos++] = caps.content_protection.cp_type_msb; for (i = 0; irecovery.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_lsb = packet[pos++]; caps->content_protection.cp_type_msb = packet[pos++]; caps->content_protection.cp_type_value_len = cap_len - 2; printf_hexdump(packet+pos, caps->content_protection.cp_type_value_len); pos += caps->content_protection.cp_type_value_len; 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; 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; // media, reporting. recovery } 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; printf_hexdump(packet+pos, caps->media_codec.media_codec_information_len); pos += caps->media_codec.media_codec_information_len; break; } registered_service_categories = store_bit16(registered_service_categories, category, 1); } return registered_service_categories; } static int avdtp_acceptor_send_seps_response(uint16_t cid, uint8_t transaction_label, avdtp_sep_t * seps, int seps_num){ 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; int i = 0; for (i=0; iacceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE; } int avdtp_acceptor_stream_config_subsm_is_done(avdtp_sink_connection_t * connection){ return connection->acceptor_config_state == AVDTP_ACCEPTOR_STREAM_CONFIG_DONE; } int avdtp_acceptor_stream_config_subsm(avdtp_sink_connection_t * connection, uint8_t *packet, uint16_t size){ int request_to_send = 1; avdtp_signaling_packet_header_t signaling_header; avdtp_read_signaling_header(&signaling_header, packet, size); // printf("SIGNALING HEADER: tr_label %d, packet_type %d, msg_type %d, signal_identifier %02x\n", // signaling_header.transaction_label, signaling_header.packet_type, signaling_header.message_type, signaling_header.signal_identifier); int i = 2; avdtp_sep_t sep; connection->acceptor_transaction_label = signaling_header.transaction_label; switch (connection->acceptor_config_state){ case AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE: switch (signaling_header.signal_identifier){ case AVDTP_SI_DISCOVER: printf(" ACP -> AVDTP_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS\n"); connection->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS; break; case AVDTP_SI_GET_CAPABILITIES: printf(" ACP -> AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES\n"); connection->local_seid = packet[2] >> 2; connection->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES; break; case AVDTP_SI_SET_CONFIGURATION: printf(" ACP -> AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION\n"); connection->local_seid = packet[2] >> 2; sep.seid = packet[3] >> 2; // find or add sep for (i=0; iremote_seps_num; i++){ if (connection->remote_seps[i].seid == sep.seid){ connection->remote_sep_index = i; } } sep.registered_service_categories = avdtp_unpack_service_capabilities(&sep.capabilities, packet+4, size-4); connection->remote_seps[connection->remote_sep_index] = sep; connection->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION; break; default: printf(" ACP -> NOT IMPLEMENTED\n"); request_to_send = 0; break; } l2cap_request_can_send_now_event(connection->l2cap_signaling_cid); break; case AVDTP_ACCEPTOR_STREAM_CONFIG_DONE: request_to_send = 0; printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION\n"); break; default: printf(" ACP -> subsm NOT IMPLEMENTED\n"); break; } return request_to_send; } int avdtp_acceptor_stream_config_subsm_run_for_connection(avdtp_sink_connection_t *connection, avdtp_sep_t * local_seps, uint8_t local_seps_num){ int sent = 1; switch (connection->acceptor_config_state){ case AVDTP_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS: printf(" AVDTP_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS -> AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE\n"); connection->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE; avdtp_acceptor_send_seps_response(connection->l2cap_signaling_cid, connection->acceptor_transaction_label, local_seps, local_seps_num); break; case AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES: printf(" AVDTP_ACCEPTOR_W2_ANSWER_GET_CAPABILITIES -> AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE\n"); connection->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE; avdtp_acceptor_send_capabilities_response(connection->l2cap_signaling_cid, connection->acceptor_transaction_label, local_seps[connection->local_seid]); break; case AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION: printf(" AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION -> AVDTP_ACCEPTOR_STREAM_CONFIG_DONE\n"); connection->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_DONE; avdtp_acceptor_send_accept_response(connection->l2cap_signaling_cid, AVDTP_SI_SET_CONFIGURATION, connection->acceptor_transaction_label); break; default: printf(" ACP -> run NOT IMPLEMENTED\n"); sent = 0; break; } return sent; }