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