1be32e7f1SMilanka Ringwald /* 2be32e7f1SMilanka Ringwald * Copyright (C) 2016 BlueKitchen GmbH 3be32e7f1SMilanka Ringwald * 4be32e7f1SMilanka Ringwald * Redistribution and use in source and binary forms, with or without 5be32e7f1SMilanka Ringwald * modification, are permitted provided that the following conditions 6be32e7f1SMilanka Ringwald * are met: 7be32e7f1SMilanka Ringwald * 8be32e7f1SMilanka Ringwald * 1. Redistributions of source code must retain the above copyright 9be32e7f1SMilanka Ringwald * notice, this list of conditions and the following disclaimer. 10be32e7f1SMilanka Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11be32e7f1SMilanka Ringwald * notice, this list of conditions and the following disclaimer in the 12be32e7f1SMilanka Ringwald * documentation and/or other materials provided with the distribution. 13be32e7f1SMilanka Ringwald * 3. Neither the name of the copyright holders nor the names of 14be32e7f1SMilanka Ringwald * contributors may be used to endorse or promote products derived 15be32e7f1SMilanka Ringwald * from this software without specific prior written permission. 16be32e7f1SMilanka Ringwald * 4. Any redistribution, use, or modification is done solely for 17be32e7f1SMilanka Ringwald * personal benefit and not for any commercial purpose or for 18be32e7f1SMilanka Ringwald * monetary gain. 19be32e7f1SMilanka Ringwald * 20be32e7f1SMilanka Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21be32e7f1SMilanka Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22be32e7f1SMilanka Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23be32e7f1SMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24be32e7f1SMilanka Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25be32e7f1SMilanka Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26be32e7f1SMilanka Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27be32e7f1SMilanka Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28be32e7f1SMilanka Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29be32e7f1SMilanka Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30be32e7f1SMilanka Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31be32e7f1SMilanka Ringwald * SUCH DAMAGE. 32be32e7f1SMilanka Ringwald * 33be32e7f1SMilanka Ringwald * Please inquire about commercial licensing options at 34be32e7f1SMilanka Ringwald * [email protected] 35be32e7f1SMilanka Ringwald * 36be32e7f1SMilanka Ringwald */ 37be32e7f1SMilanka Ringwald 38ab2c6ae4SMatthias Ringwald #define __BTSTACK_FILE__ "avrcp.c" 39ab2c6ae4SMatthias Ringwald 40be32e7f1SMilanka Ringwald #include <stdint.h> 41be32e7f1SMilanka Ringwald #include <stdio.h> 42be32e7f1SMilanka Ringwald #include <stdlib.h> 43be32e7f1SMilanka Ringwald #include <string.h> 44be32e7f1SMilanka Ringwald 45be32e7f1SMilanka Ringwald #include "btstack.h" 46be32e7f1SMilanka Ringwald #include "classic/avrcp.h" 476983e65eSMilanka Ringwald #include "classic/avrcp_controller.h" 48be32e7f1SMilanka Ringwald 49235946f1SMatthias Ringwald #define PSM_AVCTP BLUETOOTH_PROTOCOL_AVCTP 50a0f524f0SMatthias Ringwald #define PSM_AVCTP_BROWSING 0x001b 51be32e7f1SMilanka Ringwald 5201dc6e35SMilanka Ringwald /* 5301dc6e35SMilanka Ringwald Category 1: Player/Recorder 5401dc6e35SMilanka Ringwald Category 2: Monitor/Amplifier 5501dc6e35SMilanka Ringwald Category 3: Tuner 5601dc6e35SMilanka Ringwald Category 4: Menu 5701dc6e35SMilanka Ringwald */ 5801dc6e35SMilanka Ringwald 5901dc6e35SMilanka Ringwald /* controller supported features 6001dc6e35SMilanka Ringwald Bit 0 = Category 1 6101dc6e35SMilanka Ringwald Bit 1 = Category 2 6201dc6e35SMilanka Ringwald Bit 2 = Category 3 6301dc6e35SMilanka Ringwald Bit 3 = Category 4 6401dc6e35SMilanka Ringwald Bit 4-5 = RFA 6501dc6e35SMilanka Ringwald Bit 6 = Supports browsing 6601dc6e35SMilanka Ringwald Bit 7-15 = RFA 6701dc6e35SMilanka Ringwald The bits for supported categories are set to 1. Others are set to 0. 6801dc6e35SMilanka Ringwald */ 6901dc6e35SMilanka Ringwald 7001dc6e35SMilanka Ringwald /* target supported features 7101dc6e35SMilanka Ringwald Bit 0 = Category 1 7201dc6e35SMilanka Ringwald Bit 1 = Category 2 7301dc6e35SMilanka Ringwald Bit 2 = Category 3 7401dc6e35SMilanka Ringwald Bit 3 = Category 4 7501dc6e35SMilanka Ringwald Bit 4 = Player Application Settings. Bit 0 should be set for this bit to be set. 7601dc6e35SMilanka Ringwald Bit 5 = Group Navigation. Bit 0 should be set for this bit to be set. 7701dc6e35SMilanka Ringwald Bit 6 = Supports browsing*4 7801dc6e35SMilanka Ringwald Bit 7 = Supports multiple media player applications 7901dc6e35SMilanka Ringwald Bit 8-15 = RFA 8001dc6e35SMilanka Ringwald The bits for supported categories are set to 1. Others are set to 0. 8101dc6e35SMilanka Ringwald */ 8201dc6e35SMilanka Ringwald 83be32e7f1SMilanka Ringwald static const char * default_avrcp_controller_service_name = "BTstack AVRCP Controller Service"; 84be32e7f1SMilanka Ringwald static const char * default_avrcp_controller_service_provider_name = "BTstack AVRCP Controller Service Provider"; 85be32e7f1SMilanka Ringwald static const char * default_avrcp_target_service_name = "BTstack AVRCP Target Service"; 86be32e7f1SMilanka Ringwald static const char * default_avrcp_target_service_provider_name = "BTstack AVRCP Target Service Provider"; 87be32e7f1SMilanka Ringwald 886983e65eSMilanka Ringwald static uint16_t avrcp_cid_counter = 0; 89be32e7f1SMilanka Ringwald 906983e65eSMilanka Ringwald static avrcp_context_t * sdp_query_context; 916983e65eSMilanka Ringwald static int record_id = -1; 926983e65eSMilanka Ringwald static uint8_t attribute_value[1000]; 936983e65eSMilanka Ringwald static const unsigned int attribute_value_buffer_size = sizeof(attribute_value); 946983e65eSMilanka Ringwald 956983e65eSMilanka Ringwald static void avrcp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 966086246cSMilanka Ringwald 97be32e7f1SMilanka Ringwald static const char * avrcp_subunit_type_name[] = { 98be32e7f1SMilanka Ringwald "MONITOR", "AUDIO", "PRINTER", "DISC", "TAPE_RECORDER_PLAYER", "TUNER", 99be32e7f1SMilanka Ringwald "CA", "CAMERA", "RESERVED", "PANEL", "BULLETIN_BOARD", "CAMERA_STORAGE", 100be32e7f1SMilanka Ringwald "VENDOR_UNIQUE", "RESERVED_FOR_ALL_SUBUNIT_TYPES", 101be32e7f1SMilanka Ringwald "EXTENDED_TO_NEXT_BYTE", "UNIT", "ERROR" 102be32e7f1SMilanka Ringwald }; 1036983e65eSMilanka Ringwald 104be32e7f1SMilanka Ringwald const char * avrcp_subunit2str(uint16_t index){ 105be32e7f1SMilanka Ringwald if (index <= 11) return avrcp_subunit_type_name[index]; 106be32e7f1SMilanka Ringwald if (index >= 0x1C && index <= 0x1F) return avrcp_subunit_type_name[index - 0x10]; 107be32e7f1SMilanka Ringwald return avrcp_subunit_type_name[16]; 108be32e7f1SMilanka Ringwald } 109be32e7f1SMilanka Ringwald 110be32e7f1SMilanka Ringwald static const char * avrcp_event_name[] = { 111be32e7f1SMilanka Ringwald "ERROR", "PLAYBACK_STATUS_CHANGED", 112be32e7f1SMilanka Ringwald "TRACK_CHANGED", "TRACK_REACHED_END", "TRACK_REACHED_START", 113be32e7f1SMilanka Ringwald "PLAYBACK_POS_CHANGED", "BATT_STATUS_CHANGED", "SYSTEM_STATUS_CHANGED", 114be32e7f1SMilanka Ringwald "PLAYER_APPLICATION_SETTING_CHANGED", "NOW_PLAYING_CONTENT_CHANGED", 115be32e7f1SMilanka Ringwald "AVAILABLE_PLAYERS_CHANGED", "ADDRESSED_PLAYER_CHANGED", "UIDS_CHANGED", "VOLUME_CHANGED" 116be32e7f1SMilanka Ringwald }; 117be32e7f1SMilanka Ringwald const char * avrcp_event2str(uint16_t index){ 118be32e7f1SMilanka Ringwald if (index <= 0x0d) return avrcp_event_name[index]; 119be32e7f1SMilanka Ringwald return avrcp_event_name[0]; 120be32e7f1SMilanka Ringwald } 121be32e7f1SMilanka Ringwald 122be32e7f1SMilanka Ringwald static const char * avrcp_operation_name[] = { 123be32e7f1SMilanka Ringwald "NOT SUPPORTED", // 0x3B 124be32e7f1SMilanka Ringwald "SKIP", "NOT SUPPORTED", "NOT SUPPORTED", "NOT SUPPORTED", "NOT SUPPORTED", 125be32e7f1SMilanka Ringwald "VOLUME_UP", "VOLUME_DOWN", "MUTE", "PLAY", "STOP", "PAUSE", "NOT SUPPORTED", 126be32e7f1SMilanka Ringwald "REWIND", "FAST_FORWARD", "NOT SUPPORTED", "FORWARD", "BACKWARD" // 0x4C 127be32e7f1SMilanka Ringwald }; 128be32e7f1SMilanka Ringwald const char * avrcp_operation2str(uint8_t index){ 129be32e7f1SMilanka Ringwald if (index >= 0x3B && index <= 0x4C) return avrcp_operation_name[index - 0x3B]; 130be32e7f1SMilanka Ringwald return avrcp_operation_name[0]; 131be32e7f1SMilanka Ringwald } 132be32e7f1SMilanka Ringwald 133be32e7f1SMilanka Ringwald static const char * avrcp_media_attribute_id_name[] = { 134be32e7f1SMilanka Ringwald "NONE", "TITLE", "ARTIST", "ALBUM", "TRACK", "TOTAL TRACKS", "GENRE", "SONG LENGTH" 135be32e7f1SMilanka Ringwald }; 136be32e7f1SMilanka Ringwald const char * avrcp_attribute2str(uint8_t index){ 137be32e7f1SMilanka Ringwald if (index >= 1 && index <= 7) return avrcp_media_attribute_id_name[index]; 138be32e7f1SMilanka Ringwald return avrcp_media_attribute_id_name[0]; 139be32e7f1SMilanka Ringwald } 140be32e7f1SMilanka Ringwald 141be32e7f1SMilanka Ringwald static const char * avrcp_play_status_name[] = { 142be32e7f1SMilanka Ringwald "STOPPED", "PLAYING", "PAUSED", "FORWARD SEEK", "REVERSE SEEK", 143be32e7f1SMilanka Ringwald "ERROR" // 0xFF 144be32e7f1SMilanka Ringwald }; 145be32e7f1SMilanka Ringwald const char * avrcp_play_status2str(uint8_t index){ 146be32e7f1SMilanka Ringwald if (index >= 1 && index <= 4) return avrcp_play_status_name[index]; 147be32e7f1SMilanka Ringwald return avrcp_play_status_name[5]; 148be32e7f1SMilanka Ringwald } 149be32e7f1SMilanka Ringwald 150be32e7f1SMilanka Ringwald static const char * avrcp_ctype_name[] = { 151be32e7f1SMilanka Ringwald "CONTROL", 152be32e7f1SMilanka Ringwald "STATUS", 153be32e7f1SMilanka Ringwald "SPECIFIC_INQUIRY", 154be32e7f1SMilanka Ringwald "NOTIFY", 155be32e7f1SMilanka Ringwald "GENERAL_INQUIRY", 156be32e7f1SMilanka Ringwald "RESERVED5", 157be32e7f1SMilanka Ringwald "RESERVED6", 158be32e7f1SMilanka Ringwald "RESERVED7", 1599cc1f3ceSMilanka Ringwald "NOT IMPLEMENTED IN REMOTE", 1609cc1f3ceSMilanka Ringwald "ACCEPTED BY REMOTE", 1619cc1f3ceSMilanka Ringwald "REJECTED BY REMOTE", 162be32e7f1SMilanka Ringwald "IN_TRANSITION", 163be32e7f1SMilanka Ringwald "IMPLEMENTED_STABLE", 164be32e7f1SMilanka Ringwald "CHANGED_STABLE", 165be32e7f1SMilanka Ringwald "RESERVED", 166be32e7f1SMilanka Ringwald "INTERIM" 167be32e7f1SMilanka Ringwald }; 168be32e7f1SMilanka Ringwald const char * avrcp_ctype2str(uint8_t index){ 1693982eab9SMatthias Ringwald if (index < sizeof(avrcp_ctype_name)){ 170be32e7f1SMilanka Ringwald return avrcp_ctype_name[index]; 171be32e7f1SMilanka Ringwald } 172be32e7f1SMilanka Ringwald return "NONE"; 173be32e7f1SMilanka Ringwald } 174be32e7f1SMilanka Ringwald 175be32e7f1SMilanka Ringwald static const char * avrcp_shuffle_mode_name[] = { 176be32e7f1SMilanka Ringwald "SHUFFLE OFF", 177be32e7f1SMilanka Ringwald "SHUFFLE ALL TRACKS", 178be32e7f1SMilanka Ringwald "SHUFFLE GROUP" 179be32e7f1SMilanka Ringwald }; 180be32e7f1SMilanka Ringwald 181be32e7f1SMilanka Ringwald const char * avrcp_shuffle2str(uint8_t index){ 182be32e7f1SMilanka Ringwald if (index >= 1 && index <= 3) return avrcp_shuffle_mode_name[index-1]; 183be32e7f1SMilanka Ringwald return "NONE"; 184be32e7f1SMilanka Ringwald } 185be32e7f1SMilanka Ringwald 186be32e7f1SMilanka Ringwald static const char * avrcp_repeat_mode_name[] = { 187be32e7f1SMilanka Ringwald "REPEAT OFF", 188be32e7f1SMilanka Ringwald "REPEAT SINGLE TRACK", 189be32e7f1SMilanka Ringwald "REPEAT ALL TRACKS", 190be32e7f1SMilanka Ringwald "REPEAT GROUP" 191be32e7f1SMilanka Ringwald }; 192be32e7f1SMilanka Ringwald 193be32e7f1SMilanka Ringwald const char * avrcp_repeat2str(uint8_t index){ 194be32e7f1SMilanka Ringwald if (index >= 1 && index <= 4) return avrcp_repeat_mode_name[index-1]; 195be32e7f1SMilanka Ringwald return "NONE"; 196be32e7f1SMilanka Ringwald } 1976086246cSMilanka Ringwald 1984b338011SMilanka Ringwald uint8_t avrcp_cmd_opcode(uint8_t *packet, uint16_t size){ 1994b338011SMilanka Ringwald uint8_t cmd_opcode_index = 5; 2004b338011SMilanka Ringwald if (cmd_opcode_index > size) return AVRCP_CMD_OPCODE_UNDEFINED; 2014b338011SMilanka Ringwald return packet[cmd_opcode_index]; 2024b338011SMilanka Ringwald } 2034b338011SMilanka Ringwald 2046983e65eSMilanka Ringwald void avrcp_create_sdp_record(uint8_t controller, uint8_t * service, uint32_t service_record_handle, uint8_t browsing, uint16_t supported_features, const char * service_name, const char * service_provider_name){ 205be32e7f1SMilanka Ringwald uint8_t* attribute; 206be32e7f1SMilanka Ringwald de_create_sequence(service); 207be32e7f1SMilanka Ringwald 208be32e7f1SMilanka Ringwald // 0x0000 "Service Record Handle" 209235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE); 210be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle); 211be32e7f1SMilanka Ringwald 212be32e7f1SMilanka Ringwald // 0x0001 "Service Class ID List" 213235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST); 214be32e7f1SMilanka Ringwald attribute = de_push_sequence(service); 215be32e7f1SMilanka Ringwald { 216be32e7f1SMilanka Ringwald if (controller){ 2176086246cSMilanka Ringwald de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL); 2186086246cSMilanka Ringwald de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL_CONTROLLER); 219be32e7f1SMilanka Ringwald } else { 2206086246cSMilanka Ringwald de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET); 221be32e7f1SMilanka Ringwald } 222be32e7f1SMilanka Ringwald } 223be32e7f1SMilanka Ringwald de_pop_sequence(service, attribute); 224be32e7f1SMilanka Ringwald 225be32e7f1SMilanka Ringwald // 0x0004 "Protocol Descriptor List" 226235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST); 227be32e7f1SMilanka Ringwald attribute = de_push_sequence(service); 228be32e7f1SMilanka Ringwald { 229be32e7f1SMilanka Ringwald uint8_t* l2cpProtocol = de_push_sequence(attribute); 230be32e7f1SMilanka Ringwald { 231235946f1SMatthias Ringwald de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP); 232235946f1SMatthias Ringwald de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVCTP); 233be32e7f1SMilanka Ringwald } 234be32e7f1SMilanka Ringwald de_pop_sequence(attribute, l2cpProtocol); 235be32e7f1SMilanka Ringwald 236be32e7f1SMilanka Ringwald uint8_t* avctpProtocol = de_push_sequence(attribute); 237be32e7f1SMilanka Ringwald { 238235946f1SMatthias Ringwald de_add_number(avctpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVCTP); // avctpProtocol_service 239be32e7f1SMilanka Ringwald de_add_number(avctpProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version 240be32e7f1SMilanka Ringwald } 241be32e7f1SMilanka Ringwald de_pop_sequence(attribute, avctpProtocol); 242be32e7f1SMilanka Ringwald } 243be32e7f1SMilanka Ringwald de_pop_sequence(service, attribute); 244be32e7f1SMilanka Ringwald 245be32e7f1SMilanka Ringwald // 0x0005 "Public Browse Group" 246235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group 247be32e7f1SMilanka Ringwald attribute = de_push_sequence(service); 248be32e7f1SMilanka Ringwald { 249235946f1SMatthias Ringwald de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT); 250be32e7f1SMilanka Ringwald } 251be32e7f1SMilanka Ringwald de_pop_sequence(service, attribute); 252be32e7f1SMilanka Ringwald 253be32e7f1SMilanka Ringwald // 0x0009 "Bluetooth Profile Descriptor List" 254235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST); 255be32e7f1SMilanka Ringwald attribute = de_push_sequence(service); 256be32e7f1SMilanka Ringwald { 257be32e7f1SMilanka Ringwald uint8_t *avrcProfile = de_push_sequence(attribute); 258be32e7f1SMilanka Ringwald { 2596086246cSMilanka Ringwald de_add_number(avrcProfile, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL); 260be32e7f1SMilanka Ringwald de_add_number(avrcProfile, DE_UINT, DE_SIZE_16, 0x0105); 261be32e7f1SMilanka Ringwald } 262be32e7f1SMilanka Ringwald de_pop_sequence(attribute, avrcProfile); 263be32e7f1SMilanka Ringwald } 264be32e7f1SMilanka Ringwald de_pop_sequence(service, attribute); 265be32e7f1SMilanka Ringwald 266a0f524f0SMatthias Ringwald // 0x000d "Additional Bluetooth Profile Descriptor List" 2675c806868SMatthias Ringwald if (browsing){ 268a0f524f0SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS); 269a0f524f0SMatthias Ringwald attribute = de_push_sequence(service); 2705c806868SMatthias Ringwald { 2715c806868SMatthias Ringwald uint8_t * des = de_push_sequence(attribute); 2725c806868SMatthias Ringwald { 2735c806868SMatthias Ringwald uint8_t* browsing_l2cpProtocol = de_push_sequence(des); 274a0f524f0SMatthias Ringwald { 275a0f524f0SMatthias Ringwald de_add_number(browsing_l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP); 276a0f524f0SMatthias Ringwald de_add_number(browsing_l2cpProtocol, DE_UINT, DE_SIZE_16, PSM_AVCTP_BROWSING); 277a0f524f0SMatthias Ringwald } 2785c806868SMatthias Ringwald de_pop_sequence(des, browsing_l2cpProtocol); 279a0f524f0SMatthias Ringwald 2805c806868SMatthias Ringwald uint8_t* browsing_avctpProtocol = de_push_sequence(des); 281a0f524f0SMatthias Ringwald { 282a0f524f0SMatthias Ringwald de_add_number(browsing_avctpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVCTP); // browsing_avctpProtocol_service 283a0f524f0SMatthias Ringwald de_add_number(browsing_avctpProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version 284a0f524f0SMatthias Ringwald } 2855c806868SMatthias Ringwald de_pop_sequence(des, browsing_avctpProtocol); 2865c806868SMatthias Ringwald } 2875c806868SMatthias Ringwald de_pop_sequence(attribute, des); 288a0f524f0SMatthias Ringwald } 289a0f524f0SMatthias Ringwald de_pop_sequence(service, attribute); 2905c806868SMatthias Ringwald } 291a0f524f0SMatthias Ringwald 292be32e7f1SMilanka Ringwald 293be32e7f1SMilanka Ringwald // 0x0100 "Service Name" 294be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); 295be32e7f1SMilanka Ringwald if (service_name){ 296be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name); 297be32e7f1SMilanka Ringwald } else { 298be32e7f1SMilanka Ringwald if (controller){ 299be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(default_avrcp_controller_service_name), (uint8_t *) default_avrcp_controller_service_name); 300be32e7f1SMilanka Ringwald } else { 301be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(default_avrcp_target_service_name), (uint8_t *) default_avrcp_target_service_name); 302be32e7f1SMilanka Ringwald } 303be32e7f1SMilanka Ringwald } 304be32e7f1SMilanka Ringwald 305be32e7f1SMilanka Ringwald // 0x0100 "Provider Name" 306be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102); 307be32e7f1SMilanka Ringwald if (service_provider_name){ 308be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name); 309be32e7f1SMilanka Ringwald } else { 310be32e7f1SMilanka Ringwald if (controller){ 311be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(default_avrcp_controller_service_provider_name), (uint8_t *) default_avrcp_controller_service_provider_name); 312be32e7f1SMilanka Ringwald } else { 313be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(default_avrcp_target_service_provider_name), (uint8_t *) default_avrcp_target_service_provider_name); 314be32e7f1SMilanka Ringwald } 315be32e7f1SMilanka Ringwald } 316be32e7f1SMilanka Ringwald 317be32e7f1SMilanka Ringwald // 0x0311 "Supported Features" 318be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311); 319be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, supported_features); 320be32e7f1SMilanka Ringwald } 321be32e7f1SMilanka Ringwald 3226983e65eSMilanka Ringwald static avrcp_connection_t * get_avrcp_connection_for_bd_addr(bd_addr_t addr, avrcp_context_t * context){ 3236983e65eSMilanka Ringwald btstack_linked_list_iterator_t it; 3246983e65eSMilanka Ringwald btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &context->connections); 3256983e65eSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 3266983e65eSMilanka Ringwald avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it); 3276983e65eSMilanka Ringwald if (memcmp(addr, connection->remote_addr, 6) != 0) continue; 3286983e65eSMilanka Ringwald return connection; 3296983e65eSMilanka Ringwald } 3306983e65eSMilanka Ringwald return NULL; 331be32e7f1SMilanka Ringwald } 332be32e7f1SMilanka Ringwald 3336983e65eSMilanka Ringwald avrcp_connection_t * get_avrcp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid, avrcp_context_t * context){ 3346983e65eSMilanka Ringwald btstack_linked_list_iterator_t it; 3356983e65eSMilanka Ringwald btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &context->connections); 3366983e65eSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 3376983e65eSMilanka Ringwald avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it); 3386983e65eSMilanka Ringwald if (connection->l2cap_signaling_cid != l2cap_cid) continue; 3396983e65eSMilanka Ringwald return connection; 3406983e65eSMilanka Ringwald } 3416983e65eSMilanka Ringwald return NULL; 342be32e7f1SMilanka Ringwald } 343be32e7f1SMilanka Ringwald 34401dc6e35SMilanka Ringwald avrcp_connection_t * get_avrcp_connection_for_avrcp_cid(uint16_t avrcp_cid, avrcp_context_t * context){ 3456983e65eSMilanka Ringwald btstack_linked_list_iterator_t it; 3466983e65eSMilanka Ringwald btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &context->connections); 3476983e65eSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 3486983e65eSMilanka Ringwald avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it); 34901dc6e35SMilanka Ringwald if (connection->avrcp_cid != avrcp_cid) continue; 3506983e65eSMilanka Ringwald return connection; 3516983e65eSMilanka Ringwald } 3526983e65eSMilanka Ringwald return NULL; 3536983e65eSMilanka Ringwald } 3546983e65eSMilanka Ringwald 3556983e65eSMilanka Ringwald void avrcp_request_can_send_now(avrcp_connection_t * connection, uint16_t l2cap_cid){ 3566983e65eSMilanka Ringwald connection->wait_to_send = 1; 3576983e65eSMilanka Ringwald l2cap_request_can_send_now_event(l2cap_cid); 3586983e65eSMilanka Ringwald } 3596983e65eSMilanka Ringwald 3606983e65eSMilanka Ringwald 3616983e65eSMilanka Ringwald static uint16_t avdtp_get_next_avrcp_cid(void){ 3626983e65eSMilanka Ringwald avrcp_cid_counter++; 3636983e65eSMilanka Ringwald if (avrcp_cid_counter == 0){ 3646983e65eSMilanka Ringwald avrcp_cid_counter = 1; 3656983e65eSMilanka Ringwald } 3666983e65eSMilanka Ringwald return avrcp_cid_counter; 3676983e65eSMilanka Ringwald } 3686983e65eSMilanka Ringwald 3696983e65eSMilanka Ringwald static avrcp_connection_t * avrcp_create_connection(bd_addr_t remote_addr, avrcp_context_t * context){ 3706983e65eSMilanka Ringwald avrcp_connection_t * connection = btstack_memory_avrcp_connection_get(); 3714567cc17SMilanka Ringwald if (!connection){ 3724567cc17SMilanka Ringwald log_error("avrcp: not enough memory to create connection"); 3734567cc17SMilanka Ringwald return NULL; 3744567cc17SMilanka Ringwald } 3756983e65eSMilanka Ringwald memset(connection, 0, sizeof(avrcp_connection_t)); 3766983e65eSMilanka Ringwald connection->state = AVCTP_CONNECTION_IDLE; 3776983e65eSMilanka Ringwald connection->transaction_label = 0xFF; 3786983e65eSMilanka Ringwald connection->avrcp_cid = avdtp_get_next_avrcp_cid(); 3796983e65eSMilanka Ringwald memcpy(connection->remote_addr, remote_addr, 6); 3806983e65eSMilanka Ringwald btstack_linked_list_add(&context->connections, (btstack_linked_item_t *) connection); 3816983e65eSMilanka Ringwald return connection; 3826983e65eSMilanka Ringwald } 3836983e65eSMilanka Ringwald 3846983e65eSMilanka Ringwald 3856983e65eSMilanka Ringwald void avrcp_emit_connection_established(btstack_packet_handler_t callback, uint16_t avrcp_cid, bd_addr_t addr, uint8_t status){ 386b193c45eSMilanka Ringwald if (!callback) return; 3876086246cSMilanka Ringwald uint8_t event[12]; 388b193c45eSMilanka Ringwald int pos = 0; 389b193c45eSMilanka Ringwald event[pos++] = HCI_EVENT_AVRCP_META; 390b193c45eSMilanka Ringwald event[pos++] = sizeof(event) - 2; 391b193c45eSMilanka Ringwald event[pos++] = AVRCP_SUBEVENT_CONNECTION_ESTABLISHED; 3926f43fcd7SMatthias Ringwald event[pos++] = status; 393b193c45eSMilanka Ringwald reverse_bd_addr(addr,&event[pos]); 394b193c45eSMilanka Ringwald pos += 6; 395b193c45eSMilanka Ringwald little_endian_store_16(event, pos, avrcp_cid); 396b193c45eSMilanka Ringwald pos += 2; 397b193c45eSMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 398b193c45eSMilanka Ringwald } 399b193c45eSMilanka Ringwald 4006983e65eSMilanka Ringwald void avrcp_emit_connection_closed(btstack_packet_handler_t callback, uint16_t avrcp_cid){ 401be32e7f1SMilanka Ringwald if (!callback) return; 402be32e7f1SMilanka Ringwald uint8_t event[5]; 403be32e7f1SMilanka Ringwald int pos = 0; 404be32e7f1SMilanka Ringwald event[pos++] = HCI_EVENT_AVRCP_META; 405be32e7f1SMilanka Ringwald event[pos++] = sizeof(event) - 2; 406be32e7f1SMilanka Ringwald event[pos++] = AVRCP_SUBEVENT_CONNECTION_RELEASED; 407b193c45eSMilanka Ringwald little_endian_store_16(event, pos, avrcp_cid); 408be32e7f1SMilanka Ringwald pos += 2; 409be32e7f1SMilanka Ringwald (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 410be32e7f1SMilanka Ringwald } 411be32e7f1SMilanka Ringwald 4126086246cSMilanka Ringwald static void avrcp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 4136983e65eSMilanka Ringwald avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(sdp_query_context->avrcp_cid, sdp_query_context); 4146983e65eSMilanka Ringwald if (!connection) return; 4156983e65eSMilanka Ringwald if (connection->state != AVCTP_SIGNALING_W4_SDP_QUERY_COMPLETE) return; 4166086246cSMilanka Ringwald UNUSED(packet_type); 4176086246cSMilanka Ringwald UNUSED(channel); 4186086246cSMilanka Ringwald UNUSED(size); 4195448c259SMilanka Ringwald uint8_t status; 4206086246cSMilanka Ringwald des_iterator_t des_list_it; 4216086246cSMilanka Ringwald des_iterator_t prot_it; 4226086246cSMilanka Ringwald // uint32_t avdtp_remote_uuid = 0; 4236086246cSMilanka Ringwald 4246086246cSMilanka Ringwald switch (hci_event_packet_get_type(packet)){ 4256086246cSMilanka Ringwald case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: 4266086246cSMilanka Ringwald // Handle new SDP record 4276086246cSMilanka Ringwald if (sdp_event_query_attribute_byte_get_record_id(packet) != record_id) { 4286086246cSMilanka Ringwald record_id = sdp_event_query_attribute_byte_get_record_id(packet); 4296086246cSMilanka Ringwald // log_info("SDP Record: Nr: %d", record_id); 4306086246cSMilanka Ringwald } 4316086246cSMilanka Ringwald 4326086246cSMilanka Ringwald if (sdp_event_query_attribute_byte_get_attribute_length(packet) <= attribute_value_buffer_size) { 4336086246cSMilanka Ringwald attribute_value[sdp_event_query_attribute_byte_get_data_offset(packet)] = sdp_event_query_attribute_byte_get_data(packet); 4346086246cSMilanka Ringwald 4356086246cSMilanka Ringwald if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)) { 4366086246cSMilanka Ringwald switch(sdp_event_query_attribute_byte_get_attribute_id(packet)) { 4376086246cSMilanka Ringwald case BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST: 4386086246cSMilanka Ringwald if (de_get_element_type(attribute_value) != DE_DES) break; 4396086246cSMilanka Ringwald for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) { 4406086246cSMilanka Ringwald uint8_t * element = des_iterator_get_element(&des_list_it); 4416086246cSMilanka Ringwald if (de_get_element_type(element) != DE_UUID) continue; 4426086246cSMilanka Ringwald uint32_t uuid = de_get_uuid32(element); 4436086246cSMilanka Ringwald switch (uuid){ 4446086246cSMilanka Ringwald case BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET: 4456983e65eSMilanka Ringwald if (sdp_query_context->role == AVRCP_CONTROLLER) { 4466983e65eSMilanka Ringwald sdp_query_context->role_supported = 1; 4476086246cSMilanka Ringwald break; 4486086246cSMilanka Ringwald } 4496086246cSMilanka Ringwald break; 4506086246cSMilanka Ringwald case BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL: 451df642728SMilanka Ringwald case BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL_CONTROLLER: 4526983e65eSMilanka Ringwald if (sdp_query_context->role == AVRCP_TARGET) { 4536983e65eSMilanka Ringwald sdp_query_context->role_supported = 1; 4546086246cSMilanka Ringwald break; 4556086246cSMilanka Ringwald } 4566086246cSMilanka Ringwald break; 4576086246cSMilanka Ringwald default: 4586086246cSMilanka Ringwald break; 4596086246cSMilanka Ringwald } 4606086246cSMilanka Ringwald } 4616086246cSMilanka Ringwald break; 4626086246cSMilanka Ringwald 4636086246cSMilanka Ringwald case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST: { 4646086246cSMilanka Ringwald // log_info("SDP Attribute: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet)); 4656086246cSMilanka Ringwald for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) { 4666086246cSMilanka Ringwald uint8_t *des_element; 4676086246cSMilanka Ringwald uint8_t *element; 4686086246cSMilanka Ringwald uint32_t uuid; 4696086246cSMilanka Ringwald 4706086246cSMilanka Ringwald if (des_iterator_get_type(&des_list_it) != DE_DES) continue; 4716086246cSMilanka Ringwald 4726086246cSMilanka Ringwald des_element = des_iterator_get_element(&des_list_it); 4736086246cSMilanka Ringwald des_iterator_init(&prot_it, des_element); 4746086246cSMilanka Ringwald element = des_iterator_get_element(&prot_it); 4756086246cSMilanka Ringwald 4766086246cSMilanka Ringwald if (de_get_element_type(element) != DE_UUID) continue; 4776086246cSMilanka Ringwald 4786086246cSMilanka Ringwald uuid = de_get_uuid32(element); 4796086246cSMilanka Ringwald switch (uuid){ 4806086246cSMilanka Ringwald case BLUETOOTH_PROTOCOL_L2CAP: 4816086246cSMilanka Ringwald if (!des_iterator_has_more(&prot_it)) continue; 4826086246cSMilanka Ringwald des_iterator_next(&prot_it); 4836983e65eSMilanka Ringwald de_element_get_uint16(des_iterator_get_element(&prot_it), &sdp_query_context->avrcp_l2cap_psm); 4846086246cSMilanka Ringwald break; 4856086246cSMilanka Ringwald case BLUETOOTH_PROTOCOL_AVCTP: 4866086246cSMilanka Ringwald if (!des_iterator_has_more(&prot_it)) continue; 4876086246cSMilanka Ringwald des_iterator_next(&prot_it); 4886983e65eSMilanka Ringwald de_element_get_uint16(des_iterator_get_element(&prot_it), &sdp_query_context->avrcp_version); 4896086246cSMilanka Ringwald break; 4906086246cSMilanka Ringwald default: 4916086246cSMilanka Ringwald break; 4926086246cSMilanka Ringwald } 4936086246cSMilanka Ringwald } 4946086246cSMilanka Ringwald } 4956086246cSMilanka Ringwald break; 496227d16a5SMatthias Ringwald case BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS: { 497227d16a5SMatthias Ringwald // log_info("SDP Attribute: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet)); 498227d16a5SMatthias Ringwald if (de_get_element_type(attribute_value) != DE_DES) break; 499227d16a5SMatthias Ringwald 500227d16a5SMatthias Ringwald des_iterator_t des_list_0_it; 501227d16a5SMatthias Ringwald uint8_t *element_0; 502227d16a5SMatthias Ringwald 503227d16a5SMatthias Ringwald des_iterator_init(&des_list_0_it, attribute_value); 504227d16a5SMatthias Ringwald element_0 = des_iterator_get_element(&des_list_0_it); 505227d16a5SMatthias Ringwald 506227d16a5SMatthias Ringwald for (des_iterator_init(&des_list_it, element_0); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) { 507227d16a5SMatthias Ringwald uint8_t *des_element; 508227d16a5SMatthias Ringwald uint8_t *element; 509227d16a5SMatthias Ringwald uint32_t uuid; 510227d16a5SMatthias Ringwald 511227d16a5SMatthias Ringwald if (des_iterator_get_type(&des_list_it) != DE_DES) continue; 512227d16a5SMatthias Ringwald 513227d16a5SMatthias Ringwald des_element = des_iterator_get_element(&des_list_it); 514227d16a5SMatthias Ringwald des_iterator_init(&prot_it, des_element); 515227d16a5SMatthias Ringwald element = des_iterator_get_element(&prot_it); 516227d16a5SMatthias Ringwald 517227d16a5SMatthias Ringwald if (de_get_element_type(element) != DE_UUID) continue; 518227d16a5SMatthias Ringwald 519227d16a5SMatthias Ringwald uuid = de_get_uuid32(element); 520227d16a5SMatthias Ringwald switch (uuid){ 521227d16a5SMatthias Ringwald case BLUETOOTH_PROTOCOL_L2CAP: 522227d16a5SMatthias Ringwald if (!des_iterator_has_more(&prot_it)) continue; 523227d16a5SMatthias Ringwald des_iterator_next(&prot_it); 5246983e65eSMilanka Ringwald de_element_get_uint16(des_iterator_get_element(&prot_it), &sdp_query_context->avrcp_browsing_l2cap_psm); 525227d16a5SMatthias Ringwald break; 526227d16a5SMatthias Ringwald case BLUETOOTH_PROTOCOL_AVCTP: 527227d16a5SMatthias Ringwald if (!des_iterator_has_more(&prot_it)) continue; 528227d16a5SMatthias Ringwald des_iterator_next(&prot_it); 5296983e65eSMilanka Ringwald de_element_get_uint16(des_iterator_get_element(&prot_it), &sdp_query_context->avrcp_browsing_version); 530227d16a5SMatthias Ringwald break; 531227d16a5SMatthias Ringwald default: 532227d16a5SMatthias Ringwald break; 533227d16a5SMatthias Ringwald } 534227d16a5SMatthias Ringwald } 535227d16a5SMatthias Ringwald } 536227d16a5SMatthias Ringwald break; 5376086246cSMilanka Ringwald default: 5386086246cSMilanka Ringwald break; 5396086246cSMilanka Ringwald } 5406086246cSMilanka Ringwald } 5416086246cSMilanka Ringwald } else { 5426086246cSMilanka Ringwald log_error("SDP attribute value buffer size exceeded: available %d, required %d", attribute_value_buffer_size, sdp_event_query_attribute_byte_get_attribute_length(packet)); 5436086246cSMilanka Ringwald } 5446086246cSMilanka Ringwald break; 5456086246cSMilanka Ringwald 5466086246cSMilanka Ringwald case SDP_EVENT_QUERY_COMPLETE: 5475448c259SMilanka Ringwald status = sdp_event_query_complete_get_status(packet); 5485448c259SMilanka Ringwald if (status != ERROR_CODE_SUCCESS){ 5495448c259SMilanka Ringwald avrcp_emit_connection_established(sdp_query_context->avrcp_callback, connection->avrcp_cid, connection->remote_addr, status); 5505448c259SMilanka Ringwald btstack_linked_list_remove(&sdp_query_context->connections, (btstack_linked_item_t*) connection); 5515448c259SMilanka Ringwald btstack_memory_avrcp_connection_free(connection); 5525448c259SMilanka Ringwald log_info("AVRCP: SDP query failed with status 0x%02x.", status); 5535448c259SMilanka Ringwald break; 5545448c259SMilanka Ringwald } 5555448c259SMilanka Ringwald 5566983e65eSMilanka Ringwald if (!sdp_query_context->role_supported || !sdp_query_context->avrcp_l2cap_psm){ 557be32e7f1SMilanka Ringwald connection->state = AVCTP_CONNECTION_IDLE; 5586983e65eSMilanka Ringwald avrcp_emit_connection_established(sdp_query_context->avrcp_callback, connection->avrcp_cid, connection->remote_addr, SDP_SERVICE_NOT_FOUND); 5595448c259SMilanka Ringwald btstack_linked_list_remove(&sdp_query_context->connections, (btstack_linked_item_t*) connection); 5605448c259SMilanka Ringwald btstack_memory_avrcp_connection_free(connection); 5616983e65eSMilanka Ringwald break; 5626983e65eSMilanka Ringwald } 5635448c259SMilanka Ringwald // log_info("AVRCP Control PSM 0x%02x, Browsing PSM 0x%02x", sdp_query_context->avrcp_l2cap_psm, sdp_query_context->avrcp_browsing_l2cap_psm); 5646983e65eSMilanka Ringwald connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED; 5656983e65eSMilanka Ringwald l2cap_create_channel(sdp_query_context->packet_handler, connection->remote_addr, sdp_query_context->avrcp_l2cap_psm, l2cap_max_mtu(), NULL); 5666983e65eSMilanka Ringwald break; 5676983e65eSMilanka Ringwald } 568be32e7f1SMilanka Ringwald } 569be32e7f1SMilanka Ringwald 5706983e65eSMilanka Ringwald void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context){ 5716983e65eSMilanka Ringwald UNUSED(channel); 5726983e65eSMilanka Ringwald UNUSED(size); 573be32e7f1SMilanka Ringwald bd_addr_t event_addr; 574be32e7f1SMilanka Ringwald uint16_t local_cid; 575b0d75c91SMilanka Ringwald uint8_t status; 576be32e7f1SMilanka Ringwald avrcp_connection_t * connection = NULL; 577be32e7f1SMilanka Ringwald 5786983e65eSMilanka Ringwald if (packet_type != HCI_EVENT_PACKET) return; 579be32e7f1SMilanka Ringwald 580be32e7f1SMilanka Ringwald switch (hci_event_packet_get_type(packet)) { 58134b22aacSMilanka Ringwald case HCI_EVENT_DISCONNECTION_COMPLETE: 5826983e65eSMilanka Ringwald avrcp_emit_connection_closed(context->avrcp_callback, 0); 58334b22aacSMilanka Ringwald break; 584be32e7f1SMilanka Ringwald case L2CAP_EVENT_INCOMING_CONNECTION: 585be32e7f1SMilanka Ringwald l2cap_event_incoming_connection_get_address(packet, event_addr); 586be32e7f1SMilanka Ringwald local_cid = l2cap_event_incoming_connection_get_local_cid(packet); 5876086246cSMilanka Ringwald connection = avrcp_create_connection(event_addr, context); 5880f76c2d7SMatthias Ringwald if (!connection) { 5890f76c2d7SMatthias Ringwald log_error("Failed to alloc connection structure"); 5900f76c2d7SMatthias Ringwald l2cap_decline_connection(local_cid); 591be32e7f1SMilanka Ringwald break; 592be32e7f1SMilanka Ringwald } 5930f76c2d7SMatthias Ringwald connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED; 5940f76c2d7SMatthias Ringwald connection->l2cap_signaling_cid = local_cid; 595b0d75c91SMilanka Ringwald log_info("L2CAP_EVENT_INCOMING_CONNECTION avrcp_cid 0x%02x, l2cap_signaling_cid 0x%02x", connection->avrcp_cid, connection->l2cap_signaling_cid); 5960f76c2d7SMatthias Ringwald l2cap_accept_connection(local_cid); 597be32e7f1SMilanka Ringwald break; 598be32e7f1SMilanka Ringwald 599be32e7f1SMilanka Ringwald case L2CAP_EVENT_CHANNEL_OPENED: 600be32e7f1SMilanka Ringwald l2cap_event_channel_opened_get_address(packet, event_addr); 601b0d75c91SMilanka Ringwald status = l2cap_event_channel_opened_get_status(packet); 6020f76c2d7SMatthias Ringwald local_cid = l2cap_event_channel_opened_get_local_cid(packet); 6030f76c2d7SMatthias Ringwald 604b0d75c91SMilanka Ringwald connection = get_avrcp_connection_for_bd_addr(event_addr, context); 6056086246cSMilanka Ringwald if (!connection){ 606b0d75c91SMilanka Ringwald log_error("Failed to alloc AVRCP connection structure"); 6076983e65eSMilanka Ringwald avrcp_emit_connection_established(context->avrcp_callback, connection->avrcp_cid, event_addr, BTSTACK_MEMORY_ALLOC_FAILED); 6080f76c2d7SMatthias Ringwald l2cap_disconnect(local_cid, 0); // reason isn't used 609b193c45eSMilanka Ringwald break; 610b193c45eSMilanka Ringwald } 611b0d75c91SMilanka Ringwald if (status != ERROR_CODE_SUCCESS){ 612b0d75c91SMilanka Ringwald log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status); 6136983e65eSMilanka Ringwald avrcp_emit_connection_established(context->avrcp_callback, connection->avrcp_cid, event_addr, status); 6146086246cSMilanka Ringwald btstack_linked_list_remove(&context->connections, (btstack_linked_item_t*) connection); 6156086246cSMilanka Ringwald btstack_memory_avrcp_connection_free(connection); 6166086246cSMilanka Ringwald break; 6176086246cSMilanka Ringwald } 618be32e7f1SMilanka Ringwald connection->l2cap_signaling_cid = local_cid; 619*d1207cd8SMilanka Ringwald connection->song_length_ms = 0xFFFFFFFF; 620*d1207cd8SMilanka Ringwald connection->song_position_ms = 0xFFFFFFFF; 621*d1207cd8SMilanka Ringwald connection->playback_status = AVRCP_PLAYBACK_STATUS_ERROR; 622*d1207cd8SMilanka Ringwald 6236086246cSMilanka Ringwald log_info("L2CAP_EVENT_CHANNEL_OPENED avrcp_cid 0x%02x, l2cap_signaling_cid 0x%02x", connection->avrcp_cid, connection->l2cap_signaling_cid); 624be32e7f1SMilanka Ringwald connection->state = AVCTP_CONNECTION_OPENED; 6256983e65eSMilanka Ringwald avrcp_emit_connection_established(context->avrcp_callback, connection->avrcp_cid, event_addr, ERROR_CODE_SUCCESS); 626be32e7f1SMilanka Ringwald break; 627be32e7f1SMilanka Ringwald 628be32e7f1SMilanka Ringwald case L2CAP_EVENT_CHANNEL_CLOSED: 629be32e7f1SMilanka Ringwald // data: event (8), len(8), channel (16) 630be32e7f1SMilanka Ringwald local_cid = l2cap_event_channel_closed_get_local_cid(packet); 6316086246cSMilanka Ringwald connection = get_avrcp_connection_for_l2cap_signaling_cid(local_cid, context); 632be32e7f1SMilanka Ringwald if (connection){ 6336983e65eSMilanka Ringwald avrcp_emit_connection_closed(context->avrcp_callback, connection->avrcp_cid); 6346f43fcd7SMatthias Ringwald // free connection 6356086246cSMilanka Ringwald btstack_linked_list_remove(&context->connections, (btstack_linked_item_t*) connection); 6366f43fcd7SMatthias Ringwald btstack_memory_avrcp_connection_free(connection); 637be32e7f1SMilanka Ringwald break; 638be32e7f1SMilanka Ringwald } 639be32e7f1SMilanka Ringwald break; 640be32e7f1SMilanka Ringwald default: 641be32e7f1SMilanka Ringwald break; 642be32e7f1SMilanka Ringwald } 643be32e7f1SMilanka Ringwald } 644be32e7f1SMilanka Ringwald 6456086246cSMilanka Ringwald uint8_t avrcp_connect(bd_addr_t bd_addr, avrcp_context_t * context, uint16_t * avrcp_cid){ 6466086246cSMilanka Ringwald avrcp_connection_t * connection = get_avrcp_connection_for_bd_addr(bd_addr, context); 6478a2c6c7cSMilanka Ringwald if (connection){ 6488a2c6c7cSMilanka Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 6498a2c6c7cSMilanka Ringwald } 6506086246cSMilanka Ringwald connection = avrcp_create_connection(bd_addr, context); 651be32e7f1SMilanka Ringwald if (!connection){ 6528a2c6c7cSMilanka Ringwald log_error("avrcp: could not allocate connection struct."); 6538a2c6c7cSMilanka Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 654be32e7f1SMilanka Ringwald } 6558a2c6c7cSMilanka Ringwald 6566086246cSMilanka Ringwald if (!avrcp_cid) return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 6576086246cSMilanka Ringwald 658b0d75c91SMilanka Ringwald *avrcp_cid = connection->avrcp_cid; 6596086246cSMilanka Ringwald connection->state = AVCTP_SIGNALING_W4_SDP_QUERY_COMPLETE; 6606983e65eSMilanka Ringwald 6616983e65eSMilanka Ringwald context->avrcp_l2cap_psm = 0; 6626983e65eSMilanka Ringwald context->avrcp_version = 0; 6636983e65eSMilanka Ringwald context->avrcp_cid = connection->avrcp_cid; 6646983e65eSMilanka Ringwald 6656983e65eSMilanka Ringwald sdp_query_context = context; 6666086246cSMilanka Ringwald 6675448c259SMilanka Ringwald return sdp_client_query_uuid16(&avrcp_handle_sdp_client_query_result, bd_addr, BLUETOOTH_PROTOCOL_AVCTP); 668be32e7f1SMilanka Ringwald } 669