1747ec646SMilanka Ringwald /* 2747ec646SMilanka Ringwald * Copyright (C) 2016 BlueKitchen GmbH 3747ec646SMilanka Ringwald * 4747ec646SMilanka Ringwald * Redistribution and use in source and binary forms, with or without 5747ec646SMilanka Ringwald * modification, are permitted provided that the following conditions 6747ec646SMilanka Ringwald * are met: 7747ec646SMilanka Ringwald * 8747ec646SMilanka Ringwald * 1. Redistributions of source code must retain the above copyright 9747ec646SMilanka Ringwald * notice, this list of conditions and the following disclaimer. 10747ec646SMilanka Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11747ec646SMilanka Ringwald * notice, this list of conditions and the following disclaimer in the 12747ec646SMilanka Ringwald * documentation and/or other materials provided with the distribution. 13747ec646SMilanka Ringwald * 3. Neither the name of the copyright holders nor the names of 14747ec646SMilanka Ringwald * contributors may be used to endorse or promote products derived 15747ec646SMilanka Ringwald * from this software without specific prior written permission. 16747ec646SMilanka Ringwald * 4. Any redistribution, use, or modification is done solely for 17747ec646SMilanka Ringwald * personal benefit and not for any commercial purpose or for 18747ec646SMilanka Ringwald * monetary gain. 19747ec646SMilanka Ringwald * 20747ec646SMilanka Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21747ec646SMilanka Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22747ec646SMilanka Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23747ec646SMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24747ec646SMilanka Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25747ec646SMilanka Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26747ec646SMilanka Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27747ec646SMilanka Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28747ec646SMilanka Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29747ec646SMilanka Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30747ec646SMilanka Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31747ec646SMilanka Ringwald * SUCH DAMAGE. 32747ec646SMilanka Ringwald * 33747ec646SMilanka Ringwald * Please inquire about commercial licensing options at 34747ec646SMilanka Ringwald * [email protected] 35747ec646SMilanka Ringwald * 36747ec646SMilanka Ringwald */ 37747ec646SMilanka Ringwald 38ab2c6ae4SMatthias Ringwald #define __BTSTACK_FILE__ "avdtp.c" 39ab2c6ae4SMatthias Ringwald 40747ec646SMilanka Ringwald 41747ec646SMilanka Ringwald #include <stdint.h> 42747ec646SMilanka Ringwald #include <stdio.h> 43747ec646SMilanka Ringwald #include <stdlib.h> 44747ec646SMilanka Ringwald #include <string.h> 45747ec646SMilanka Ringwald #include <unistd.h> 46747ec646SMilanka Ringwald 47747ec646SMilanka Ringwald #include "btstack.h" 48747ec646SMilanka Ringwald #include "avdtp.h" 49747ec646SMilanka Ringwald #include "avdtp_util.h" 50747ec646SMilanka Ringwald #include "avdtp_acceptor.h" 51747ec646SMilanka Ringwald #include "avdtp_initiator.h" 52747ec646SMilanka Ringwald 53747ec646SMilanka Ringwald static uint8_t audio_samples_storage[44100*4]; // 1s buffer 54747ec646SMilanka Ringwald // static btstack_ring_buffer_t audio_ring_buffer; 55747ec646SMilanka Ringwald 56747ec646SMilanka Ringwald static uint8_t sbc_samples_storage[44100*4]; 57747ec646SMilanka Ringwald // static btstack_ring_buffer_t sbc_ring_buffer; 58747ec646SMilanka Ringwald 59747ec646SMilanka Ringwald static void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size); 60747ec646SMilanka Ringwald 61747ec646SMilanka Ringwald void avdtp_register_media_transport_category(avdtp_stream_endpoint_t * stream_endpoint){ 62747ec646SMilanka Ringwald if (!stream_endpoint){ 63747ec646SMilanka Ringwald log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered"); 64747ec646SMilanka Ringwald return; 65747ec646SMilanka Ringwald } 66747ec646SMilanka Ringwald uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_TRANSPORT, 1); 67747ec646SMilanka Ringwald stream_endpoint->sep.registered_service_categories = bitmap; 68747ec646SMilanka Ringwald printf("registered services AVDTP_MEDIA_TRANSPORT(%d) %02x\n", AVDTP_MEDIA_TRANSPORT, stream_endpoint->sep.registered_service_categories); 69747ec646SMilanka Ringwald } 70747ec646SMilanka Ringwald 71747ec646SMilanka Ringwald void avdtp_register_reporting_category(avdtp_stream_endpoint_t * stream_endpoint){ 72747ec646SMilanka Ringwald if (!stream_endpoint){ 73747ec646SMilanka Ringwald log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered"); 74747ec646SMilanka Ringwald return; 75747ec646SMilanka Ringwald } 76747ec646SMilanka Ringwald uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_REPORTING, 1); 77747ec646SMilanka Ringwald stream_endpoint->sep.registered_service_categories = bitmap; 78747ec646SMilanka Ringwald } 79747ec646SMilanka Ringwald 80747ec646SMilanka Ringwald void avdtp_register_delay_reporting_category(avdtp_stream_endpoint_t * stream_endpoint){ 81747ec646SMilanka Ringwald if (!stream_endpoint){ 82747ec646SMilanka Ringwald log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered"); 83747ec646SMilanka Ringwald return; 84747ec646SMilanka Ringwald } 85747ec646SMilanka Ringwald uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_DELAY_REPORTING, 1); 86747ec646SMilanka Ringwald stream_endpoint->sep.registered_service_categories = bitmap; 87747ec646SMilanka Ringwald } 88747ec646SMilanka Ringwald 89747ec646SMilanka Ringwald void avdtp_register_recovery_category(avdtp_stream_endpoint_t * stream_endpoint, uint8_t maximum_recovery_window_size, uint8_t maximum_number_media_packets){ 90747ec646SMilanka Ringwald if (!stream_endpoint){ 91747ec646SMilanka Ringwald log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered"); 92747ec646SMilanka Ringwald return; 93747ec646SMilanka Ringwald } 94747ec646SMilanka Ringwald uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_RECOVERY, 1); 95747ec646SMilanka Ringwald stream_endpoint->sep.registered_service_categories = bitmap; 96747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.recovery.recovery_type = 0x01; // 0x01 = RFC2733 97747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.recovery.maximum_recovery_window_size = maximum_recovery_window_size; 98747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.recovery.maximum_number_media_packets = maximum_number_media_packets; 99747ec646SMilanka Ringwald } 100747ec646SMilanka Ringwald 101747ec646SMilanka Ringwald void avdtp_register_content_protection_category(avdtp_stream_endpoint_t * stream_endpoint, uint16_t cp_type, const uint8_t * cp_type_value, uint8_t cp_type_value_len){ 102747ec646SMilanka Ringwald if (!stream_endpoint){ 103747ec646SMilanka Ringwald log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered"); 104747ec646SMilanka Ringwald return; 105747ec646SMilanka Ringwald } 106747ec646SMilanka Ringwald uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_CONTENT_PROTECTION, 1); 107747ec646SMilanka Ringwald stream_endpoint->sep.registered_service_categories = bitmap; 108747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.content_protection.cp_type = cp_type; 109747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.content_protection.cp_type_value = cp_type_value; 110747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.content_protection.cp_type_value_len = cp_type_value_len; 111747ec646SMilanka Ringwald } 112747ec646SMilanka Ringwald 113747ec646SMilanka Ringwald void avdtp_register_header_compression_category(avdtp_stream_endpoint_t * stream_endpoint, uint8_t back_ch, uint8_t media, uint8_t recovery){ 114747ec646SMilanka Ringwald if (!stream_endpoint){ 115747ec646SMilanka Ringwald log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered"); 116747ec646SMilanka Ringwald return; 117747ec646SMilanka Ringwald } 118747ec646SMilanka Ringwald uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_HEADER_COMPRESSION, 1); 119747ec646SMilanka Ringwald stream_endpoint->sep.registered_service_categories = bitmap; 120747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.header_compression.back_ch = back_ch; 121747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.header_compression.media = media; 122747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.header_compression.recovery = recovery; 123747ec646SMilanka Ringwald } 124747ec646SMilanka Ringwald 125747ec646SMilanka Ringwald void avdtp_register_media_codec_category(avdtp_stream_endpoint_t * stream_endpoint, 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){ 126747ec646SMilanka Ringwald if (!stream_endpoint){ 127747ec646SMilanka Ringwald log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered"); 128747ec646SMilanka Ringwald return; 129747ec646SMilanka Ringwald } 130747ec646SMilanka Ringwald uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_CODEC, 1); 131747ec646SMilanka Ringwald stream_endpoint->sep.registered_service_categories = bitmap; 132747ec646SMilanka Ringwald printf("registered services AVDTP_MEDIA_CODEC(%d) %02x\n", AVDTP_MEDIA_CODEC, stream_endpoint->sep.registered_service_categories); 133747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.media_codec.media_type = media_type; 134747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.media_codec.media_codec_type = media_codec_type; 135747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.media_codec.media_codec_information = media_codec_info; 136747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.media_codec.media_codec_information_len = media_codec_info_len; 137747ec646SMilanka Ringwald } 138747ec646SMilanka Ringwald 139747ec646SMilanka Ringwald void avdtp_register_multiplexing_category(avdtp_stream_endpoint_t * stream_endpoint, uint8_t fragmentation){ 140747ec646SMilanka Ringwald if (!stream_endpoint){ 141747ec646SMilanka Ringwald log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered"); 142747ec646SMilanka Ringwald return; 143747ec646SMilanka Ringwald } 144747ec646SMilanka Ringwald uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MULTIPLEXING, 1); 145747ec646SMilanka Ringwald stream_endpoint->sep.registered_service_categories = bitmap; 146747ec646SMilanka Ringwald stream_endpoint->sep.capabilities.multiplexing_mode.fragmentation = fragmentation; 147747ec646SMilanka Ringwald } 148747ec646SMilanka Ringwald 149747ec646SMilanka Ringwald 150747ec646SMilanka Ringwald /* START: tracking can send now requests pro l2cap cid */ 151747ec646SMilanka Ringwald void avdtp_handle_can_send_now(avdtp_connection_t * connection, uint16_t l2cap_cid, avdtp_context_t * context){ 152747ec646SMilanka Ringwald if (connection->wait_to_send_acceptor){ 153747ec646SMilanka Ringwald connection->wait_to_send_acceptor = 0; 154747ec646SMilanka Ringwald avdtp_acceptor_stream_config_subsm_run(connection, context); 155747ec646SMilanka Ringwald } else if (connection->wait_to_send_initiator){ 156747ec646SMilanka Ringwald connection->wait_to_send_initiator = 0; 157747ec646SMilanka Ringwald avdtp_initiator_stream_config_subsm_run(connection, context); 158747ec646SMilanka Ringwald } else if (connection->wait_to_send_self){ 159747ec646SMilanka Ringwald connection->wait_to_send_self = 0; 160747ec646SMilanka Ringwald if (connection->disconnect){ 161747ec646SMilanka Ringwald btstack_linked_list_iterator_t it; 162747ec646SMilanka Ringwald btstack_linked_list_iterator_init(&it, &context->stream_endpoints); 163747ec646SMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 164747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); 165747ec646SMilanka Ringwald if (stream_endpoint->connection == connection){ 166747ec646SMilanka Ringwald if (stream_endpoint->state >= AVDTP_STREAM_ENDPOINT_OPENED && stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_DISCONNECTED){ 167747ec646SMilanka Ringwald stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_DISCONNECTED; 168747ec646SMilanka Ringwald avdtp_request_can_send_now_self(connection, connection->l2cap_signaling_cid); 169747ec646SMilanka Ringwald l2cap_disconnect(stream_endpoint->l2cap_media_cid, 0); 170747ec646SMilanka Ringwald return; 171747ec646SMilanka Ringwald } 172747ec646SMilanka Ringwald } 173747ec646SMilanka Ringwald } 174747ec646SMilanka Ringwald connection->disconnect = 0; 175747ec646SMilanka Ringwald connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED; 176747ec646SMilanka Ringwald l2cap_disconnect(connection->l2cap_signaling_cid, 0); 177747ec646SMilanka Ringwald return; 178747ec646SMilanka Ringwald } 179747ec646SMilanka Ringwald } 180747ec646SMilanka Ringwald 181747ec646SMilanka Ringwald // re-register 182747ec646SMilanka Ringwald int more_to_send = connection->wait_to_send_acceptor || connection->wait_to_send_initiator || connection->wait_to_send_self; 183747ec646SMilanka Ringwald if (more_to_send){ 184747ec646SMilanka Ringwald l2cap_request_can_send_now_event(l2cap_cid); 185747ec646SMilanka Ringwald } 186747ec646SMilanka Ringwald } 187747ec646SMilanka Ringwald /* END: tracking can send now requests pro l2cap cid */ 188747ec646SMilanka Ringwald 189747ec646SMilanka Ringwald avdtp_connection_t * avdtp_create_connection(bd_addr_t remote_addr, avdtp_context_t * context){ 190747ec646SMilanka Ringwald avdtp_connection_t * connection = btstack_memory_avdtp_connection_get(); 191747ec646SMilanka Ringwald memset(connection, 0, sizeof(avdtp_connection_t)); 192747ec646SMilanka Ringwald connection->state = AVDTP_SIGNALING_CONNECTION_IDLE; 193747ec646SMilanka Ringwald connection->initiator_transaction_label++; 194747ec646SMilanka Ringwald memcpy(connection->remote_addr, remote_addr, 6); 195747ec646SMilanka Ringwald btstack_linked_list_add(&context->connections, (btstack_linked_item_t *) connection); 196747ec646SMilanka Ringwald return connection; 197747ec646SMilanka Ringwald } 198747ec646SMilanka Ringwald 199747ec646SMilanka Ringwald avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type, avdtp_context_t * context){ 200747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = btstack_memory_avdtp_stream_endpoint_get(); 201747ec646SMilanka Ringwald memset(stream_endpoint, 0, sizeof(avdtp_stream_endpoint_t)); 202747ec646SMilanka Ringwald context->stream_endpoints_id_counter++; 203747ec646SMilanka Ringwald stream_endpoint->sep.seid = context->stream_endpoints_id_counter; 204747ec646SMilanka Ringwald stream_endpoint->sep.media_type = media_type; 205747ec646SMilanka Ringwald stream_endpoint->sep.type = sep_type; 206747ec646SMilanka Ringwald 207747ec646SMilanka Ringwald memset(audio_samples_storage, 0, sizeof(audio_samples_storage)); 208747ec646SMilanka Ringwald btstack_ring_buffer_init(&stream_endpoint->audio_ring_buffer, audio_samples_storage, sizeof(audio_samples_storage)); 209747ec646SMilanka Ringwald 210747ec646SMilanka Ringwald memset(sbc_samples_storage, 0, sizeof(sbc_samples_storage)); 211747ec646SMilanka Ringwald btstack_ring_buffer_init(&stream_endpoint->sbc_ring_buffer, sbc_samples_storage, sizeof(sbc_samples_storage)); 212747ec646SMilanka Ringwald 213747ec646SMilanka Ringwald 214747ec646SMilanka Ringwald btstack_linked_list_add(&context->stream_endpoints, (btstack_linked_item_t *) stream_endpoint); 215747ec646SMilanka Ringwald return stream_endpoint; 216747ec646SMilanka Ringwald } 217747ec646SMilanka Ringwald 218747ec646SMilanka Ringwald 219747ec646SMilanka Ringwald static void handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t * connection, uint8_t *packet, uint16_t size, avdtp_context_t * context){ 220747ec646SMilanka Ringwald int offset = avdtp_read_signaling_header(&connection->signaling_packet, packet, size); 221747ec646SMilanka Ringwald switch (connection->signaling_packet.message_type){ 222747ec646SMilanka Ringwald case AVDTP_CMD_MSG: 223747ec646SMilanka Ringwald avdtp_acceptor_stream_config_subsm(connection, packet, size, offset, context); 224747ec646SMilanka Ringwald break; 225747ec646SMilanka Ringwald default: 226747ec646SMilanka Ringwald avdtp_initiator_stream_config_subsm(connection, packet, size, offset, context); 227747ec646SMilanka Ringwald break; 228747ec646SMilanka Ringwald } 229747ec646SMilanka Ringwald } 230747ec646SMilanka Ringwald 231747ec646SMilanka Ringwald 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, avdtp_context_t * context){ 232747ec646SMilanka Ringwald uint16_t local_cid; 233747ec646SMilanka Ringwald switch (packet_type){ 234747ec646SMilanka Ringwald case L2CAP_DATA_PACKET:{ 235747ec646SMilanka Ringwald int offset = avdtp_read_signaling_header(&connection->signaling_packet, packet, size); 236747ec646SMilanka Ringwald if (connection->signaling_packet.message_type == AVDTP_CMD_MSG){ 237747ec646SMilanka Ringwald avdtp_acceptor_stream_config_subsm(connection, packet, size, offset, context); 238747ec646SMilanka Ringwald } else { 239747ec646SMilanka Ringwald avdtp_initiator_stream_config_subsm(connection, packet, size, offset, context); 240747ec646SMilanka Ringwald } 241747ec646SMilanka Ringwald break; 242747ec646SMilanka Ringwald } 243747ec646SMilanka Ringwald case HCI_EVENT_PACKET: 244747ec646SMilanka Ringwald switch (event){ 245747ec646SMilanka Ringwald case L2CAP_EVENT_CHANNEL_OPENED: 246747ec646SMilanka Ringwald if (stream_endpoint->l2cap_media_cid == 0){ 247747ec646SMilanka Ringwald if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED) return; 248747ec646SMilanka Ringwald stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED; 249747ec646SMilanka Ringwald stream_endpoint->connection = connection; 250747ec646SMilanka Ringwald stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet); 251747ec646SMilanka Ringwald printf(" -> AVDTP_STREAM_ENDPOINT_OPENED, stream endpoint %p, connection %p\n", stream_endpoint, connection); 252747ec646SMilanka Ringwald avdtp_streaming_emit_connection_established(context->avdtp_callback, stream_endpoint->l2cap_media_cid, 0); 253747ec646SMilanka Ringwald break; 254747ec646SMilanka Ringwald } 255747ec646SMilanka Ringwald break; 256747ec646SMilanka Ringwald case L2CAP_EVENT_CHANNEL_CLOSED: 257747ec646SMilanka Ringwald local_cid = l2cap_event_channel_closed_get_local_cid(packet); 258747ec646SMilanka Ringwald if (stream_endpoint->l2cap_media_cid == local_cid){ 259747ec646SMilanka Ringwald stream_endpoint->l2cap_media_cid = 0; 260747ec646SMilanka Ringwald printf(" -> L2CAP_EVENT_CHANNEL_CLOSED: AVDTP_STREAM_ENDPOINT_IDLE\n"); 261747ec646SMilanka Ringwald stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE; 262747ec646SMilanka Ringwald stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE; 263747ec646SMilanka Ringwald stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE; 264747ec646SMilanka Ringwald stream_endpoint->remote_seps_num = 0; 265747ec646SMilanka Ringwald memset(stream_endpoint->remote_seps, 0, sizeof(avdtp_sep_t)*MAX_NUM_SEPS); 266747ec646SMilanka Ringwald stream_endpoint->remote_sep_index = 0; 267747ec646SMilanka Ringwald break; 268747ec646SMilanka Ringwald } 269747ec646SMilanka Ringwald if (stream_endpoint->l2cap_recovery_cid == local_cid){ 270747ec646SMilanka Ringwald log_info(" -> L2CAP_EVENT_CHANNEL_CLOSED recovery cid 0x%0x", local_cid); 271747ec646SMilanka Ringwald stream_endpoint->l2cap_recovery_cid = 0; 272747ec646SMilanka Ringwald break; 273747ec646SMilanka Ringwald } 274747ec646SMilanka Ringwald 275747ec646SMilanka Ringwald if (stream_endpoint->l2cap_reporting_cid == local_cid){ 276747ec646SMilanka Ringwald log_info("L2CAP_EVENT_CHANNEL_CLOSED reporting cid 0x%0x", local_cid); 277747ec646SMilanka Ringwald stream_endpoint->l2cap_reporting_cid = 0; 278747ec646SMilanka Ringwald break; 279747ec646SMilanka Ringwald } 280747ec646SMilanka Ringwald break; 281747ec646SMilanka Ringwald default: 282747ec646SMilanka Ringwald break; 283747ec646SMilanka Ringwald } 284747ec646SMilanka Ringwald break; 285747ec646SMilanka Ringwald default: 286747ec646SMilanka Ringwald break; 287747ec646SMilanka Ringwald } 288747ec646SMilanka Ringwald } 289747ec646SMilanka Ringwald 290747ec646SMilanka Ringwald void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avdtp_context_t * context){ 291747ec646SMilanka Ringwald bd_addr_t event_addr; 292747ec646SMilanka Ringwald hci_con_handle_t con_handle; 293747ec646SMilanka Ringwald uint16_t psm; 294747ec646SMilanka Ringwald uint16_t local_cid; 295747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = NULL; 296747ec646SMilanka Ringwald avdtp_connection_t * connection = NULL; 297747ec646SMilanka Ringwald btstack_linked_list_t * avdtp_connections = &context->connections; 298747ec646SMilanka Ringwald btstack_linked_list_t * stream_endpoints = &context->stream_endpoints; 299747ec646SMilanka Ringwald handle_media_data = context->handle_media_data; 300747ec646SMilanka Ringwald // printf("avdtp_packet_handler packet type %02x, event %02x \n", packet_type, hci_event_packet_get_type(packet)); 301747ec646SMilanka Ringwald switch (packet_type) { 302747ec646SMilanka Ringwald case L2CAP_DATA_PACKET: 303747ec646SMilanka Ringwald connection = avdtp_connection_for_l2cap_signaling_cid(channel, context); 304747ec646SMilanka Ringwald if (connection){ 305747ec646SMilanka Ringwald handle_l2cap_data_packet_for_signaling_connection(connection, packet, size, context); 306747ec646SMilanka Ringwald break; 307747ec646SMilanka Ringwald } 308747ec646SMilanka Ringwald 309747ec646SMilanka Ringwald stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(channel, context); 310747ec646SMilanka Ringwald if (!stream_endpoint){ 311747ec646SMilanka Ringwald if (!connection) break; 312747ec646SMilanka Ringwald handle_l2cap_data_packet_for_signaling_connection(connection, packet, size, context); 313747ec646SMilanka Ringwald break; 314747ec646SMilanka Ringwald } 315747ec646SMilanka Ringwald 316747ec646SMilanka Ringwald if (channel == stream_endpoint->connection->l2cap_signaling_cid){ 317747ec646SMilanka Ringwald stream_endpoint_state_machine(stream_endpoint->connection, stream_endpoint, L2CAP_DATA_PACKET, 0, packet, size, context); 318747ec646SMilanka Ringwald break; 319747ec646SMilanka Ringwald } 320747ec646SMilanka Ringwald 321747ec646SMilanka Ringwald if (channel == stream_endpoint->l2cap_media_cid){ 322747ec646SMilanka Ringwald (*handle_media_data)(stream_endpoint, packet, size); 323747ec646SMilanka Ringwald break; 324747ec646SMilanka Ringwald } 325747ec646SMilanka Ringwald 326747ec646SMilanka Ringwald if (channel == stream_endpoint->l2cap_reporting_cid){ 327747ec646SMilanka Ringwald // TODO 328747ec646SMilanka Ringwald printf("L2CAP_DATA_PACKET for reporting: NOT IMPLEMENTED\n"); 329747ec646SMilanka Ringwald } else if (channel == stream_endpoint->l2cap_recovery_cid){ 330747ec646SMilanka Ringwald // TODO 331747ec646SMilanka Ringwald printf("L2CAP_DATA_PACKET for recovery: NOT IMPLEMENTED\n"); 332747ec646SMilanka Ringwald } else { 333747ec646SMilanka Ringwald log_error("avdtp packet handler L2CAP_DATA_PACKET: local cid 0x%02x not found", channel); 334747ec646SMilanka Ringwald } 335747ec646SMilanka Ringwald break; 336747ec646SMilanka Ringwald 337747ec646SMilanka Ringwald case HCI_EVENT_PACKET: 338747ec646SMilanka Ringwald switch (hci_event_packet_get_type(packet)) { 339747ec646SMilanka Ringwald case L2CAP_EVENT_INCOMING_CONNECTION: 340747ec646SMilanka Ringwald l2cap_event_incoming_connection_get_address(packet, event_addr); 341747ec646SMilanka Ringwald local_cid = l2cap_event_incoming_connection_get_local_cid(packet); 342747ec646SMilanka Ringwald 343747ec646SMilanka Ringwald connection = avdtp_connection_for_bd_addr(event_addr, context); 344747ec646SMilanka Ringwald if (!connection){ 345747ec646SMilanka Ringwald connection = avdtp_create_connection(event_addr, context); 346747ec646SMilanka Ringwald connection->state = AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED; 347747ec646SMilanka Ringwald l2cap_accept_connection(local_cid); 348747ec646SMilanka Ringwald break; 349747ec646SMilanka Ringwald } 350747ec646SMilanka Ringwald 351747ec646SMilanka Ringwald stream_endpoint = avdtp_stream_endpoint_for_seid(connection->query_seid, context); 352747ec646SMilanka Ringwald if (!stream_endpoint) { 353747ec646SMilanka Ringwald printf("L2CAP_EVENT_INCOMING_CONNECTION no streamendpoint found for seid %d\n", connection->query_seid); 354747ec646SMilanka Ringwald break; 355747ec646SMilanka Ringwald } 356747ec646SMilanka Ringwald 357747ec646SMilanka Ringwald if (stream_endpoint->l2cap_media_cid == 0){ 358747ec646SMilanka Ringwald if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED) break; 359747ec646SMilanka Ringwald l2cap_accept_connection(local_cid); 360747ec646SMilanka Ringwald break; 361747ec646SMilanka Ringwald } 362747ec646SMilanka Ringwald break; 363747ec646SMilanka Ringwald 364747ec646SMilanka Ringwald case L2CAP_EVENT_CHANNEL_OPENED: 365747ec646SMilanka Ringwald // inform about new l2cap connection 366747ec646SMilanka Ringwald l2cap_event_channel_opened_get_address(packet, event_addr); 367747ec646SMilanka Ringwald if (l2cap_event_channel_opened_get_status(packet)){ 368747ec646SMilanka Ringwald log_error("L2CAP connection to connection %s failed. status code 0x%02x", 369747ec646SMilanka Ringwald bd_addr_to_str(event_addr), l2cap_event_channel_opened_get_status(packet)); 370747ec646SMilanka Ringwald break; 371747ec646SMilanka Ringwald } 372747ec646SMilanka Ringwald psm = l2cap_event_channel_opened_get_psm(packet); 373*235946f1SMatthias Ringwald if (psm != BLUETOOTH_PROTOCOL_AVDTP){ 374747ec646SMilanka Ringwald log_error("unexpected PSM - Not implemented yet, avdtp sink: L2CAP_EVENT_CHANNEL_OPENED"); 375747ec646SMilanka Ringwald return; 376747ec646SMilanka Ringwald } 377747ec646SMilanka Ringwald 378747ec646SMilanka Ringwald con_handle = l2cap_event_channel_opened_get_handle(packet); 379747ec646SMilanka Ringwald local_cid = l2cap_event_channel_opened_get_local_cid(packet); 380747ec646SMilanka Ringwald 381747ec646SMilanka Ringwald // printf("L2CAP_EVENT_CHANNEL_OPENED: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n", 382747ec646SMilanka Ringwald // bd_addr_to_str(event_addr), con_handle, psm, local_cid, l2cap_event_channel_opened_get_remote_cid(packet)); 383747ec646SMilanka Ringwald 384*235946f1SMatthias Ringwald if (psm != BLUETOOTH_PROTOCOL_AVDTP) break; 385747ec646SMilanka Ringwald 386747ec646SMilanka Ringwald connection = avdtp_connection_for_bd_addr(event_addr, context); 387747ec646SMilanka Ringwald if (!connection) break; 388747ec646SMilanka Ringwald 389747ec646SMilanka Ringwald if (connection->l2cap_signaling_cid == 0) { 390747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED) break; 391747ec646SMilanka Ringwald connection->l2cap_signaling_cid = local_cid; 392747ec646SMilanka Ringwald connection->con_handle = con_handle; 393747ec646SMilanka Ringwald connection->query_seid = 0; 394747ec646SMilanka Ringwald connection->state = AVDTP_SIGNALING_CONNECTION_OPENED; 395747ec646SMilanka Ringwald printf(" -> AVDTP_SIGNALING_CONNECTION_OPENED, connection %p\n", connection); 396747ec646SMilanka Ringwald avdtp_signaling_emit_connection_established(context->avdtp_callback, con_handle, event_addr, 0); 397747ec646SMilanka Ringwald break; 398747ec646SMilanka Ringwald } 399747ec646SMilanka Ringwald 400747ec646SMilanka Ringwald stream_endpoint = avdtp_stream_endpoint_for_seid(connection->query_seid, context); 401747ec646SMilanka Ringwald if (!stream_endpoint){ 402747ec646SMilanka Ringwald printf("L2CAP_EVENT_CHANNEL_OPENED: stream_endpoint not found"); 403747ec646SMilanka Ringwald return; 404747ec646SMilanka Ringwald } 405747ec646SMilanka Ringwald stream_endpoint_state_machine(connection, stream_endpoint, HCI_EVENT_PACKET, L2CAP_EVENT_CHANNEL_OPENED, packet, size, context); 406747ec646SMilanka Ringwald break; 407747ec646SMilanka Ringwald 408747ec646SMilanka Ringwald case L2CAP_EVENT_CHANNEL_CLOSED: 409747ec646SMilanka Ringwald // data: event (8), len(8), channel (16) 410747ec646SMilanka Ringwald local_cid = l2cap_event_channel_closed_get_local_cid(packet); 411747ec646SMilanka Ringwald connection = avdtp_connection_for_l2cap_signaling_cid(local_cid, context); 412747ec646SMilanka Ringwald printf(" -> L2CAP_EVENT_CHANNEL_CLOSED signaling cid 0x%0x\n", local_cid); 413747ec646SMilanka Ringwald 414747ec646SMilanka Ringwald if (connection){ 415747ec646SMilanka Ringwald printf(" -> AVDTP_STREAM_ENDPOINT_IDLE, connection closed\n"); 416747ec646SMilanka Ringwald btstack_linked_list_remove(avdtp_connections, (btstack_linked_item_t*) connection); 417747ec646SMilanka Ringwald btstack_linked_list_iterator_t it; 418747ec646SMilanka Ringwald btstack_linked_list_iterator_init(&it, stream_endpoints); 419747ec646SMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 420747ec646SMilanka Ringwald avdtp_stream_endpoint_t * _stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); 421747ec646SMilanka Ringwald avdtp_initialize_stream_endpoint(_stream_endpoint); 422747ec646SMilanka Ringwald } 423747ec646SMilanka Ringwald break; 424747ec646SMilanka Ringwald } 425747ec646SMilanka Ringwald 426747ec646SMilanka Ringwald stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(local_cid, context); 427747ec646SMilanka Ringwald if (!stream_endpoint) return; 428747ec646SMilanka Ringwald 429747ec646SMilanka Ringwald stream_endpoint_state_machine(connection, stream_endpoint, HCI_EVENT_PACKET, L2CAP_EVENT_CHANNEL_CLOSED, packet, size, context); 430747ec646SMilanka Ringwald break; 431747ec646SMilanka Ringwald 432747ec646SMilanka Ringwald case HCI_EVENT_DISCONNECTION_COMPLETE: 433747ec646SMilanka Ringwald break; 434747ec646SMilanka Ringwald 435747ec646SMilanka Ringwald case L2CAP_EVENT_CAN_SEND_NOW: 436747ec646SMilanka Ringwald connection = avdtp_connection_for_l2cap_signaling_cid(channel, context); 437747ec646SMilanka Ringwald if (!connection) { 438747ec646SMilanka Ringwald stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(channel, context); 439747ec646SMilanka Ringwald if (!stream_endpoint->connection) break; 440747ec646SMilanka Ringwald if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND){ 441747ec646SMilanka Ringwald stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING; 442747ec646SMilanka Ringwald //send sbc 443747ec646SMilanka Ringwald uint8_t rtp_version = 2; 444747ec646SMilanka Ringwald uint8_t padding = 0; 4453f8ff0dcSMilanka Ringwald uint8_t extension = 0; 446747ec646SMilanka Ringwald uint8_t csrc_count = 0; 447747ec646SMilanka Ringwald uint8_t marker = 0; 4483f8ff0dcSMilanka Ringwald uint8_t payload_type = 0x60; 449747ec646SMilanka Ringwald uint16_t sequence_number = stream_endpoint->sequence_number; 450747ec646SMilanka Ringwald uint32_t timestamp = btstack_run_loop_get_time_ms(); 4513f8ff0dcSMilanka Ringwald uint32_t ssrc = 0x11223344; 452747ec646SMilanka Ringwald 453747ec646SMilanka Ringwald // rtp header (min size 12B) 454747ec646SMilanka Ringwald int pos = 0; 455747ec646SMilanka Ringwald int mtu = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid); 456747ec646SMilanka Ringwald 457747ec646SMilanka Ringwald uint8_t media_packet[mtu]; 4583f8ff0dcSMilanka Ringwald media_packet[pos++] = (rtp_version << 6) | (padding << 5) | (extension << 4) | csrc_count; 4593f8ff0dcSMilanka Ringwald media_packet[pos++] = (marker << 1) | payload_type; 4603f8ff0dcSMilanka Ringwald big_endian_store_16(media_packet, pos, sequence_number); 461747ec646SMilanka Ringwald pos += 2; 4623f8ff0dcSMilanka Ringwald big_endian_store_32(media_packet, pos, timestamp); 463747ec646SMilanka Ringwald pos += 4; 4643f8ff0dcSMilanka Ringwald big_endian_store_32(media_packet, pos, ssrc); // only used for multicast 465747ec646SMilanka Ringwald pos += 4; 466747ec646SMilanka Ringwald 467747ec646SMilanka Ringwald // media payload 468747ec646SMilanka Ringwald // sbc_header (size 1B) 469747ec646SMilanka Ringwald uint8_t sbc_header_index = pos; 470747ec646SMilanka Ringwald pos++; 471747ec646SMilanka Ringwald uint8_t fragmentation = 0; 472747ec646SMilanka Ringwald uint8_t starting_packet = 0; // set to 1 for the first packet of a fragmented SBC frame 473747ec646SMilanka Ringwald uint8_t last_packet = 0; // set to 1 for the last packet of a fragmented SBC frame 474747ec646SMilanka Ringwald uint8_t num_frames = 0; 475747ec646SMilanka Ringwald 476747ec646SMilanka Ringwald uint32_t total_sbc_bytes_read = 0; 477747ec646SMilanka Ringwald uint8_t sbc_frame_size = 0; 478747ec646SMilanka Ringwald // payload 479747ec646SMilanka Ringwald while (mtu - 13 - total_sbc_bytes_read >= 120 && btstack_ring_buffer_bytes_available(&stream_endpoint->sbc_ring_buffer)){ 480747ec646SMilanka Ringwald uint32_t number_of_bytes_read = 0; 481747ec646SMilanka Ringwald btstack_ring_buffer_read(&stream_endpoint->sbc_ring_buffer, &sbc_frame_size, 1, &number_of_bytes_read); 482747ec646SMilanka Ringwald btstack_ring_buffer_read(&stream_endpoint->sbc_ring_buffer, media_packet + pos, sbc_frame_size, &number_of_bytes_read); 483747ec646SMilanka Ringwald pos += sbc_frame_size; 484747ec646SMilanka Ringwald total_sbc_bytes_read += sbc_frame_size; 485747ec646SMilanka Ringwald num_frames++; 486747ec646SMilanka Ringwald // printf("send sbc frame: timestamp %d, seq. nr %d\n", timestamp, stream_endpoint->sequence_number); 487747ec646SMilanka Ringwald } 4883f8ff0dcSMilanka Ringwald media_packet[sbc_header_index] = (fragmentation << 7) | (starting_packet << 6) | (last_packet << 5) | num_frames; 489747ec646SMilanka Ringwald stream_endpoint->sequence_number++; 490747ec646SMilanka Ringwald l2cap_send(stream_endpoint->l2cap_media_cid, media_packet, pos); 491747ec646SMilanka Ringwald if (btstack_ring_buffer_bytes_available(&stream_endpoint->sbc_ring_buffer)){ 492747ec646SMilanka Ringwald stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND; 493747ec646SMilanka Ringwald l2cap_request_can_send_now_event(stream_endpoint->l2cap_media_cid); 494747ec646SMilanka Ringwald } 495747ec646SMilanka Ringwald } 496747ec646SMilanka Ringwald connection = stream_endpoint->connection; 497747ec646SMilanka Ringwald } 498747ec646SMilanka Ringwald avdtp_handle_can_send_now(connection, channel, context); 499747ec646SMilanka Ringwald break; 500747ec646SMilanka Ringwald default: 501747ec646SMilanka Ringwald printf("unknown HCI event type %02x\n", hci_event_packet_get_type(packet)); 502747ec646SMilanka Ringwald break; 503747ec646SMilanka Ringwald } 504747ec646SMilanka Ringwald break; 505747ec646SMilanka Ringwald 506747ec646SMilanka Ringwald default: 507747ec646SMilanka Ringwald // other packet type 508747ec646SMilanka Ringwald break; 509747ec646SMilanka Ringwald } 510747ec646SMilanka Ringwald } 511747ec646SMilanka Ringwald 512747ec646SMilanka Ringwald void avdtp_disconnect(uint16_t con_handle, avdtp_context_t * context){ 513747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 514747ec646SMilanka Ringwald if (!connection) return; 515747ec646SMilanka Ringwald if (connection->state == AVDTP_SIGNALING_CONNECTION_IDLE) return; 516747ec646SMilanka Ringwald if (connection->state == AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED) return; 517747ec646SMilanka Ringwald 518747ec646SMilanka Ringwald connection->disconnect = 1; 519747ec646SMilanka Ringwald avdtp_request_can_send_now_self(connection, connection->l2cap_signaling_cid); 520747ec646SMilanka Ringwald } 521747ec646SMilanka Ringwald 522747ec646SMilanka Ringwald void avdtp_open_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){ 523747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 524747ec646SMilanka Ringwald if (!connection){ 525747ec646SMilanka Ringwald printf("avdtp_media_connect: no connection for handle 0x%02x found\n", con_handle); 526747ec646SMilanka Ringwald return; 527747ec646SMilanka Ringwald } 528747ec646SMilanka Ringwald 529747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) { 530747ec646SMilanka Ringwald printf("avdtp_media_connect: wrong connection state %d\n", connection->state); 531747ec646SMilanka Ringwald return; 532747ec646SMilanka Ringwald } 533747ec646SMilanka Ringwald 534747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context); 535747ec646SMilanka Ringwald if (!stream_endpoint) { 536747ec646SMilanka Ringwald printf("avdtp_media_connect: no stream_endpoint with acp seid %d found\n", acp_seid); 537747ec646SMilanka Ringwald return; 538747ec646SMilanka Ringwald } 539747ec646SMilanka Ringwald 540747ec646SMilanka Ringwald if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED) return; 541747ec646SMilanka Ringwald if (stream_endpoint->remote_sep_index == 0xFF) return; 542747ec646SMilanka Ringwald 543747ec646SMilanka Ringwald connection->initiator_transaction_label++; 544747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 545747ec646SMilanka Ringwald connection->int_seid = stream_endpoint->sep.seid; 546747ec646SMilanka Ringwald stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_OPEN_STREAM; 547747ec646SMilanka Ringwald stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM; 548747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 549747ec646SMilanka Ringwald } 550747ec646SMilanka Ringwald 551747ec646SMilanka Ringwald void avdtp_start_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){ 552747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 553747ec646SMilanka Ringwald if (!connection){ 554747ec646SMilanka Ringwald printf("avdtp_media_connect: no connection for handle 0x%02x found\n", con_handle); 555747ec646SMilanka Ringwald return; 556747ec646SMilanka Ringwald } 557747ec646SMilanka Ringwald 558747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) { 559747ec646SMilanka Ringwald printf("avdtp_media_connect: wrong connection state %d\n", connection->state); 560747ec646SMilanka Ringwald return; 561747ec646SMilanka Ringwald } 562747ec646SMilanka Ringwald 563747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context); 564747ec646SMilanka Ringwald if (!stream_endpoint) { 565747ec646SMilanka Ringwald printf("avdtp_media_connect: no stream_endpoint with acp_seid %d found\n", acp_seid); 566747ec646SMilanka Ringwald return; 567747ec646SMilanka Ringwald } 568747ec646SMilanka Ringwald if (stream_endpoint->remote_sep_index == 0xFF) return; 569747ec646SMilanka Ringwald if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_OPENED) return; 570747ec646SMilanka Ringwald connection->initiator_transaction_label++; 571747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 572747ec646SMilanka Ringwald connection->int_seid = stream_endpoint->sep.seid; 573747ec646SMilanka Ringwald stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_START; 574747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 575747ec646SMilanka Ringwald } 576747ec646SMilanka Ringwald 577747ec646SMilanka Ringwald void avdtp_stop_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){ 578747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 579747ec646SMilanka Ringwald if (!connection){ 580747ec646SMilanka Ringwald printf("avdtp_stop_stream: no connection for handle 0x%02x found\n", con_handle); 581747ec646SMilanka Ringwald return; 582747ec646SMilanka Ringwald } 583747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) { 584747ec646SMilanka Ringwald printf("avdtp_stop_stream: wrong connection state %d\n", connection->state); 585747ec646SMilanka Ringwald return; 586747ec646SMilanka Ringwald } 587747ec646SMilanka Ringwald 588747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context); 589747ec646SMilanka Ringwald if (!stream_endpoint) { 590747ec646SMilanka Ringwald printf("avdtp_stop_stream: no stream_endpoint with acp seid %d found\n", acp_seid); 591747ec646SMilanka Ringwald return; 592747ec646SMilanka Ringwald } 593747ec646SMilanka Ringwald if (stream_endpoint->remote_sep_index == 0xFF) return; 594747ec646SMilanka Ringwald switch (stream_endpoint->state){ 595747ec646SMilanka Ringwald case AVDTP_STREAM_ENDPOINT_OPENED: 596747ec646SMilanka Ringwald case AVDTP_STREAM_ENDPOINT_STREAMING: 597747ec646SMilanka Ringwald printf(" AVDTP_INITIATOR_W2_STREAMING_STOP \n"); 598747ec646SMilanka Ringwald connection->initiator_transaction_label++; 599747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 600747ec646SMilanka Ringwald connection->int_seid = stream_endpoint->sep.seid; 601747ec646SMilanka Ringwald stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_STOP; 602747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 603747ec646SMilanka Ringwald break; 604747ec646SMilanka Ringwald default: 605747ec646SMilanka Ringwald break; 606747ec646SMilanka Ringwald } 607747ec646SMilanka Ringwald } 608747ec646SMilanka Ringwald 609747ec646SMilanka Ringwald void avdtp_abort_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){ 610747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 611747ec646SMilanka Ringwald if (!connection){ 612747ec646SMilanka Ringwald printf("avdtp_abort_stream: no connection for handle 0x%02x found\n", con_handle); 613747ec646SMilanka Ringwald return; 614747ec646SMilanka Ringwald } 615747ec646SMilanka Ringwald 616747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) { 617747ec646SMilanka Ringwald printf("avdtp_abort_stream: wrong connection state %d\n", connection->state); 618747ec646SMilanka Ringwald return; 619747ec646SMilanka Ringwald } 620747ec646SMilanka Ringwald 621747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context); 622747ec646SMilanka Ringwald if (!stream_endpoint) { 623747ec646SMilanka Ringwald printf("avdtp_abort_stream: no stream_endpoint for seid %d found\n", acp_seid); 624747ec646SMilanka Ringwald return; 625747ec646SMilanka Ringwald } 626747ec646SMilanka Ringwald if (stream_endpoint->remote_sep_index == 0xFF) return; 627747ec646SMilanka Ringwald switch (stream_endpoint->state){ 628747ec646SMilanka Ringwald case AVDTP_STREAM_ENDPOINT_CONFIGURED: 629747ec646SMilanka Ringwald case AVDTP_STREAM_ENDPOINT_CLOSING: 630747ec646SMilanka Ringwald case AVDTP_STREAM_ENDPOINT_OPENED: 631747ec646SMilanka Ringwald case AVDTP_STREAM_ENDPOINT_STREAMING: 632747ec646SMilanka Ringwald printf(" AVDTP_INITIATOR_W2_STREAMING_ABORT \n"); 633747ec646SMilanka Ringwald connection->initiator_transaction_label++; 634747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 635747ec646SMilanka Ringwald connection->int_seid = stream_endpoint->sep.seid; 636747ec646SMilanka Ringwald stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_ABORT; 637747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 638747ec646SMilanka Ringwald break; 639747ec646SMilanka Ringwald default: 640747ec646SMilanka Ringwald break; 641747ec646SMilanka Ringwald } 642747ec646SMilanka Ringwald } 643747ec646SMilanka Ringwald 644747ec646SMilanka Ringwald void avdtp_discover_stream_endpoints(uint16_t con_handle, avdtp_context_t * context){ 645747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 646747ec646SMilanka Ringwald if (!connection){ 647747ec646SMilanka Ringwald printf("avdtp_discover_stream_endpoints: no connection for handle 0x%02x found\n", con_handle); 648747ec646SMilanka Ringwald return; 649747ec646SMilanka Ringwald } 650747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; 651747ec646SMilanka Ringwald 652747ec646SMilanka Ringwald switch (connection->initiator_connection_state){ 653747ec646SMilanka Ringwald case AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE: 654747ec646SMilanka Ringwald connection->initiator_transaction_label++; 655747ec646SMilanka Ringwald connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS; 656747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 657747ec646SMilanka Ringwald break; 658747ec646SMilanka Ringwald default: 659747ec646SMilanka Ringwald printf("avdtp_discover_stream_endpoints: wrong state\n"); 660747ec646SMilanka Ringwald break; 661747ec646SMilanka Ringwald } 662747ec646SMilanka Ringwald } 663747ec646SMilanka Ringwald 664747ec646SMilanka Ringwald 665747ec646SMilanka Ringwald void avdtp_get_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){ 666747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 667747ec646SMilanka Ringwald if (!connection){ 668747ec646SMilanka Ringwald printf("avdtp_get_capabilities: no connection for handle 0x%02x found\n", con_handle); 669747ec646SMilanka Ringwald return; 670747ec646SMilanka Ringwald } 671747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; 672747ec646SMilanka Ringwald if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; 673747ec646SMilanka Ringwald connection->initiator_transaction_label++; 674747ec646SMilanka Ringwald connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES; 675747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 676747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 677747ec646SMilanka Ringwald } 678747ec646SMilanka Ringwald 679747ec646SMilanka Ringwald 680747ec646SMilanka Ringwald void avdtp_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){ 681747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 682747ec646SMilanka Ringwald if (!connection){ 683747ec646SMilanka Ringwald printf("avdtp_get_all_capabilities: no connection for handle 0x%02x found\n", con_handle); 684747ec646SMilanka Ringwald return; 685747ec646SMilanka Ringwald } 686747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; 687747ec646SMilanka Ringwald if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; 688747ec646SMilanka Ringwald connection->initiator_transaction_label++; 689747ec646SMilanka Ringwald connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES; 690747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 691747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 692747ec646SMilanka Ringwald } 693747ec646SMilanka Ringwald 694747ec646SMilanka Ringwald void avdtp_get_configuration(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){ 695747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 696747ec646SMilanka Ringwald if (!connection){ 697747ec646SMilanka Ringwald printf("avdtp_get_configuration: no connection for handle 0x%02x found\n", con_handle); 698747ec646SMilanka Ringwald return; 699747ec646SMilanka Ringwald } 700747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; 701747ec646SMilanka Ringwald if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; 702747ec646SMilanka Ringwald connection->initiator_transaction_label++; 703747ec646SMilanka Ringwald connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION; 704747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 705747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 706747ec646SMilanka Ringwald } 707747ec646SMilanka Ringwald 708747ec646SMilanka Ringwald void avdtp_set_configuration(uint16_t con_handle, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){ 709747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 710747ec646SMilanka Ringwald if (!connection){ 711747ec646SMilanka Ringwald log_error("avdtp_set_configuration: no connection for handle 0x%02x found\n", con_handle); 712747ec646SMilanka Ringwald return; 713747ec646SMilanka Ringwald } 714747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; 715747ec646SMilanka Ringwald if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; 716747ec646SMilanka Ringwald 717747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, context); 718747ec646SMilanka Ringwald if (!stream_endpoint) { 719747ec646SMilanka Ringwald log_error("avdtp_set_configuration: no initiator stream endpoint for seid %d\n", int_seid); 720747ec646SMilanka Ringwald return; 721747ec646SMilanka Ringwald } 722747ec646SMilanka Ringwald // printf("avdtp_set_configuration int seid %d, acp seid %d\n", int_seid, acp_seid); 723747ec646SMilanka Ringwald 724747ec646SMilanka Ringwald connection->initiator_transaction_label++; 725747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 726747ec646SMilanka Ringwald connection->int_seid = int_seid; 727747ec646SMilanka Ringwald connection->remote_capabilities_bitmap = configured_services_bitmap; 728747ec646SMilanka Ringwald connection->remote_capabilities = configuration; 729747ec646SMilanka Ringwald stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SET_CONFIGURATION; 730747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 731747ec646SMilanka Ringwald } 732747ec646SMilanka Ringwald 733747ec646SMilanka Ringwald void avdtp_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){ 734747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 735747ec646SMilanka Ringwald if (!connection){ 736747ec646SMilanka Ringwald printf("avdtp_reconfigure: no connection for handle 0x%02x found\n", con_handle); 737747ec646SMilanka Ringwald return; 738747ec646SMilanka Ringwald } 739747ec646SMilanka Ringwald //TODO: if opened only app capabilities, enable reconfigure for not opened 740747ec646SMilanka Ringwald if (connection->state < AVDTP_SIGNALING_CONNECTION_OPENED) return; 741747ec646SMilanka Ringwald if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; 742747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context); 743747ec646SMilanka Ringwald if (!stream_endpoint) return; 744747ec646SMilanka Ringwald if (stream_endpoint->remote_sep_index == 0xFF) return; 745747ec646SMilanka Ringwald connection->initiator_transaction_label++; 746747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 747747ec646SMilanka Ringwald connection->int_seid = stream_endpoint->sep.seid; 748747ec646SMilanka Ringwald connection->remote_capabilities_bitmap = configured_services_bitmap; 749747ec646SMilanka Ringwald connection->remote_capabilities = configuration; 750747ec646SMilanka Ringwald stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID; 751747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 752747ec646SMilanka Ringwald } 753747ec646SMilanka Ringwald 754747ec646SMilanka Ringwald void avdtp_suspend(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){ 755747ec646SMilanka Ringwald avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context); 756747ec646SMilanka Ringwald if (!connection){ 757747ec646SMilanka Ringwald printf("avdtp_suspend: no connection for handle 0x%02x found\n", con_handle); 758747ec646SMilanka Ringwald return; 759747ec646SMilanka Ringwald } 760747ec646SMilanka Ringwald if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return; 761747ec646SMilanka Ringwald if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return; 762747ec646SMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context); 763747ec646SMilanka Ringwald if (!stream_endpoint) return; 764747ec646SMilanka Ringwald if (stream_endpoint->remote_sep_index == 0xFF) return; 765747ec646SMilanka Ringwald connection->initiator_transaction_label++; 766747ec646SMilanka Ringwald connection->acp_seid = acp_seid; 767747ec646SMilanka Ringwald connection->int_seid = stream_endpoint->sep.seid; 768747ec646SMilanka Ringwald stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID; 769747ec646SMilanka Ringwald avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid); 770747ec646SMilanka Ringwald } 771