1*8ef7100fSMilanka Ringwald /* 2*8ef7100fSMilanka Ringwald * Copyright (C) 2016 BlueKitchen GmbH 3*8ef7100fSMilanka Ringwald * 4*8ef7100fSMilanka Ringwald * Redistribution and use in source and binary forms, with or without 5*8ef7100fSMilanka Ringwald * modification, are permitted provided that the following conditions 6*8ef7100fSMilanka Ringwald * are met: 7*8ef7100fSMilanka Ringwald * 8*8ef7100fSMilanka Ringwald * 1. Redistributions of source code must retain the above copyright 9*8ef7100fSMilanka Ringwald * notice, this list of conditions and the following disclaimer. 10*8ef7100fSMilanka Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*8ef7100fSMilanka Ringwald * notice, this list of conditions and the following disclaimer in the 12*8ef7100fSMilanka Ringwald * documentation and/or other materials provided with the distribution. 13*8ef7100fSMilanka Ringwald * 3. Neither the name of the copyright holders nor the names of 14*8ef7100fSMilanka Ringwald * contributors may be used to endorse or promote products derived 15*8ef7100fSMilanka Ringwald * from this software without specific prior written permission. 16*8ef7100fSMilanka Ringwald * 4. Any redistribution, use, or modification is done solely for 17*8ef7100fSMilanka Ringwald * personal benefit and not for any commercial purpose or for 18*8ef7100fSMilanka Ringwald * monetary gain. 19*8ef7100fSMilanka Ringwald * 20*8ef7100fSMilanka Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*8ef7100fSMilanka Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*8ef7100fSMilanka Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*8ef7100fSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*8ef7100fSMilanka Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*8ef7100fSMilanka Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*8ef7100fSMilanka Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*8ef7100fSMilanka Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*8ef7100fSMilanka Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*8ef7100fSMilanka Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*8ef7100fSMilanka Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*8ef7100fSMilanka Ringwald * SUCH DAMAGE. 32*8ef7100fSMilanka Ringwald * 33*8ef7100fSMilanka Ringwald * Please inquire about commercial licensing options at 34*8ef7100fSMilanka Ringwald * [email protected] 35*8ef7100fSMilanka Ringwald * 36*8ef7100fSMilanka Ringwald */ 37*8ef7100fSMilanka Ringwald 38*8ef7100fSMilanka Ringwald 39*8ef7100fSMilanka Ringwald #include <stdint.h> 40*8ef7100fSMilanka Ringwald #include <stdio.h> 41*8ef7100fSMilanka Ringwald #include <stdlib.h> 42*8ef7100fSMilanka Ringwald #include <string.h> 43*8ef7100fSMilanka Ringwald #include <unistd.h> 44*8ef7100fSMilanka Ringwald 45*8ef7100fSMilanka Ringwald #include "btstack.h" 46*8ef7100fSMilanka Ringwald #include "avdtp.h" 47*8ef7100fSMilanka Ringwald #include "avdtp_util.h" 48*8ef7100fSMilanka Ringwald 49*8ef7100fSMilanka Ringwald inline uint8_t avdtp_header(uint8_t tr_label, avdtp_packet_type_t packet_type, avdtp_message_type_t msg_type){ 50*8ef7100fSMilanka Ringwald return (tr_label<<4) | ((uint8_t)packet_type<<2) | (uint8_t)msg_type; 51*8ef7100fSMilanka Ringwald } 52*8ef7100fSMilanka Ringwald 53*8ef7100fSMilanka Ringwald avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_with_seid(uint8_t seid){ 54*8ef7100fSMilanka Ringwald btstack_linked_list_iterator_t it; 55*8ef7100fSMilanka Ringwald btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &stream_endpoints); 56*8ef7100fSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 57*8ef7100fSMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); 58*8ef7100fSMilanka Ringwald if (stream_endpoint->sep.seid == seid){ 59*8ef7100fSMilanka Ringwald return stream_endpoint; 60*8ef7100fSMilanka Ringwald } 61*8ef7100fSMilanka Ringwald } 62*8ef7100fSMilanka Ringwald return NULL; 63*8ef7100fSMilanka Ringwald } 64*8ef7100fSMilanka Ringwald 65*8ef7100fSMilanka Ringwald avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_associated_with_acp_seid(uint16_t acp_seid){ 66*8ef7100fSMilanka Ringwald btstack_linked_list_iterator_t it; 67*8ef7100fSMilanka Ringwald btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &stream_endpoints); 68*8ef7100fSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 69*8ef7100fSMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); 70*8ef7100fSMilanka Ringwald if (stream_endpoint->remote_sep_index >= 0 && stream_endpoint->remote_sep_index < MAX_NUM_SEPS){ 71*8ef7100fSMilanka Ringwald if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid == acp_seid){ 72*8ef7100fSMilanka Ringwald return stream_endpoint; 73*8ef7100fSMilanka Ringwald } 74*8ef7100fSMilanka Ringwald } 75*8ef7100fSMilanka Ringwald } 76*8ef7100fSMilanka Ringwald return NULL; 77*8ef7100fSMilanka Ringwald } 78*8ef7100fSMilanka Ringwald 79*8ef7100fSMilanka Ringwald int get_bit16(uint16_t bitmap, int position){ 80*8ef7100fSMilanka Ringwald return (bitmap >> position) & 1; 81*8ef7100fSMilanka Ringwald } 82*8ef7100fSMilanka Ringwald 83*8ef7100fSMilanka Ringwald uint8_t store_bit16(uint16_t bitmap, int position, uint8_t value){ 84*8ef7100fSMilanka Ringwald if (value){ 85*8ef7100fSMilanka Ringwald bitmap |= 1 << position; 86*8ef7100fSMilanka Ringwald } else { 87*8ef7100fSMilanka Ringwald bitmap &= ~ (1 << position); 88*8ef7100fSMilanka Ringwald } 89*8ef7100fSMilanka Ringwald return bitmap; 90*8ef7100fSMilanka Ringwald } 91*8ef7100fSMilanka Ringwald 92*8ef7100fSMilanka Ringwald int avdtp_read_signaling_header(avdtp_signaling_packet_t * signaling_header, uint8_t * packet, uint16_t size){ 93*8ef7100fSMilanka Ringwald int pos = 0; 94*8ef7100fSMilanka Ringwald if (size < 2) return pos; 95*8ef7100fSMilanka Ringwald signaling_header->transaction_label = packet[pos] >> 4; 96*8ef7100fSMilanka Ringwald signaling_header->packet_type = (avdtp_packet_type_t)((packet[pos] >> 2) & 0x03); 97*8ef7100fSMilanka Ringwald signaling_header->message_type = (avdtp_message_type_t) (packet[pos] & 0x03); 98*8ef7100fSMilanka Ringwald pos++; 99*8ef7100fSMilanka Ringwald memset(signaling_header->command, 0, sizeof(signaling_header->command)); 100*8ef7100fSMilanka Ringwald switch (signaling_header->packet_type){ 101*8ef7100fSMilanka Ringwald case AVDTP_SINGLE_PACKET: 102*8ef7100fSMilanka Ringwald signaling_header->num_packets = 0; 103*8ef7100fSMilanka Ringwald signaling_header->offset = 0; 104*8ef7100fSMilanka Ringwald signaling_header->size = 0; 105*8ef7100fSMilanka Ringwald break; 106*8ef7100fSMilanka Ringwald case AVDTP_END_PACKET: 107*8ef7100fSMilanka Ringwald signaling_header->num_packets = 0; 108*8ef7100fSMilanka Ringwald break; 109*8ef7100fSMilanka Ringwald case AVDTP_START_PACKET: 110*8ef7100fSMilanka Ringwald signaling_header->num_packets = packet[pos++]; 111*8ef7100fSMilanka Ringwald signaling_header->size = 0; 112*8ef7100fSMilanka Ringwald signaling_header->offset = 0; 113*8ef7100fSMilanka Ringwald break; 114*8ef7100fSMilanka Ringwald case AVDTP_CONTINUE_PACKET: 115*8ef7100fSMilanka Ringwald if (signaling_header->num_packets <= 0) { 116*8ef7100fSMilanka Ringwald printf(" ERROR: wrong num fragmented packets\n"); 117*8ef7100fSMilanka Ringwald break; 118*8ef7100fSMilanka Ringwald } 119*8ef7100fSMilanka Ringwald signaling_header->num_packets--; 120*8ef7100fSMilanka Ringwald break; 121*8ef7100fSMilanka Ringwald } 122*8ef7100fSMilanka Ringwald signaling_header->signal_identifier = packet[pos++] & 0x3f; 123*8ef7100fSMilanka Ringwald return pos; 124*8ef7100fSMilanka Ringwald } 125*8ef7100fSMilanka Ringwald 126*8ef7100fSMilanka Ringwald int avdtp_pack_service_capabilities(uint8_t * buffer, int size, avdtp_capabilities_t caps, avdtp_service_category_t category, uint8_t pack_all_capabilities){ 127*8ef7100fSMilanka Ringwald UNUSED(size); 128*8ef7100fSMilanka Ringwald 129*8ef7100fSMilanka Ringwald int i; 130*8ef7100fSMilanka Ringwald // pos = 0 reserved for length 131*8ef7100fSMilanka Ringwald int pos = 1; 132*8ef7100fSMilanka Ringwald switch(category){ 133*8ef7100fSMilanka Ringwald case AVDTP_MEDIA_TRANSPORT: 134*8ef7100fSMilanka Ringwald case AVDTP_REPORTING: 135*8ef7100fSMilanka Ringwald break; 136*8ef7100fSMilanka Ringwald case AVDTP_DELAY_REPORTING: 137*8ef7100fSMilanka Ringwald if (!pack_all_capabilities) break; 138*8ef7100fSMilanka Ringwald break; 139*8ef7100fSMilanka Ringwald case AVDTP_RECOVERY: 140*8ef7100fSMilanka Ringwald buffer[pos++] = caps.recovery.recovery_type; // 0x01=RFC2733 141*8ef7100fSMilanka Ringwald buffer[pos++] = caps.recovery.maximum_recovery_window_size; 142*8ef7100fSMilanka Ringwald buffer[pos++] = caps.recovery.maximum_number_media_packets; 143*8ef7100fSMilanka Ringwald break; 144*8ef7100fSMilanka Ringwald case AVDTP_CONTENT_PROTECTION: 145*8ef7100fSMilanka Ringwald buffer[pos++] = caps.content_protection.cp_type_value_len + 2; 146*8ef7100fSMilanka Ringwald big_endian_store_16(buffer, pos, caps.content_protection.cp_type); 147*8ef7100fSMilanka Ringwald pos += 2; 148*8ef7100fSMilanka Ringwald memcpy(buffer+pos, caps.content_protection.cp_type_value, caps.content_protection.cp_type_value_len); 149*8ef7100fSMilanka Ringwald break; 150*8ef7100fSMilanka Ringwald case AVDTP_HEADER_COMPRESSION: 151*8ef7100fSMilanka Ringwald buffer[pos++] = (caps.header_compression.back_ch << 7) | (caps.header_compression.media << 6) | (caps.header_compression.recovery << 5); 152*8ef7100fSMilanka Ringwald break; 153*8ef7100fSMilanka Ringwald case AVDTP_MULTIPLEXING: 154*8ef7100fSMilanka Ringwald buffer[pos++] = caps.multiplexing_mode.fragmentation << 7; 155*8ef7100fSMilanka Ringwald for (i=0; i<caps.multiplexing_mode.transport_identifiers_num; i++){ 156*8ef7100fSMilanka Ringwald buffer[pos++] = caps.multiplexing_mode.transport_session_identifiers[i] << 7; 157*8ef7100fSMilanka Ringwald buffer[pos++] = caps.multiplexing_mode.tcid[i] << 7; 158*8ef7100fSMilanka Ringwald // media, reporting. recovery 159*8ef7100fSMilanka Ringwald } 160*8ef7100fSMilanka Ringwald break; 161*8ef7100fSMilanka Ringwald case AVDTP_MEDIA_CODEC: 162*8ef7100fSMilanka Ringwald buffer[pos++] = ((uint8_t)caps.media_codec.media_type) << 4; 163*8ef7100fSMilanka Ringwald buffer[pos++] = (uint8_t)caps.media_codec.media_codec_type; 164*8ef7100fSMilanka Ringwald for (i = 0; i<caps.media_codec.media_codec_information_len; i++){ 165*8ef7100fSMilanka Ringwald buffer[pos++] = caps.media_codec.media_codec_information[i]; 166*8ef7100fSMilanka Ringwald } 167*8ef7100fSMilanka Ringwald break; 168*8ef7100fSMilanka Ringwald default: 169*8ef7100fSMilanka Ringwald break; 170*8ef7100fSMilanka Ringwald } 171*8ef7100fSMilanka Ringwald buffer[0] = pos - 1; // length 172*8ef7100fSMilanka Ringwald return pos; 173*8ef7100fSMilanka Ringwald } 174*8ef7100fSMilanka Ringwald 175*8ef7100fSMilanka Ringwald static int avdtp_unpack_service_capabilities_has_errors(avdtp_connection_t * connection, avdtp_service_category_t category, uint8_t cap_len){ 176*8ef7100fSMilanka Ringwald connection->error_code = 0; 177*8ef7100fSMilanka Ringwald 178*8ef7100fSMilanka Ringwald if (category == AVDTP_SERVICE_CATEGORY_INVALID_0 || 179*8ef7100fSMilanka Ringwald (category == AVDTP_SERVICE_CATEGORY_INVALID_FF && connection->signaling_packet.signal_identifier == AVDTP_SI_RECONFIGURE)){ 180*8ef7100fSMilanka Ringwald printf(" ERROR: BAD SERVICE CATEGORY %d\n", category); 181*8ef7100fSMilanka Ringwald connection->reject_service_category = category; 182*8ef7100fSMilanka Ringwald connection->error_code = BAD_SERV_CATEGORY; 183*8ef7100fSMilanka Ringwald return 1; 184*8ef7100fSMilanka Ringwald } 185*8ef7100fSMilanka Ringwald 186*8ef7100fSMilanka Ringwald if (connection->signaling_packet.signal_identifier == AVDTP_SI_RECONFIGURE){ 187*8ef7100fSMilanka Ringwald if (category != AVDTP_CONTENT_PROTECTION && category != AVDTP_MEDIA_CODEC){ 188*8ef7100fSMilanka Ringwald printf(" ERROR: REJECT CATEGORY, INVALID_CAPABILITIES\n"); 189*8ef7100fSMilanka Ringwald connection->reject_service_category = category; 190*8ef7100fSMilanka Ringwald connection->error_code = INVALID_CAPABILITIES; 191*8ef7100fSMilanka Ringwald return 1; 192*8ef7100fSMilanka Ringwald } 193*8ef7100fSMilanka Ringwald } 194*8ef7100fSMilanka Ringwald 195*8ef7100fSMilanka Ringwald switch(category){ 196*8ef7100fSMilanka Ringwald case AVDTP_MEDIA_TRANSPORT: 197*8ef7100fSMilanka Ringwald if (cap_len != 0){ 198*8ef7100fSMilanka Ringwald printf(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n"); 199*8ef7100fSMilanka Ringwald connection->reject_service_category = category; 200*8ef7100fSMilanka Ringwald connection->error_code = BAD_MEDIA_TRANSPORT_FORMAT; 201*8ef7100fSMilanka Ringwald return 1; 202*8ef7100fSMilanka Ringwald } 203*8ef7100fSMilanka Ringwald break; 204*8ef7100fSMilanka Ringwald case AVDTP_REPORTING: 205*8ef7100fSMilanka Ringwald case AVDTP_DELAY_REPORTING: 206*8ef7100fSMilanka Ringwald if (cap_len != 0){ 207*8ef7100fSMilanka Ringwald printf(" ERROR: REJECT CATEGORY, BAD_LENGTH\n"); 208*8ef7100fSMilanka Ringwald connection->reject_service_category = category; 209*8ef7100fSMilanka Ringwald connection->error_code = BAD_LENGTH; 210*8ef7100fSMilanka Ringwald return 1; 211*8ef7100fSMilanka Ringwald } 212*8ef7100fSMilanka Ringwald break; 213*8ef7100fSMilanka Ringwald case AVDTP_RECOVERY: 214*8ef7100fSMilanka Ringwald if (cap_len < 3){ 215*8ef7100fSMilanka Ringwald printf(" ERROR: REJECT CATEGORY, BAD_MEDIA_TRANSPORT\n"); 216*8ef7100fSMilanka Ringwald connection->reject_service_category = category; 217*8ef7100fSMilanka Ringwald connection->error_code = BAD_RECOVERY_FORMAT; 218*8ef7100fSMilanka Ringwald return 1; 219*8ef7100fSMilanka Ringwald } 220*8ef7100fSMilanka Ringwald break; 221*8ef7100fSMilanka Ringwald case AVDTP_CONTENT_PROTECTION: 222*8ef7100fSMilanka Ringwald if (cap_len < 2){ 223*8ef7100fSMilanka Ringwald printf(" ERROR: REJECT CATEGORY, BAD_CP_FORMAT\n"); 224*8ef7100fSMilanka Ringwald connection->reject_service_category = category; 225*8ef7100fSMilanka Ringwald connection->error_code = BAD_CP_FORMAT; 226*8ef7100fSMilanka Ringwald return 1; 227*8ef7100fSMilanka Ringwald } 228*8ef7100fSMilanka Ringwald break; 229*8ef7100fSMilanka Ringwald case AVDTP_HEADER_COMPRESSION: 230*8ef7100fSMilanka Ringwald break; 231*8ef7100fSMilanka Ringwald case AVDTP_MULTIPLEXING: 232*8ef7100fSMilanka Ringwald break; 233*8ef7100fSMilanka Ringwald case AVDTP_MEDIA_CODEC: 234*8ef7100fSMilanka Ringwald break; 235*8ef7100fSMilanka Ringwald default: 236*8ef7100fSMilanka Ringwald break; 237*8ef7100fSMilanka Ringwald } 238*8ef7100fSMilanka Ringwald return 0; 239*8ef7100fSMilanka Ringwald } 240*8ef7100fSMilanka Ringwald 241*8ef7100fSMilanka Ringwald uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connection, avdtp_capabilities_t * caps, uint8_t * packet, uint16_t size){ 242*8ef7100fSMilanka Ringwald if (size == 0) return 0; 243*8ef7100fSMilanka Ringwald 244*8ef7100fSMilanka Ringwald uint16_t registered_service_categories = 0; 245*8ef7100fSMilanka Ringwald int pos = 0; 246*8ef7100fSMilanka Ringwald int i; 247*8ef7100fSMilanka Ringwald avdtp_service_category_t category = (avdtp_service_category_t)packet[pos++]; 248*8ef7100fSMilanka Ringwald uint8_t cap_len = packet[pos++]; 249*8ef7100fSMilanka Ringwald 250*8ef7100fSMilanka Ringwald if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0; 251*8ef7100fSMilanka Ringwald int processed_cap_len = 0; 252*8ef7100fSMilanka Ringwald int rfa = 0; 253*8ef7100fSMilanka Ringwald //printf(" size %d, cat size %d\n", size, cap_len); 254*8ef7100fSMilanka Ringwald 255*8ef7100fSMilanka Ringwald while (pos < size){ 256*8ef7100fSMilanka Ringwald if (cap_len > size - pos){ 257*8ef7100fSMilanka Ringwald connection->reject_service_category = category; 258*8ef7100fSMilanka Ringwald connection->error_code = BAD_LENGTH; 259*8ef7100fSMilanka Ringwald return 0; 260*8ef7100fSMilanka Ringwald } 261*8ef7100fSMilanka Ringwald rfa = 0; 262*8ef7100fSMilanka Ringwald processed_cap_len = pos; 263*8ef7100fSMilanka Ringwald switch(category){ 264*8ef7100fSMilanka Ringwald case AVDTP_RECOVERY: 265*8ef7100fSMilanka Ringwald caps->recovery.recovery_type = packet[pos++]; 266*8ef7100fSMilanka Ringwald caps->recovery.maximum_recovery_window_size = packet[pos++]; 267*8ef7100fSMilanka Ringwald caps->recovery.maximum_number_media_packets = packet[pos++]; 268*8ef7100fSMilanka Ringwald break; 269*8ef7100fSMilanka Ringwald case AVDTP_CONTENT_PROTECTION: 270*8ef7100fSMilanka Ringwald caps->content_protection.cp_type = big_endian_read_16(packet, pos); 271*8ef7100fSMilanka Ringwald pos+=2; 272*8ef7100fSMilanka Ringwald 273*8ef7100fSMilanka Ringwald caps->content_protection.cp_type_value_len = cap_len - 2; 274*8ef7100fSMilanka Ringwald pos += caps->content_protection.cp_type_value_len; 275*8ef7100fSMilanka Ringwald 276*8ef7100fSMilanka Ringwald // connection->reject_service_category = category; 277*8ef7100fSMilanka Ringwald // connection->error_code = UNSUPPORTED_CONFIGURATION; 278*8ef7100fSMilanka Ringwald // support for content protection goes here 279*8ef7100fSMilanka Ringwald break; 280*8ef7100fSMilanka Ringwald 281*8ef7100fSMilanka Ringwald case AVDTP_HEADER_COMPRESSION: 282*8ef7100fSMilanka Ringwald caps->header_compression.back_ch = packet[pos] >> 7; 283*8ef7100fSMilanka Ringwald caps->header_compression.media = packet[pos] >> 6; 284*8ef7100fSMilanka Ringwald caps->header_compression.recovery = packet[pos] >> 5; 285*8ef7100fSMilanka Ringwald pos++; 286*8ef7100fSMilanka Ringwald break; 287*8ef7100fSMilanka Ringwald case AVDTP_MULTIPLEXING: 288*8ef7100fSMilanka Ringwald caps->multiplexing_mode.fragmentation = packet[pos++] >> 7; 289*8ef7100fSMilanka Ringwald // read [tsid, tcid] for media, reporting. recovery respectively 290*8ef7100fSMilanka Ringwald caps->multiplexing_mode.transport_identifiers_num = 3; 291*8ef7100fSMilanka Ringwald for (i=0; i<caps->multiplexing_mode.transport_identifiers_num; i++){ 292*8ef7100fSMilanka Ringwald caps->multiplexing_mode.transport_session_identifiers[i] = packet[pos++] >> 7; 293*8ef7100fSMilanka Ringwald caps->multiplexing_mode.tcid[i] = packet[pos++] >> 7; 294*8ef7100fSMilanka Ringwald } 295*8ef7100fSMilanka Ringwald break; 296*8ef7100fSMilanka Ringwald case AVDTP_MEDIA_CODEC: 297*8ef7100fSMilanka Ringwald caps->media_codec.media_type = packet[pos++] >> 4; 298*8ef7100fSMilanka Ringwald caps->media_codec.media_codec_type = packet[pos++]; 299*8ef7100fSMilanka Ringwald caps->media_codec.media_codec_information_len = cap_len - 2; 300*8ef7100fSMilanka Ringwald caps->media_codec.media_codec_information = &packet[pos]; 301*8ef7100fSMilanka Ringwald pos += caps->media_codec.media_codec_information_len; 302*8ef7100fSMilanka Ringwald break; 303*8ef7100fSMilanka Ringwald case AVDTP_MEDIA_TRANSPORT: 304*8ef7100fSMilanka Ringwald case AVDTP_REPORTING: 305*8ef7100fSMilanka Ringwald case AVDTP_DELAY_REPORTING: 306*8ef7100fSMilanka Ringwald pos += cap_len; 307*8ef7100fSMilanka Ringwald break; 308*8ef7100fSMilanka Ringwald default: 309*8ef7100fSMilanka Ringwald pos += cap_len; 310*8ef7100fSMilanka Ringwald rfa = 1; 311*8ef7100fSMilanka Ringwald break; 312*8ef7100fSMilanka Ringwald } 313*8ef7100fSMilanka Ringwald processed_cap_len = pos - processed_cap_len; 314*8ef7100fSMilanka Ringwald 315*8ef7100fSMilanka Ringwald if (cap_len == processed_cap_len){ 316*8ef7100fSMilanka Ringwald if (!rfa) { 317*8ef7100fSMilanka Ringwald registered_service_categories = store_bit16(registered_service_categories, category, 1); 318*8ef7100fSMilanka Ringwald } 319*8ef7100fSMilanka Ringwald if (pos < size-2){ 320*8ef7100fSMilanka Ringwald //int old_pos = pos; 321*8ef7100fSMilanka Ringwald category = (avdtp_service_category_t)packet[pos++]; 322*8ef7100fSMilanka Ringwald cap_len = packet[pos++]; 323*8ef7100fSMilanka Ringwald if (avdtp_unpack_service_capabilities_has_errors(connection, category, cap_len)) return 0; 324*8ef7100fSMilanka Ringwald //printf("category %d, pos %d + 2 + %d -> %d\n", category, old_pos, cap_len, pos + cap_len); 325*8ef7100fSMilanka Ringwald //printf_hexdump(packet+old_pos, size-old_pos); 326*8ef7100fSMilanka Ringwald } 327*8ef7100fSMilanka Ringwald } 328*8ef7100fSMilanka Ringwald } 329*8ef7100fSMilanka Ringwald return registered_service_categories; 330*8ef7100fSMilanka Ringwald } 331*8ef7100fSMilanka Ringwald 332*8ef7100fSMilanka Ringwald void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uint8_t transaction_label, uint16_t registered_service_categories, avdtp_capabilities_t capabilities, uint8_t identifier){ 333*8ef7100fSMilanka Ringwald if (signaling_packet->offset) return; 334*8ef7100fSMilanka Ringwald uint8_t pack_all_capabilities = 1; 335*8ef7100fSMilanka Ringwald signaling_packet->message_type = AVDTP_RESPONSE_ACCEPT_MSG; 336*8ef7100fSMilanka Ringwald signaling_packet->size = 0; 337*8ef7100fSMilanka Ringwald int i; 338*8ef7100fSMilanka Ringwald signaling_packet->command[signaling_packet->size++] = signaling_packet->acp_seid << 2; 339*8ef7100fSMilanka Ringwald 340*8ef7100fSMilanka Ringwald switch (identifier) { 341*8ef7100fSMilanka Ringwald case AVDTP_SI_GET_CAPABILITIES: 342*8ef7100fSMilanka Ringwald pack_all_capabilities = 0; 343*8ef7100fSMilanka Ringwald break; 344*8ef7100fSMilanka Ringwald case AVDTP_SI_GET_ALL_CAPABILITIES: 345*8ef7100fSMilanka Ringwald pack_all_capabilities = 1; 346*8ef7100fSMilanka Ringwald break; 347*8ef7100fSMilanka Ringwald case AVDTP_SI_SET_CONFIGURATION: 348*8ef7100fSMilanka Ringwald signaling_packet->command[signaling_packet->size++] = signaling_packet->int_seid << 2; 349*8ef7100fSMilanka Ringwald signaling_packet->message_type = AVDTP_CMD_MSG; 350*8ef7100fSMilanka Ringwald break; 351*8ef7100fSMilanka Ringwald case AVDTP_SI_RECONFIGURE: 352*8ef7100fSMilanka Ringwald signaling_packet->message_type = AVDTP_CMD_MSG; 353*8ef7100fSMilanka Ringwald break; 354*8ef7100fSMilanka Ringwald default: 355*8ef7100fSMilanka Ringwald log_error("avdtp_prepare_capabilities wrong identifier %d", identifier); 356*8ef7100fSMilanka Ringwald break; 357*8ef7100fSMilanka Ringwald } 358*8ef7100fSMilanka Ringwald 359*8ef7100fSMilanka Ringwald for (i = 1; i < 9; i++){ 360*8ef7100fSMilanka Ringwald if (get_bit16(registered_service_categories, i)){ 361*8ef7100fSMilanka Ringwald // service category 362*8ef7100fSMilanka Ringwald signaling_packet->command[signaling_packet->size++] = i; 363*8ef7100fSMilanka Ringwald signaling_packet->size += avdtp_pack_service_capabilities(signaling_packet->command+signaling_packet->size, sizeof(signaling_packet->command)-signaling_packet->size, capabilities, (avdtp_service_category_t)i, pack_all_capabilities); 364*8ef7100fSMilanka Ringwald } 365*8ef7100fSMilanka Ringwald } 366*8ef7100fSMilanka Ringwald // signaling_packet->command[signaling_packet->size++] = 0x04; 367*8ef7100fSMilanka Ringwald // signaling_packet->command[signaling_packet->size++] = 0x02; 368*8ef7100fSMilanka Ringwald // signaling_packet->command[signaling_packet->size++] = 0x02; 369*8ef7100fSMilanka Ringwald // signaling_packet->command[signaling_packet->size++] = 0x00; 370*8ef7100fSMilanka Ringwald 371*8ef7100fSMilanka Ringwald signaling_packet->signal_identifier = identifier; 372*8ef7100fSMilanka Ringwald signaling_packet->transaction_label = transaction_label; 373*8ef7100fSMilanka Ringwald } 374*8ef7100fSMilanka Ringwald 375*8ef7100fSMilanka Ringwald int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * signaling_packet, uint8_t * out_buffer) { 376*8ef7100fSMilanka Ringwald int mtu = l2cap_get_remote_mtu_for_local_cid(cid); 377*8ef7100fSMilanka Ringwald // hack for test 378*8ef7100fSMilanka Ringwald // int mtu = 6; 379*8ef7100fSMilanka Ringwald int data_len = 0; 380*8ef7100fSMilanka Ringwald 381*8ef7100fSMilanka Ringwald uint16_t offset = signaling_packet->offset; 382*8ef7100fSMilanka Ringwald uint16_t pos = 1; 383*8ef7100fSMilanka Ringwald // printf(" avdtp_signaling_create_fragment offset %d, packet type %d\n", signaling_packet->offset, signaling_packet->packet_type); 384*8ef7100fSMilanka Ringwald 385*8ef7100fSMilanka Ringwald if (offset == 0){ 386*8ef7100fSMilanka Ringwald if (signaling_packet->size <= mtu - 2){ 387*8ef7100fSMilanka Ringwald // printf(" AVDTP_SINGLE_PACKET\n"); 388*8ef7100fSMilanka Ringwald signaling_packet->packet_type = AVDTP_SINGLE_PACKET; 389*8ef7100fSMilanka Ringwald out_buffer[pos++] = signaling_packet->signal_identifier; 390*8ef7100fSMilanka Ringwald data_len = signaling_packet->size; 391*8ef7100fSMilanka Ringwald } else { 392*8ef7100fSMilanka Ringwald signaling_packet->packet_type = AVDTP_START_PACKET; 393*8ef7100fSMilanka Ringwald out_buffer[pos++] = (mtu + signaling_packet->size)/ (mtu-1); 394*8ef7100fSMilanka Ringwald out_buffer[pos++] = signaling_packet->signal_identifier; 395*8ef7100fSMilanka Ringwald data_len = mtu - 3; 396*8ef7100fSMilanka Ringwald signaling_packet->offset = data_len; 397*8ef7100fSMilanka Ringwald // printf(" AVDTP_START_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset); 398*8ef7100fSMilanka Ringwald } 399*8ef7100fSMilanka Ringwald } else { 400*8ef7100fSMilanka Ringwald int remaining_bytes = signaling_packet->size - offset; 401*8ef7100fSMilanka Ringwald if (remaining_bytes <= mtu - 1){ 402*8ef7100fSMilanka Ringwald //signaling_packet->fragmentation = 1; 403*8ef7100fSMilanka Ringwald signaling_packet->packet_type = AVDTP_END_PACKET; 404*8ef7100fSMilanka Ringwald data_len = remaining_bytes; 405*8ef7100fSMilanka Ringwald signaling_packet->offset = 0; 406*8ef7100fSMilanka Ringwald // printf(" AVDTP_END_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset); 407*8ef7100fSMilanka Ringwald } else{ 408*8ef7100fSMilanka Ringwald signaling_packet->packet_type = AVDTP_CONTINUE_PACKET; 409*8ef7100fSMilanka Ringwald data_len = mtu - 1; 410*8ef7100fSMilanka Ringwald signaling_packet->offset += data_len; 411*8ef7100fSMilanka Ringwald // printf(" AVDTP_CONTINUE_PACKET len %d, offset %d\n", signaling_packet->size, signaling_packet->offset); 412*8ef7100fSMilanka Ringwald } 413*8ef7100fSMilanka Ringwald } 414*8ef7100fSMilanka Ringwald out_buffer[0] = avdtp_header(signaling_packet->transaction_label, signaling_packet->packet_type, signaling_packet->message_type); 415*8ef7100fSMilanka Ringwald memcpy(out_buffer+pos, signaling_packet->command + offset, data_len); 416*8ef7100fSMilanka Ringwald pos += data_len; 417*8ef7100fSMilanka Ringwald return pos; 418*8ef7100fSMilanka Ringwald } 419*8ef7100fSMilanka Ringwald 420*8ef7100fSMilanka Ringwald 421*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t con_handle, bd_addr_t addr, uint8_t status){ 422*8ef7100fSMilanka Ringwald if (!callback) return; 423*8ef7100fSMilanka Ringwald uint8_t event[12]; 424*8ef7100fSMilanka Ringwald int pos = 0; 425*8ef7100fSMilanka Ringwald event[pos++] = HCI_EVENT_AVDTP_META; 426*8ef7100fSMilanka Ringwald event[pos++] = sizeof(event) - 2; 427*8ef7100fSMilanka Ringwald event[pos++] = AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED; 428*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, con_handle); 429*8ef7100fSMilanka Ringwald pos += 2; 430*8ef7100fSMilanka Ringwald reverse_bd_addr(addr,&event[pos]); 431*8ef7100fSMilanka Ringwald pos += 6; 432*8ef7100fSMilanka Ringwald event[pos++] = status; 433*8ef7100fSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 434*8ef7100fSMilanka Ringwald } 435*8ef7100fSMilanka Ringwald 436*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_sep_t sep){ 437*8ef7100fSMilanka Ringwald if (!callback) return; 438*8ef7100fSMilanka Ringwald uint8_t event[9]; 439*8ef7100fSMilanka Ringwald int pos = 0; 440*8ef7100fSMilanka Ringwald event[pos++] = HCI_EVENT_AVDTP_META; 441*8ef7100fSMilanka Ringwald event[pos++] = sizeof(event) - 2; 442*8ef7100fSMilanka Ringwald event[pos++] = AVDTP_SUBEVENT_SIGNALING_SEP_FOUND; 443*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, con_handle); 444*8ef7100fSMilanka Ringwald pos += 2; 445*8ef7100fSMilanka Ringwald event[pos++] = sep.seid; 446*8ef7100fSMilanka Ringwald event[pos++] = sep.in_use; 447*8ef7100fSMilanka Ringwald event[pos++] = sep.media_type; 448*8ef7100fSMilanka Ringwald event[pos++] = sep.type; 449*8ef7100fSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 450*8ef7100fSMilanka Ringwald } 451*8ef7100fSMilanka Ringwald 452*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier, uint8_t status){ 453*8ef7100fSMilanka Ringwald if (!callback) return; 454*8ef7100fSMilanka Ringwald uint8_t event[7]; 455*8ef7100fSMilanka Ringwald int pos = 0; 456*8ef7100fSMilanka Ringwald event[pos++] = HCI_EVENT_AVDTP_META; 457*8ef7100fSMilanka Ringwald event[pos++] = sizeof(event) - 2; 458*8ef7100fSMilanka Ringwald event[pos++] = AVDTP_SUBEVENT_SIGNALING_ACCEPT; 459*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, con_handle); 460*8ef7100fSMilanka Ringwald pos += 2; 461*8ef7100fSMilanka Ringwald event[pos++] = identifier; 462*8ef7100fSMilanka Ringwald event[pos++] = status; 463*8ef7100fSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 464*8ef7100fSMilanka Ringwald } 465*8ef7100fSMilanka Ringwald 466*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier){ 467*8ef7100fSMilanka Ringwald if (!callback) return; 468*8ef7100fSMilanka Ringwald uint8_t event[6]; 469*8ef7100fSMilanka Ringwald int pos = 0; 470*8ef7100fSMilanka Ringwald event[pos++] = HCI_EVENT_AVDTP_META; 471*8ef7100fSMilanka Ringwald event[pos++] = sizeof(event) - 2; 472*8ef7100fSMilanka Ringwald event[pos++] = AVDTP_SUBEVENT_SIGNALING_REJECT; 473*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, con_handle); 474*8ef7100fSMilanka Ringwald pos += 2; 475*8ef7100fSMilanka Ringwald event[pos++] = identifier; 476*8ef7100fSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 477*8ef7100fSMilanka Ringwald } 478*8ef7100fSMilanka Ringwald 479*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t con_handle, avdtp_signal_identifier_t identifier){ 480*8ef7100fSMilanka Ringwald if (!callback) return; 481*8ef7100fSMilanka Ringwald uint8_t event[6]; 482*8ef7100fSMilanka Ringwald int pos = 0; 483*8ef7100fSMilanka Ringwald event[pos++] = HCI_EVENT_AVDTP_META; 484*8ef7100fSMilanka Ringwald event[pos++] = sizeof(event) - 2; 485*8ef7100fSMilanka Ringwald event[pos++] = AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT; 486*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, con_handle); 487*8ef7100fSMilanka Ringwald pos += 2; 488*8ef7100fSMilanka Ringwald event[pos++] = identifier; 489*8ef7100fSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 490*8ef7100fSMilanka Ringwald } 491*8ef7100fSMilanka Ringwald 492*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_media_codec_sbc_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ 493*8ef7100fSMilanka Ringwald if (!callback) return; 494*8ef7100fSMilanka Ringwald uint8_t event[13]; 495*8ef7100fSMilanka Ringwald int pos = 0; 496*8ef7100fSMilanka Ringwald event[pos++] = HCI_EVENT_AVDTP_META; 497*8ef7100fSMilanka Ringwald event[pos++] = sizeof(event) - 2; 498*8ef7100fSMilanka Ringwald event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY; 499*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, con_handle); 500*8ef7100fSMilanka Ringwald pos += 2; 501*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_type; 502*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_codec_information[0] >> 4; 503*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_codec_information[0] & 0x0F; 504*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_codec_information[1] >> 4; 505*8ef7100fSMilanka Ringwald event[pos++] = (media_codec.media_codec_information[1] & 0x0F) >> 2; 506*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_codec_information[1] & 0x03; 507*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_codec_information[2]; 508*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_codec_information[3]; 509*8ef7100fSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 510*8ef7100fSMilanka Ringwald } 511*8ef7100fSMilanka Ringwald 512*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_media_codec_other_capability(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ 513*8ef7100fSMilanka Ringwald if (!callback) return; 514*8ef7100fSMilanka Ringwald uint8_t event[109]; 515*8ef7100fSMilanka Ringwald int pos = 0; 516*8ef7100fSMilanka Ringwald event[pos++] = HCI_EVENT_AVDTP_META; 517*8ef7100fSMilanka Ringwald event[pos++] = sizeof(event) - 2; 518*8ef7100fSMilanka Ringwald event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY; 519*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, con_handle); 520*8ef7100fSMilanka Ringwald pos += 2; 521*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_type; 522*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, media_codec.media_codec_type); 523*8ef7100fSMilanka Ringwald pos += 2; 524*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, media_codec.media_codec_information_len); 525*8ef7100fSMilanka Ringwald pos += 2; 526*8ef7100fSMilanka Ringwald if (media_codec.media_codec_information_len < 100){ 527*8ef7100fSMilanka Ringwald memcpy(event+pos, media_codec.media_codec_information, media_codec.media_codec_information_len); 528*8ef7100fSMilanka Ringwald } else { 529*8ef7100fSMilanka Ringwald memcpy(event+pos, media_codec.media_codec_information, 100); 530*8ef7100fSMilanka Ringwald } 531*8ef7100fSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 532*8ef7100fSMilanka Ringwald } 533*8ef7100fSMilanka Ringwald 534*8ef7100fSMilanka Ringwald static inline void avdtp_signaling_emit_media_codec_sbc(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){ 535*8ef7100fSMilanka Ringwald if (!callback) return; 536*8ef7100fSMilanka Ringwald uint8_t event[14+2]; 537*8ef7100fSMilanka Ringwald int pos = 0; 538*8ef7100fSMilanka Ringwald event[pos++] = HCI_EVENT_AVDTP_META; 539*8ef7100fSMilanka Ringwald event[pos++] = sizeof(event) - 2; 540*8ef7100fSMilanka Ringwald 541*8ef7100fSMilanka Ringwald event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION; 542*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, con_handle); 543*8ef7100fSMilanka Ringwald pos += 2; 544*8ef7100fSMilanka Ringwald event[pos++] = reconfigure; 545*8ef7100fSMilanka Ringwald 546*8ef7100fSMilanka Ringwald uint8_t num_channels = 0; 547*8ef7100fSMilanka Ringwald uint16_t sampling_frequency = 0; 548*8ef7100fSMilanka Ringwald uint8_t subbands = 0; 549*8ef7100fSMilanka Ringwald uint8_t block_length = 0; 550*8ef7100fSMilanka Ringwald 551*8ef7100fSMilanka Ringwald uint8_t sampling_frequency_bitmap = media_codec.media_codec_information[0] >> 4; 552*8ef7100fSMilanka Ringwald uint8_t channel_mode_bitmap = media_codec.media_codec_information[0] & 0x0F; 553*8ef7100fSMilanka Ringwald uint8_t block_length_bitmap = media_codec.media_codec_information[1] >> 4; 554*8ef7100fSMilanka Ringwald uint8_t subbands_bitmap = (media_codec.media_codec_information[1] & 0x0F) >> 2; 555*8ef7100fSMilanka Ringwald 556*8ef7100fSMilanka Ringwald if (channel_mode_bitmap & AVDTP_SBC_MONO){ 557*8ef7100fSMilanka Ringwald num_channels = 1; 558*8ef7100fSMilanka Ringwald } 559*8ef7100fSMilanka Ringwald if ( (channel_mode_bitmap & AVDTP_SBC_JOINT_STEREO) || 560*8ef7100fSMilanka Ringwald (channel_mode_bitmap & AVDTP_SBC_STEREO) || 561*8ef7100fSMilanka Ringwald (channel_mode_bitmap & AVDTP_SBC_DUAL_CHANNEL) ){ 562*8ef7100fSMilanka Ringwald num_channels = 2; 563*8ef7100fSMilanka Ringwald } 564*8ef7100fSMilanka Ringwald 565*8ef7100fSMilanka Ringwald if (sampling_frequency_bitmap & AVDTP_SBC_16000){ 566*8ef7100fSMilanka Ringwald sampling_frequency = 16000; 567*8ef7100fSMilanka Ringwald } 568*8ef7100fSMilanka Ringwald if (sampling_frequency_bitmap & AVDTP_SBC_32000){ 569*8ef7100fSMilanka Ringwald sampling_frequency = 32000; 570*8ef7100fSMilanka Ringwald } 571*8ef7100fSMilanka Ringwald if (sampling_frequency_bitmap & AVDTP_SBC_44100){ 572*8ef7100fSMilanka Ringwald sampling_frequency = 44100; 573*8ef7100fSMilanka Ringwald } 574*8ef7100fSMilanka Ringwald if (sampling_frequency_bitmap & AVDTP_SBC_48000){ 575*8ef7100fSMilanka Ringwald sampling_frequency = 48000; 576*8ef7100fSMilanka Ringwald } 577*8ef7100fSMilanka Ringwald 578*8ef7100fSMilanka Ringwald if (subbands_bitmap & AVDTP_SBC_SUBBANDS_4){ 579*8ef7100fSMilanka Ringwald subbands = 4; 580*8ef7100fSMilanka Ringwald } 581*8ef7100fSMilanka Ringwald if (subbands_bitmap & AVDTP_SBC_SUBBANDS_8){ 582*8ef7100fSMilanka Ringwald subbands = 8; 583*8ef7100fSMilanka Ringwald } 584*8ef7100fSMilanka Ringwald 585*8ef7100fSMilanka Ringwald if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_4){ 586*8ef7100fSMilanka Ringwald block_length = 4; 587*8ef7100fSMilanka Ringwald } 588*8ef7100fSMilanka Ringwald if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_8){ 589*8ef7100fSMilanka Ringwald block_length = 8; 590*8ef7100fSMilanka Ringwald } 591*8ef7100fSMilanka Ringwald if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_12){ 592*8ef7100fSMilanka Ringwald block_length = 12; 593*8ef7100fSMilanka Ringwald } 594*8ef7100fSMilanka Ringwald if (block_length_bitmap & AVDTP_SBC_BLOCK_LENGTH_16){ 595*8ef7100fSMilanka Ringwald block_length = 16; 596*8ef7100fSMilanka Ringwald } 597*8ef7100fSMilanka Ringwald 598*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_type; 599*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, sampling_frequency); 600*8ef7100fSMilanka Ringwald pos += 2; 601*8ef7100fSMilanka Ringwald 602*8ef7100fSMilanka Ringwald event[pos++] = channel_mode_bitmap; 603*8ef7100fSMilanka Ringwald event[pos++] = num_channels; 604*8ef7100fSMilanka Ringwald event[pos++] = block_length; 605*8ef7100fSMilanka Ringwald event[pos++] = subbands; 606*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_codec_information[1] & 0x03; 607*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_codec_information[2]; 608*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_codec_information[3]; 609*8ef7100fSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 610*8ef7100fSMilanka Ringwald } 611*8ef7100fSMilanka Ringwald 612*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_media_codec_sbc_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ 613*8ef7100fSMilanka Ringwald if (!callback) return; 614*8ef7100fSMilanka Ringwald avdtp_signaling_emit_media_codec_sbc(callback, con_handle, media_codec, 0); 615*8ef7100fSMilanka Ringwald } 616*8ef7100fSMilanka Ringwald 617*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_media_codec_sbc_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ 618*8ef7100fSMilanka Ringwald if (!callback) return; 619*8ef7100fSMilanka Ringwald avdtp_signaling_emit_media_codec_sbc(callback, con_handle, media_codec, 1); 620*8ef7100fSMilanka Ringwald } 621*8ef7100fSMilanka Ringwald 622*8ef7100fSMilanka Ringwald static inline void avdtp_signaling_emit_media_codec_other(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec, uint8_t reconfigure){ 623*8ef7100fSMilanka Ringwald uint8_t event[110]; 624*8ef7100fSMilanka Ringwald int pos = 0; 625*8ef7100fSMilanka Ringwald event[pos++] = HCI_EVENT_AVDTP_META; 626*8ef7100fSMilanka Ringwald event[pos++] = sizeof(event) - 2; 627*8ef7100fSMilanka Ringwald event[pos++] = AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION; 628*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, con_handle); 629*8ef7100fSMilanka Ringwald pos += 2; 630*8ef7100fSMilanka Ringwald 631*8ef7100fSMilanka Ringwald event[pos++] = reconfigure; 632*8ef7100fSMilanka Ringwald 633*8ef7100fSMilanka Ringwald event[pos++] = media_codec.media_type; 634*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, media_codec.media_codec_type); 635*8ef7100fSMilanka Ringwald pos += 2; 636*8ef7100fSMilanka Ringwald little_endian_store_16(event, pos, media_codec.media_codec_information_len); 637*8ef7100fSMilanka Ringwald pos += 2; 638*8ef7100fSMilanka Ringwald 639*8ef7100fSMilanka Ringwald if (media_codec.media_codec_information_len < 100){ 640*8ef7100fSMilanka Ringwald memcpy(event+pos, media_codec.media_codec_information, media_codec.media_codec_information_len); 641*8ef7100fSMilanka Ringwald } else { 642*8ef7100fSMilanka Ringwald memcpy(event+pos, media_codec.media_codec_information, 100); 643*8ef7100fSMilanka Ringwald } 644*8ef7100fSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 645*8ef7100fSMilanka Ringwald } 646*8ef7100fSMilanka Ringwald 647*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_media_codec_other_configuration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ 648*8ef7100fSMilanka Ringwald if (!callback) return; 649*8ef7100fSMilanka Ringwald avdtp_signaling_emit_media_codec_other(callback, con_handle, media_codec, 0); 650*8ef7100fSMilanka Ringwald } 651*8ef7100fSMilanka Ringwald 652*8ef7100fSMilanka Ringwald void avdtp_signaling_emit_media_codec_other_reconfiguration(btstack_packet_handler_t callback, uint16_t con_handle, adtvp_media_codec_capabilities_t media_codec){ 653*8ef7100fSMilanka Ringwald if (!callback) return; 654*8ef7100fSMilanka Ringwald avdtp_signaling_emit_media_codec_other(callback, con_handle, media_codec, 1); 655*8ef7100fSMilanka Ringwald } 656*8ef7100fSMilanka Ringwald 657*8ef7100fSMilanka Ringwald 658*8ef7100fSMilanka Ringwald void avdtp_sink_request_can_send_now_acceptor(avdtp_connection_t * connection, uint16_t l2cap_cid){ 659*8ef7100fSMilanka Ringwald connection->wait_to_send_acceptor = 1; 660*8ef7100fSMilanka Ringwald l2cap_request_can_send_now_event(l2cap_cid); 661*8ef7100fSMilanka Ringwald } 662*8ef7100fSMilanka Ringwald void avdtp_sink_request_can_send_now_initiator(avdtp_connection_t * connection, uint16_t l2cap_cid){ 663*8ef7100fSMilanka Ringwald connection->wait_to_send_initiator = 1; 664*8ef7100fSMilanka Ringwald l2cap_request_can_send_now_event(l2cap_cid); 665*8ef7100fSMilanka Ringwald } 666*8ef7100fSMilanka Ringwald void avdtp_sink_request_can_send_now_self(avdtp_connection_t * connection, uint16_t l2cap_cid){ 667*8ef7100fSMilanka Ringwald connection->wait_to_send_self = 1; 668*8ef7100fSMilanka Ringwald l2cap_request_can_send_now_event(l2cap_cid); 669*8ef7100fSMilanka Ringwald } 670*8ef7100fSMilanka Ringwald 671*8ef7100fSMilanka Ringwald avdtp_stream_endpoint_t * get_avdtp_stream_endpoint_for_seid(uint16_t seid){ 672*8ef7100fSMilanka Ringwald btstack_linked_list_iterator_t it; 673*8ef7100fSMilanka Ringwald btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &stream_endpoints); 674*8ef7100fSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 675*8ef7100fSMilanka Ringwald avdtp_stream_endpoint_t * stream_endpoint = (avdtp_stream_endpoint_t *)btstack_linked_list_iterator_next(&it); 676*8ef7100fSMilanka Ringwald if (stream_endpoint->sep.seid == seid){ 677*8ef7100fSMilanka Ringwald return stream_endpoint; 678*8ef7100fSMilanka Ringwald } 679*8ef7100fSMilanka Ringwald } 680*8ef7100fSMilanka Ringwald return NULL; 681*8ef7100fSMilanka Ringwald } 682*8ef7100fSMilanka Ringwald 683*8ef7100fSMilanka Ringwald uint8_t avdtp_get_index_of_remote_stream_endpoint_with_seid(avdtp_stream_endpoint_t * stream_endpoint, uint16_t seid){ 684*8ef7100fSMilanka Ringwald if (stream_endpoint->remote_seps[stream_endpoint->remote_sep_index].seid == seid){ 685*8ef7100fSMilanka Ringwald return stream_endpoint->remote_sep_index; 686*8ef7100fSMilanka Ringwald } 687*8ef7100fSMilanka Ringwald int i; 688*8ef7100fSMilanka Ringwald for (i=0; i < stream_endpoint->remote_seps_num; i++){ 689*8ef7100fSMilanka Ringwald if (stream_endpoint->remote_seps[i].seid == seid){ 690*8ef7100fSMilanka Ringwald return i; 691*8ef7100fSMilanka Ringwald } 692*8ef7100fSMilanka Ringwald } 693*8ef7100fSMilanka Ringwald return 0xFF; 694*8ef7100fSMilanka Ringwald } 695