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