xref: /btstack/src/classic/avdtp.c (revision 3f8ff0dcb65ea613a0e1c9ef2f8b384c65a87bb9)
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