avdtp.c (5cfe7f4cc81075ececf34a61639f3bc15baacb2c) avdtp.c (6484b28a8cf2e8dc89acafacb3c57e97937a4b51)
1/*
2 * Copyright (C) 2016 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 36 unchanged lines hidden (view full) ---

45#include <unistd.h>
46
47#include "btstack.h"
48#include "avdtp.h"
49#include "avdtp_util.h"
50#include "avdtp_acceptor.h"
51#include "avdtp_initiator.h"
52
1/*
2 * Copyright (C) 2016 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 36 unchanged lines hidden (view full) ---

45#include <unistd.h>
46
47#include "btstack.h"
48#include "avdtp.h"
49#include "avdtp_util.h"
50#include "avdtp_acceptor.h"
51#include "avdtp_initiator.h"
52
53static uint8_t audio_samples_storage[44100*4]; // 1s buffer
54// static btstack_ring_buffer_t audio_ring_buffer;
55
56static uint8_t sbc_samples_storage[44100*4];
57// static btstack_ring_buffer_t sbc_ring_buffer;
58
53static void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
54
55void avdtp_register_media_transport_category(avdtp_stream_endpoint_t * stream_endpoint){
56 if (!stream_endpoint){
57 log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered");
58 return;
59 }
60 uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_TRANSPORT, 1);

--- 50 unchanged lines hidden (view full) ---

111 }
112 uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_HEADER_COMPRESSION, 1);
113 stream_endpoint->sep.registered_service_categories = bitmap;
114 stream_endpoint->sep.capabilities.header_compression.back_ch = back_ch;
115 stream_endpoint->sep.capabilities.header_compression.media = media;
116 stream_endpoint->sep.capabilities.header_compression.recovery = recovery;
117}
118
59static void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
60
61void avdtp_register_media_transport_category(avdtp_stream_endpoint_t * stream_endpoint){
62 if (!stream_endpoint){
63 log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered");
64 return;
65 }
66 uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_TRANSPORT, 1);

--- 50 unchanged lines hidden (view full) ---

117 }
118 uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_HEADER_COMPRESSION, 1);
119 stream_endpoint->sep.registered_service_categories = bitmap;
120 stream_endpoint->sep.capabilities.header_compression.back_ch = back_ch;
121 stream_endpoint->sep.capabilities.header_compression.media = media;
122 stream_endpoint->sep.capabilities.header_compression.recovery = recovery;
123}
124
119void 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, uint8_t * media_codec_info, uint16_t media_codec_info_len){
125void 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){
120 if (!stream_endpoint){
121 log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered");
122 return;
123 }
124 uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_CODEC, 1);
125 stream_endpoint->sep.registered_service_categories = bitmap;
126 printf("registered services AVDTP_MEDIA_CODEC(%d) %02x\n", AVDTP_MEDIA_CODEC, stream_endpoint->sep.registered_service_categories);
127 stream_endpoint->sep.capabilities.media_codec.media_type = media_type;

--- 64 unchanged lines hidden (view full) ---

192
193avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type, avdtp_context_t * context){
194 avdtp_stream_endpoint_t * stream_endpoint = btstack_memory_avdtp_stream_endpoint_get();
195 memset(stream_endpoint, 0, sizeof(avdtp_stream_endpoint_t));
196 context->stream_endpoints_id_counter++;
197 stream_endpoint->sep.seid = context->stream_endpoints_id_counter;
198 stream_endpoint->sep.media_type = media_type;
199 stream_endpoint->sep.type = sep_type;
126 if (!stream_endpoint){
127 log_error("avdtp_register_media_transport_category: stream endpoint with given seid is not registered");
128 return;
129 }
130 uint16_t bitmap = store_bit16(stream_endpoint->sep.registered_service_categories, AVDTP_MEDIA_CODEC, 1);
131 stream_endpoint->sep.registered_service_categories = bitmap;
132 printf("registered services AVDTP_MEDIA_CODEC(%d) %02x\n", AVDTP_MEDIA_CODEC, stream_endpoint->sep.registered_service_categories);
133 stream_endpoint->sep.capabilities.media_codec.media_type = media_type;

--- 64 unchanged lines hidden (view full) ---

198
199avdtp_stream_endpoint_t * avdtp_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type, avdtp_context_t * context){
200 avdtp_stream_endpoint_t * stream_endpoint = btstack_memory_avdtp_stream_endpoint_get();
201 memset(stream_endpoint, 0, sizeof(avdtp_stream_endpoint_t));
202 context->stream_endpoints_id_counter++;
203 stream_endpoint->sep.seid = context->stream_endpoints_id_counter;
204 stream_endpoint->sep.media_type = media_type;
205 stream_endpoint->sep.type = sep_type;
206
207 memset(audio_samples_storage, 0, sizeof(audio_samples_storage));
208 btstack_ring_buffer_init(&stream_endpoint->audio_ring_buffer, audio_samples_storage, sizeof(audio_samples_storage));
209
210 memset(sbc_samples_storage, 0, sizeof(sbc_samples_storage));
211 btstack_ring_buffer_init(&stream_endpoint->sbc_ring_buffer, sbc_samples_storage, sizeof(sbc_samples_storage));
212
213
200 btstack_linked_list_add(&context->stream_endpoints, (btstack_linked_item_t *) stream_endpoint);
201 return stream_endpoint;
202}
203
204
205static void handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t * connection, uint8_t *packet, uint16_t size, avdtp_context_t * context){
206 int offset = avdtp_read_signaling_header(&connection->signaling_packet, packet, size);
207 switch (connection->signaling_packet.message_type){

--- 21 unchanged lines hidden (view full) ---

229 case HCI_EVENT_PACKET:
230 switch (event){
231 case L2CAP_EVENT_CHANNEL_OPENED:
232 if (stream_endpoint->l2cap_media_cid == 0){
233 if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED) return;
234 stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
235 stream_endpoint->connection = connection;
236 stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet);
214 btstack_linked_list_add(&context->stream_endpoints, (btstack_linked_item_t *) stream_endpoint);
215 return stream_endpoint;
216}
217
218
219static void handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t * connection, uint8_t *packet, uint16_t size, avdtp_context_t * context){
220 int offset = avdtp_read_signaling_header(&connection->signaling_packet, packet, size);
221 switch (connection->signaling_packet.message_type){

--- 21 unchanged lines hidden (view full) ---

243 case HCI_EVENT_PACKET:
244 switch (event){
245 case L2CAP_EVENT_CHANNEL_OPENED:
246 if (stream_endpoint->l2cap_media_cid == 0){
247 if (stream_endpoint->state != AVDTP_STREAM_ENDPOINT_W4_L2CAP_FOR_MEDIA_CONNECTED) return;
248 stream_endpoint->state = AVDTP_STREAM_ENDPOINT_OPENED;
249 stream_endpoint->connection = connection;
250 stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet);
237 stream_endpoint->media_con_handle = l2cap_event_channel_opened_get_handle(packet);
238 printf(" -> AVDTP_STREAM_ENDPOINT_OPENED, media con handle 0x%02x, l2cap_media_cid 0x%02x\n", stream_endpoint->media_con_handle, stream_endpoint->l2cap_media_cid);
239 avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->l2cap_signaling_cid, stream_endpoint->sep.seid, connection->remote_seps[stream_endpoint->remote_sep_index].seid, 0);
251 printf(" -> AVDTP_STREAM_ENDPOINT_OPENED, stream endpoint %p, connection %p\n", stream_endpoint, connection);
252 avdtp_streaming_emit_connection_established(context->avdtp_callback, stream_endpoint->l2cap_media_cid, 0);
240 break;
241 }
242 break;
243 case L2CAP_EVENT_CHANNEL_CLOSED:
244 local_cid = l2cap_event_channel_closed_get_local_cid(packet);
245 if (stream_endpoint->l2cap_media_cid == local_cid){
246 stream_endpoint->l2cap_media_cid = 0;
247 printf(" -> L2CAP_EVENT_CHANNEL_CLOSED: AVDTP_STREAM_ENDPOINT_IDLE\n");
248 stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE;
249 stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
250 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
253 break;
254 }
255 break;
256 case L2CAP_EVENT_CHANNEL_CLOSED:
257 local_cid = l2cap_event_channel_closed_get_local_cid(packet);
258 if (stream_endpoint->l2cap_media_cid == local_cid){
259 stream_endpoint->l2cap_media_cid = 0;
260 printf(" -> L2CAP_EVENT_CHANNEL_CLOSED: AVDTP_STREAM_ENDPOINT_IDLE\n");
261 stream_endpoint->state = AVDTP_STREAM_ENDPOINT_IDLE;
262 stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_STREAM_CONFIG_IDLE;
263 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_STREAM_CONFIG_IDLE;
251 stream_endpoint->remote_sep_index = 0;
264 stream_endpoint->remote_seps_num = 0;
265 memset(stream_endpoint->remote_seps, 0, sizeof(avdtp_sep_t)*MAX_NUM_SEPS);
266 stream_endpoint->remote_sep_index = AVDTP_INVALID_SEP_INDEX;
252 break;
253 }
254 if (stream_endpoint->l2cap_recovery_cid == local_cid){
255 log_info(" -> L2CAP_EVENT_CHANNEL_CLOSED recovery cid 0x%0x", local_cid);
256 stream_endpoint->l2cap_recovery_cid = 0;
257 break;
258 }
259

--- 113 unchanged lines hidden (view full) ---

373
374 if (connection->l2cap_signaling_cid == 0) {
375 if (connection->state != AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED) break;
376 connection->l2cap_signaling_cid = local_cid;
377 connection->con_handle = con_handle;
378 connection->query_seid = 0;
379 connection->state = AVDTP_SIGNALING_CONNECTION_OPENED;
380 printf(" -> AVDTP_SIGNALING_CONNECTION_OPENED, connection %p\n", connection);
267 break;
268 }
269 if (stream_endpoint->l2cap_recovery_cid == local_cid){
270 log_info(" -> L2CAP_EVENT_CHANNEL_CLOSED recovery cid 0x%0x", local_cid);
271 stream_endpoint->l2cap_recovery_cid = 0;
272 break;
273 }
274

--- 113 unchanged lines hidden (view full) ---

388
389 if (connection->l2cap_signaling_cid == 0) {
390 if (connection->state != AVDTP_SIGNALING_CONNECTION_W4_L2CAP_CONNECTED) break;
391 connection->l2cap_signaling_cid = local_cid;
392 connection->con_handle = con_handle;
393 connection->query_seid = 0;
394 connection->state = AVDTP_SIGNALING_CONNECTION_OPENED;
395 printf(" -> AVDTP_SIGNALING_CONNECTION_OPENED, connection %p\n", connection);
381 avdtp_signaling_emit_connection_established(context->avdtp_callback, connection->l2cap_signaling_cid, event_addr, 0);
396 avdtp_signaling_emit_connection_established(context->avdtp_callback, con_handle, event_addr, 0);
382 break;
383 }
384
385 stream_endpoint = avdtp_stream_endpoint_for_seid(connection->query_seid, context);
386 if (!stream_endpoint){
387 printf("L2CAP_EVENT_CHANNEL_OPENED: stream_endpoint not found");
388 return;
389 }

--- 27 unchanged lines hidden (view full) ---

417 case HCI_EVENT_DISCONNECTION_COMPLETE:
418 break;
419
420 case L2CAP_EVENT_CAN_SEND_NOW:
421 connection = avdtp_connection_for_l2cap_signaling_cid(channel, context);
422 if (!connection) {
423 stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(channel, context);
424 if (!stream_endpoint->connection) break;
397 break;
398 }
399
400 stream_endpoint = avdtp_stream_endpoint_for_seid(connection->query_seid, context);
401 if (!stream_endpoint){
402 printf("L2CAP_EVENT_CHANNEL_OPENED: stream_endpoint not found");
403 return;
404 }

--- 27 unchanged lines hidden (view full) ---

432 case HCI_EVENT_DISCONNECTION_COMPLETE:
433 break;
434
435 case L2CAP_EVENT_CAN_SEND_NOW:
436 connection = avdtp_connection_for_l2cap_signaling_cid(channel, context);
437 if (!connection) {
438 stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(channel, context);
439 if (!stream_endpoint->connection) break;
440 if (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND){
441 stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;
442 //send sbc
443 uint8_t rtp_version = 2;
444 uint8_t padding = 0;
445 uint8_t extension = 0;
446 uint8_t csrc_count = 0;
447 uint8_t marker = 0;
448 uint8_t payload_type = 0x60;
449 uint16_t sequence_number = stream_endpoint->sequence_number;
450 uint32_t timestamp = btstack_run_loop_get_time_ms();
451 uint32_t ssrc = 0x11223344;
452
453 // rtp header (min size 12B)
454 int pos = 0;
455 int mtu = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
456
457 uint8_t media_packet[mtu];
458 media_packet[pos++] = (rtp_version << 6) | (padding << 5) | (extension << 4) | csrc_count;
459 media_packet[pos++] = (marker << 1) | payload_type;
460 big_endian_store_16(media_packet, pos, sequence_number);
461 pos += 2;
462 big_endian_store_32(media_packet, pos, timestamp);
463 pos += 4;
464 big_endian_store_32(media_packet, pos, ssrc); // only used for multicast
465 pos += 4;
466
467 // media payload
468 // sbc_header (size 1B)
469 uint8_t sbc_header_index = pos;
470 pos++;
471 uint8_t fragmentation = 0;
472 uint8_t starting_packet = 0; // set to 1 for the first packet of a fragmented SBC frame
473 uint8_t last_packet = 0; // set to 1 for the last packet of a fragmented SBC frame
474 uint8_t num_frames = 0;
475
476 uint32_t total_sbc_bytes_read = 0;
477 uint8_t sbc_frame_size = 0;
478 // payload
479 while (mtu - 13 - total_sbc_bytes_read >= 120 && btstack_ring_buffer_bytes_available(&stream_endpoint->sbc_ring_buffer)){
480 uint32_t number_of_bytes_read = 0;
481 btstack_ring_buffer_read(&stream_endpoint->sbc_ring_buffer, &sbc_frame_size, 1, &number_of_bytes_read);
482 btstack_ring_buffer_read(&stream_endpoint->sbc_ring_buffer, media_packet + pos, sbc_frame_size, &number_of_bytes_read);
483 pos += sbc_frame_size;
484 total_sbc_bytes_read += sbc_frame_size;
485 num_frames++;
486 // printf("send sbc frame: timestamp %d, seq. nr %d\n", timestamp, stream_endpoint->sequence_number);
487 }
488 media_packet[sbc_header_index] = (fragmentation << 7) | (starting_packet << 6) | (last_packet << 5) | num_frames;
489 stream_endpoint->sequence_number++;
490 l2cap_send(stream_endpoint->l2cap_media_cid, media_packet, pos);
491 if (btstack_ring_buffer_bytes_available(&stream_endpoint->sbc_ring_buffer)){
492 stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND;
493 l2cap_request_can_send_now_event(stream_endpoint->l2cap_media_cid);
494 }
495 }
425 connection = stream_endpoint->connection;
426 }
427 avdtp_handle_can_send_now(connection, channel, context);
428 break;
429 default:
430 printf("unknown HCI event type %02x\n", hci_event_packet_get_type(packet));
431 break;
432 }
433 break;
434
435 default:
436 // other packet type
437 break;
438 }
439}
440
496 connection = stream_endpoint->connection;
497 }
498 avdtp_handle_can_send_now(connection, channel, context);
499 break;
500 default:
501 printf("unknown HCI event type %02x\n", hci_event_packet_get_type(packet));
502 break;
503 }
504 break;
505
506 default:
507 // other packet type
508 break;
509 }
510}
511
441void avdtp_disconnect(uint16_t avdtp_cid, avdtp_context_t * context){
442 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
512void avdtp_disconnect(uint16_t con_handle, avdtp_context_t * context){
513 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
443 if (!connection) return;
444 if (connection->state == AVDTP_SIGNALING_CONNECTION_IDLE) return;
445 if (connection->state == AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED) return;
446
447 connection->disconnect = 1;
448 avdtp_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
449}
450
514 if (!connection) return;
515 if (connection->state == AVDTP_SIGNALING_CONNECTION_IDLE) return;
516 if (connection->state == AVDTP_SIGNALING_CONNECTION_W4_L2CAP_DISCONNECTED) return;
517
518 connection->disconnect = 1;
519 avdtp_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
520}
521
451void avdtp_open_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, avdtp_context_t * context){
452 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
522void avdtp_open_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
523 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
453 if (!connection){
524 if (!connection){
454 printf("avdtp_media_connect: no connection for signaling cid 0x%02x found\n", avdtp_cid);
525 printf("avdtp_media_connect: no connection for handle 0x%02x found\n", con_handle);
455 return;
456 }
526 return;
527 }
457 if (avdtp_find_remote_sep(connection, acp_seid) == 0xFF){
458 printf("avdtp_media_connect: no remote sep for seid %d found\n", acp_seid);
459 return;
460 }
461
528
462 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
463 printf("avdtp_media_connect: wrong connection state %d\n", connection->state);
464 return;
465 }
466
529 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
530 printf("avdtp_media_connect: wrong connection state %d\n", connection->state);
531 return;
532 }
533
467 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
534 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
468 if (!stream_endpoint) {
535 if (!stream_endpoint) {
469 printf("avdtp_media_connect: no stream_endpoint with seid %d found\n", int_seid);
536 printf("avdtp_media_connect: no stream_endpoint with acp seid %d found\n", acp_seid);
470 return;
471 }
472
473 if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED) return;
537 return;
538 }
539
540 if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_CONFIGURED) return;
474 if (stream_endpoint->remote_sep_index == 0xFF) return;
541 if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
475
476 connection->initiator_transaction_label++;
477 connection->acp_seid = acp_seid;
478 connection->int_seid = stream_endpoint->sep.seid;
479 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_OPEN_STREAM;
480 stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM;
481 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
482}
483
542
543 connection->initiator_transaction_label++;
544 connection->acp_seid = acp_seid;
545 connection->int_seid = stream_endpoint->sep.seid;
546 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_OPEN_STREAM;
547 stream_endpoint->state = AVDTP_STREAM_ENDPOINT_W2_REQUEST_OPEN_STREAM;
548 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
549}
550
484void avdtp_start_stream(uint8_t int_seid, avdtp_context_t * context){
485 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
486 if (!stream_endpoint) {
487 printf("avdtp_start_stream: no stream_endpoint with seid %d found\n", int_seid);
551void avdtp_start_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
552 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
553 if (!connection){
554 printf("avdtp_media_connect: no connection for handle 0x%02x found\n", con_handle);
488 return;
489 }
555 return;
556 }
490 avdtp_connection_t * connection = stream_endpoint->connection;
491 if (!connection){
492 printf("avdtp_start_stream: no connection for seid %d found\n",stream_endpoint->sep.seid);
557
558 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
559 printf("avdtp_media_connect: wrong connection state %d\n", connection->state);
493 return;
494 }
560 return;
561 }
495
496 if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->start_stream) return;
497 stream_endpoint->start_stream = 1;
498 connection->int_seid = int_seid;
499 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
500}
501
562
502void avdtp_stop_stream(uint8_t int_seid, avdtp_context_t * context){
503 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
563 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
504 if (!stream_endpoint) {
564 if (!stream_endpoint) {
505 printf("avdtp_stop_stream: no stream_endpoint with seid %d found\n", int_seid);
565 printf("avdtp_media_connect: no stream_endpoint with acp_seid %d found\n", acp_seid);
506 return;
507 }
566 return;
567 }
508 avdtp_connection_t * connection = stream_endpoint->connection;
568 if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
569 if (stream_endpoint->state < AVDTP_STREAM_ENDPOINT_OPENED) return;
570 connection->initiator_transaction_label++;
571 connection->acp_seid = acp_seid;
572 connection->int_seid = stream_endpoint->sep.seid;
573 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_START;
574 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
575}
576
577void avdtp_stop_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
578 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
509 if (!connection){
579 if (!connection){
510 printf("avdtp_stop_stream: no connection for seid %d found\n",stream_endpoint->sep.seid);
580 printf("avdtp_stop_stream: no connection for handle 0x%02x found\n", con_handle);
511 return;
512 }
581 return;
582 }
513 if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->stop_stream) return;
514 stream_endpoint->stop_stream = 1;
515 connection->int_seid = int_seid;
516 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
517}
583 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
584 printf("avdtp_stop_stream: wrong connection state %d\n", connection->state);
585 return;
586 }
518
587
519void avdtp_abort_stream(uint8_t int_seid, avdtp_context_t * context){
520 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
588 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
521 if (!stream_endpoint) {
589 if (!stream_endpoint) {
522 printf("avdtp_abort_stream: no stream_endpoint with seid %d found\n", int_seid);
590 printf("avdtp_stop_stream: no stream_endpoint with acp seid %d found\n", acp_seid);
523 return;
524 }
591 return;
592 }
525 avdtp_connection_t * connection = stream_endpoint->connection;
593 if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
594 switch (stream_endpoint->state){
595 case AVDTP_STREAM_ENDPOINT_OPENED:
596 case AVDTP_STREAM_ENDPOINT_STREAMING:
597 printf(" AVDTP_INITIATOR_W2_STREAMING_STOP \n");
598 connection->initiator_transaction_label++;
599 connection->acp_seid = acp_seid;
600 connection->int_seid = stream_endpoint->sep.seid;
601 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_STOP;
602 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
603 break;
604 default:
605 break;
606 }
607}
608
609void avdtp_abort_stream(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
610 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
526 if (!connection){
611 if (!connection){
527 printf("avdtp_abort_stream: no connection for seid %d found\n",stream_endpoint->sep.seid);
612 printf("avdtp_abort_stream: no connection for handle 0x%02x found\n", con_handle);
528 return;
529 }
613 return;
614 }
530 if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->abort_stream) return;
531 stream_endpoint->abort_stream = 1;
532 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
533}
615
616 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) {
617 printf("avdtp_abort_stream: wrong connection state %d\n", connection->state);
618 return;
619 }
534
620
535void avdtp_suspend_stream(uint8_t int_seid, avdtp_context_t * context){
536 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_with_seid(int_seid, context);
621 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
537 if (!stream_endpoint) {
622 if (!stream_endpoint) {
538 printf("avdtp_abort_stream: no stream_endpoint with seid %d found\n", int_seid);
623 printf("avdtp_abort_stream: no stream_endpoint for seid %d found\n", acp_seid);
539 return;
540 }
624 return;
625 }
541 avdtp_connection_t * connection = stream_endpoint->connection;
542 if (!connection){
543 printf("avdtp_abort_stream: no connection for seid %d found\n",stream_endpoint->sep.seid);
544 return;
626 if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
627 switch (stream_endpoint->state){
628 case AVDTP_STREAM_ENDPOINT_CONFIGURED:
629 case AVDTP_STREAM_ENDPOINT_CLOSING:
630 case AVDTP_STREAM_ENDPOINT_OPENED:
631 case AVDTP_STREAM_ENDPOINT_STREAMING:
632 printf(" AVDTP_INITIATOR_W2_STREAMING_ABORT \n");
633 connection->initiator_transaction_label++;
634 connection->acp_seid = acp_seid;
635 connection->int_seid = stream_endpoint->sep.seid;
636 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_STREAMING_ABORT;
637 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
638 break;
639 default:
640 break;
545 }
641 }
546 if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->suspend_stream) return;
547 stream_endpoint->suspend_stream = 1;
548 connection->int_seid = int_seid;
549 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
550}
551
642}
643
552void avdtp_discover_stream_endpoints(uint16_t avdtp_cid, avdtp_context_t * context){
553 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
644void avdtp_discover_stream_endpoints(uint16_t con_handle, avdtp_context_t * context){
645 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
554 if (!connection){
646 if (!connection){
555 printf("avdtp_discover_stream_endpoints: no connection for signaling cid 0x%02x found\n", avdtp_cid);
647 printf("avdtp_discover_stream_endpoints: no connection for handle 0x%02x found\n", con_handle);
556 return;
557 }
558 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
559
560 switch (connection->initiator_connection_state){
561 case AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE:
562 connection->initiator_transaction_label++;
563 connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS;
564 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
565 break;
566 default:
567 printf("avdtp_discover_stream_endpoints: wrong state\n");
568 break;
569 }
570}
571
572
648 return;
649 }
650 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
651
652 switch (connection->initiator_connection_state){
653 case AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE:
654 connection->initiator_transaction_label++;
655 connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS;
656 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
657 break;
658 default:
659 printf("avdtp_discover_stream_endpoints: wrong state\n");
660 break;
661 }
662}
663
664
573void avdtp_get_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context){
574 printf("avdtp_get_capabilities: acp_seid %d\n", acp_seid);
575 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
665void avdtp_get_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
666 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
576 if (!connection){
667 if (!connection){
577 printf("avdtp_get_capabilities: no connection for signaling cid 0x%02x found\n", avdtp_cid);
668 printf("avdtp_get_capabilities: no connection for handle 0x%02x found\n", con_handle);
578 return;
579 }
580 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
581 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
582 connection->initiator_transaction_label++;
583 connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES;
584 connection->acp_seid = acp_seid;
585 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
586}
587
588
669 return;
670 }
671 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
672 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
673 connection->initiator_transaction_label++;
674 connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CAPABILITIES;
675 connection->acp_seid = acp_seid;
676 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
677}
678
679
589void avdtp_get_all_capabilities(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context){
590 printf("avdtp_get_all_capabilities: acp_seid %d\n", acp_seid);
591 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
680void avdtp_get_all_capabilities(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
681 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
592 if (!connection){
682 if (!connection){
593 printf("avdtp_get_all_capabilities: no connection for signaling cid 0x%02x found\n", avdtp_cid);
683 printf("avdtp_get_all_capabilities: no connection for handle 0x%02x found\n", con_handle);
594 return;
595 }
596 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
597 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
598 connection->initiator_transaction_label++;
599 connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES;
600 connection->acp_seid = acp_seid;
601 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
602}
603
684 return;
685 }
686 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
687 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
688 connection->initiator_transaction_label++;
689 connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_ALL_CAPABILITIES;
690 connection->acp_seid = acp_seid;
691 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
692}
693
604void avdtp_get_configuration(uint16_t avdtp_cid, uint8_t acp_seid, avdtp_context_t * context){
605 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
694void avdtp_get_configuration(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
695 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
606 if (!connection){
696 if (!connection){
607 printf("avdtp_get_configuration: no connection for signaling cid 0x%02x found\n", avdtp_cid);
697 printf("avdtp_get_configuration: no connection for handle 0x%02x found\n", con_handle);
608 return;
609 }
610 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
611 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
612 connection->initiator_transaction_label++;
613 connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION;
614 connection->acp_seid = acp_seid;
615 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
616}
617
698 return;
699 }
700 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
701 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
702 connection->initiator_transaction_label++;
703 connection->initiator_connection_state = AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_GET_CONFIGURATION;
704 connection->acp_seid = acp_seid;
705 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
706}
707
618void avdtp_set_configuration(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
619 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
708void 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){
709 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
620 if (!connection){
710 if (!connection){
621 log_error("avdtp_set_configuration: no connection for signaling cid 0x%02x found\n", avdtp_cid);
711 log_error("avdtp_set_configuration: no connection for handle 0x%02x found\n", con_handle);
622 return;
623 }
624 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
625 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
626
627 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, context);
628 if (!stream_endpoint) {
629 log_error("avdtp_set_configuration: no initiator stream endpoint for seid %d\n", int_seid);
630 return;
631 }
632 // printf("avdtp_set_configuration int seid %d, acp seid %d\n", int_seid, acp_seid);
633
634 connection->initiator_transaction_label++;
635 connection->acp_seid = acp_seid;
636 connection->int_seid = int_seid;
712 return;
713 }
714 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
715 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
716
717 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, context);
718 if (!stream_endpoint) {
719 log_error("avdtp_set_configuration: no initiator stream endpoint for seid %d\n", int_seid);
720 return;
721 }
722 // printf("avdtp_set_configuration int seid %d, acp seid %d\n", int_seid, acp_seid);
723
724 connection->initiator_transaction_label++;
725 connection->acp_seid = acp_seid;
726 connection->int_seid = int_seid;
637 stream_endpoint->remote_capabilities_bitmap = configured_services_bitmap;
638 stream_endpoint->remote_capabilities = configuration;
727 connection->remote_capabilities_bitmap = configured_services_bitmap;
728 connection->remote_capabilities = configuration;
639 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SET_CONFIGURATION;
640 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
641}
642
729 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SET_CONFIGURATION;
730 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
731}
732
643void avdtp_reconfigure(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
644 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
733void avdtp_reconfigure(uint16_t con_handle, uint8_t acp_seid, uint16_t configured_services_bitmap, avdtp_capabilities_t configuration, avdtp_context_t * context){
734 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
645 if (!connection){
735 if (!connection){
646 printf("avdtp_reconfigure: no connection for signaling cid 0x%02x found\n", avdtp_cid);
736 printf("avdtp_reconfigure: no connection for handle 0x%02x found\n", con_handle);
647 return;
648 }
649 //TODO: if opened only app capabilities, enable reconfigure for not opened
650 if (connection->state < AVDTP_SIGNALING_CONNECTION_OPENED) return;
651 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
737 return;
738 }
739 //TODO: if opened only app capabilities, enable reconfigure for not opened
740 if (connection->state < AVDTP_SIGNALING_CONNECTION_OPENED) return;
741 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
652
653 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, context);
654 if (!stream_endpoint) {
655 log_error("avdtp_reconfigure: no initiator stream endpoint for seid %d\n", int_seid);
656 return;
657 }
658
659 if (stream_endpoint->remote_sep_index == 0xFF){
660 log_error("avdtp_reconfigure: no associated remote sep\n");
661 return;
662 }
663
742 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
743 if (!stream_endpoint) return;
744 if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
664 connection->initiator_transaction_label++;
665 connection->acp_seid = acp_seid;
666 connection->int_seid = stream_endpoint->sep.seid;
745 connection->initiator_transaction_label++;
746 connection->acp_seid = acp_seid;
747 connection->int_seid = stream_endpoint->sep.seid;
667 stream_endpoint->remote_capabilities_bitmap = configured_services_bitmap;
668 stream_endpoint->remote_capabilities = configuration;
748 connection->remote_capabilities_bitmap = configured_services_bitmap;
749 connection->remote_capabilities = configuration;
669 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID;
670 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
671}
672
750 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_RECONFIGURE_STREAM_WITH_SEID;
751 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
752}
753
673uint8_t avdtp_remote_seps_num(uint16_t avdtp_cid, avdtp_context_t * context){
674 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
754void avdtp_suspend(uint16_t con_handle, uint8_t acp_seid, avdtp_context_t * context){
755 avdtp_connection_t * connection = avdtp_connection_for_con_handle(con_handle, context);
675 if (!connection){
756 if (!connection){
676 printf("avdtp_suspend: no connection for signaling cid 0x%02x found\n", avdtp_cid);
677 return 0;
678 }
679 return connection->remote_seps_num;
680}
681
682avdtp_sep_t * avdtp_remote_sep(uint16_t avdtp_cid, uint8_t index, avdtp_context_t * context){
683 avdtp_connection_t * connection = avdtp_connection_for_l2cap_signaling_cid(avdtp_cid, context);
684 if (!connection){
685 printf("avdtp_suspend: no connection for signaling cid 0x%02x found\n", avdtp_cid);
686 return NULL;
687 }
688 return &connection->remote_seps[index];
689}
690
691void avdtp_initialize_sbc_configuration_storage(avdtp_stream_endpoint_t * stream_endpoint, uint8_t * config_storage, uint16_t storage_size, uint8_t * packet, uint16_t packet_size){
692 UNUSED(packet_size);
693 if (storage_size < 4) {
694 printf("storage must have 4 bytes\n");
757 printf("avdtp_suspend: no connection for handle 0x%02x found\n", con_handle);
695 return;
696 }
758 return;
759 }
697 uint8_t sampling_frequency = avdtp_choose_sbc_sampling_frequency(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet));
698 uint8_t channel_mode = avdtp_choose_sbc_channel_mode(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet));
699 uint8_t block_length = avdtp_choose_sbc_block_length(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet));
700 uint8_t subbands = avdtp_choose_sbc_subbands(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet));
701
702 uint8_t allocation_method = avdtp_choose_sbc_allocation_method(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet));
703 uint8_t max_bitpool_value = avdtp_choose_sbc_max_bitpool_value(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet));
704 uint8_t min_bitpool_value = avdtp_choose_sbc_min_bitpool_value(stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet));
705
706 config_storage[0] = (sampling_frequency << 4) | channel_mode;
707 config_storage[1] = (block_length << 4) | (subbands << 2) | allocation_method;
708 config_storage[2] = min_bitpool_value;
709 config_storage[3] = max_bitpool_value;
710
711 stream_endpoint->remote_configuration_bitmap = store_bit16(stream_endpoint->remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
712 stream_endpoint->remote_configuration.media_codec.media_type = AVDTP_AUDIO;
713 stream_endpoint->remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
714 stream_endpoint->remote_configuration.media_codec.media_codec_information_len = storage_size;
715 stream_endpoint->remote_configuration.media_codec.media_codec_information = config_storage;
760 if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return;
761 if (connection->initiator_connection_state != AVDTP_SIGNALING_CONNECTION_INITIATOR_IDLE) return;
762 avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(acp_seid, context);
763 if (!stream_endpoint) return;
764 if (stream_endpoint->remote_sep_index == AVDTP_INVALID_SEP_INDEX) return;
765 connection->initiator_transaction_label++;
766 connection->acp_seid = acp_seid;
767 connection->int_seid = stream_endpoint->sep.seid;
768 stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W2_SUSPEND_STREAM_WITH_SEID;
769 avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
716}
770}
717
718uint8_t avdtp_choose_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_channel_mode_bitmap){
719 uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
720 uint8_t channel_mode_bitmap = (media_codec[0] & 0x0F) & remote_channel_mode_bitmap;
721
722 uint8_t channel_mode = AVDTP_SBC_STEREO;
723 if (channel_mode_bitmap & AVDTP_SBC_JOINT_STEREO){
724 channel_mode = AVDTP_SBC_JOINT_STEREO;
725 } else if (channel_mode_bitmap & AVDTP_SBC_STEREO){
726 channel_mode = AVDTP_SBC_STEREO;
727 } else if (channel_mode_bitmap & AVDTP_SBC_DUAL_CHANNEL){
728 channel_mode = AVDTP_SBC_DUAL_CHANNEL;
729 } else if (channel_mode_bitmap & AVDTP_SBC_MONO){
730 channel_mode = AVDTP_SBC_MONO;
731 }
732 return channel_mode;
733}
734
735uint8_t avdtp_choose_sbc_allocation_method(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_allocation_method_bitmap){
736 uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
737 uint8_t allocation_method_bitmap = (media_codec[1] & 0x03) & remote_allocation_method_bitmap;
738
739 uint8_t allocation_method = AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS;
740 if (allocation_method_bitmap & AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS){
741 allocation_method = AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS;
742 } else if (allocation_method_bitmap & AVDTP_SBC_ALLOCATION_METHOD_SNR){
743 allocation_method = AVDTP_SBC_ALLOCATION_METHOD_SNR;
744 }
745 return allocation_method;
746}
747
748uint8_t avdtp_stream_endpoint_seid(avdtp_stream_endpoint_t * stream_endpoint){
749 if (!stream_endpoint) return 0;
750 return stream_endpoint->sep.seid;
751}
752uint8_t avdtp_choose_sbc_subbands(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_subbands_bitmap){
753 uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
754 uint8_t subbands_bitmap = ((media_codec[1] >> 2) & 0x03) & remote_subbands_bitmap;
755
756 uint8_t subbands = AVDTP_SBC_SUBBANDS_8;
757 if (subbands_bitmap & AVDTP_SBC_SUBBANDS_8){
758 subbands = AVDTP_SBC_SUBBANDS_8;
759 } else if (subbands_bitmap & AVDTP_SBC_SUBBANDS_4){
760 subbands = AVDTP_SBC_SUBBANDS_4;
761 }
762 return subbands;
763}
764
765uint8_t avdtp_choose_sbc_block_length(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_block_length_bitmap){
766 uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
767 uint8_t block_length_bitmap = (media_codec[1] >> 4) & remote_block_length_bitmap;
768
769 uint8_t block_length = AVDTP_SBC_BLOCK_LENGTH_16;
770 if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_16){
771 block_length = AVDTP_SBC_BLOCK_LENGTH_16;
772 } else if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_12){
773 block_length = AVDTP_SBC_BLOCK_LENGTH_12;
774 } else if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_8){
775 block_length = AVDTP_SBC_BLOCK_LENGTH_8;
776 } else if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_4){
777 block_length = AVDTP_SBC_BLOCK_LENGTH_4;
778 }
779 return block_length;
780}
781
782uint8_t avdtp_choose_sbc_sampling_frequency(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_sampling_frequency_bitmap){
783 uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
784 uint8_t sampling_frequency_bitmap = (media_codec[0] >> 4) & remote_sampling_frequency_bitmap;
785
786 uint8_t sampling_frequency = AVDTP_SBC_44100;
787 if (sampling_frequency_bitmap & AVDTP_SBC_48000){
788 sampling_frequency = AVDTP_SBC_48000;
789 } else if (sampling_frequency_bitmap & AVDTP_SBC_44100){
790 sampling_frequency = AVDTP_SBC_44100;
791 } else if (sampling_frequency_bitmap & AVDTP_SBC_32000){
792 sampling_frequency = AVDTP_SBC_32000;
793 } else if (sampling_frequency_bitmap & AVDTP_SBC_16000){
794 sampling_frequency = AVDTP_SBC_16000;
795 }
796 return sampling_frequency;
797}
798
799uint8_t avdtp_choose_sbc_max_bitpool_value(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_max_bitpool_value){
800 uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
801 return btstack_min(media_codec[3], remote_max_bitpool_value);
802}
803
804uint8_t avdtp_choose_sbc_min_bitpool_value(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_min_bitpool_value){
805 uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information;
806 return btstack_max(media_codec[2], remote_min_bitpool_value);
807}