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 uint8_t attribute_value[1000]; 926983e65eSMilanka Ringwald static const unsigned int attribute_value_buffer_size = sizeof(attribute_value); 936983e65eSMilanka Ringwald 946086246cSMilanka Ringwald 95be32e7f1SMilanka Ringwald static const char * avrcp_subunit_type_name[] = { 96be32e7f1SMilanka Ringwald "MONITOR", "AUDIO", "PRINTER", "DISC", "TAPE_RECORDER_PLAYER", "TUNER", 97be32e7f1SMilanka Ringwald "CA", "CAMERA", "RESERVED", "PANEL", "BULLETIN_BOARD", "CAMERA_STORAGE", 98be32e7f1SMilanka Ringwald "VENDOR_UNIQUE", "RESERVED_FOR_ALL_SUBUNIT_TYPES", 99be32e7f1SMilanka Ringwald "EXTENDED_TO_NEXT_BYTE", "UNIT", "ERROR" 100be32e7f1SMilanka Ringwald }; 1016983e65eSMilanka Ringwald 102be32e7f1SMilanka Ringwald const char * avrcp_subunit2str(uint16_t index){ 103be32e7f1SMilanka Ringwald if (index <= 11) return avrcp_subunit_type_name[index]; 104be32e7f1SMilanka Ringwald if (index >= 0x1C && index <= 0x1F) return avrcp_subunit_type_name[index - 0x10]; 105be32e7f1SMilanka Ringwald return avrcp_subunit_type_name[16]; 106be32e7f1SMilanka Ringwald } 107be32e7f1SMilanka Ringwald 108be32e7f1SMilanka Ringwald static const char * avrcp_event_name[] = { 109be32e7f1SMilanka Ringwald "ERROR", "PLAYBACK_STATUS_CHANGED", 110be32e7f1SMilanka Ringwald "TRACK_CHANGED", "TRACK_REACHED_END", "TRACK_REACHED_START", 111be32e7f1SMilanka Ringwald "PLAYBACK_POS_CHANGED", "BATT_STATUS_CHANGED", "SYSTEM_STATUS_CHANGED", 112be32e7f1SMilanka Ringwald "PLAYER_APPLICATION_SETTING_CHANGED", "NOW_PLAYING_CONTENT_CHANGED", 113be32e7f1SMilanka Ringwald "AVAILABLE_PLAYERS_CHANGED", "ADDRESSED_PLAYER_CHANGED", "UIDS_CHANGED", "VOLUME_CHANGED" 114be32e7f1SMilanka Ringwald }; 115be32e7f1SMilanka Ringwald const char * avrcp_event2str(uint16_t index){ 116be32e7f1SMilanka Ringwald if (index <= 0x0d) return avrcp_event_name[index]; 117be32e7f1SMilanka Ringwald return avrcp_event_name[0]; 118be32e7f1SMilanka Ringwald } 119be32e7f1SMilanka Ringwald 120be32e7f1SMilanka Ringwald static const char * avrcp_operation_name[] = { 121be32e7f1SMilanka Ringwald "NOT SUPPORTED", // 0x3B 122be32e7f1SMilanka Ringwald "SKIP", "NOT SUPPORTED", "NOT SUPPORTED", "NOT SUPPORTED", "NOT SUPPORTED", 123be32e7f1SMilanka Ringwald "VOLUME_UP", "VOLUME_DOWN", "MUTE", "PLAY", "STOP", "PAUSE", "NOT SUPPORTED", 124be32e7f1SMilanka Ringwald "REWIND", "FAST_FORWARD", "NOT SUPPORTED", "FORWARD", "BACKWARD" // 0x4C 125be32e7f1SMilanka Ringwald }; 126be32e7f1SMilanka Ringwald const char * avrcp_operation2str(uint8_t index){ 127be32e7f1SMilanka Ringwald if (index >= 0x3B && index <= 0x4C) return avrcp_operation_name[index - 0x3B]; 128be32e7f1SMilanka Ringwald return avrcp_operation_name[0]; 129be32e7f1SMilanka Ringwald } 130be32e7f1SMilanka Ringwald 131be32e7f1SMilanka Ringwald static const char * avrcp_media_attribute_id_name[] = { 132be32e7f1SMilanka Ringwald "NONE", "TITLE", "ARTIST", "ALBUM", "TRACK", "TOTAL TRACKS", "GENRE", "SONG LENGTH" 133be32e7f1SMilanka Ringwald }; 134be32e7f1SMilanka Ringwald const char * avrcp_attribute2str(uint8_t index){ 135be32e7f1SMilanka Ringwald if (index >= 1 && index <= 7) return avrcp_media_attribute_id_name[index]; 136be32e7f1SMilanka Ringwald return avrcp_media_attribute_id_name[0]; 137be32e7f1SMilanka Ringwald } 138be32e7f1SMilanka Ringwald 139be32e7f1SMilanka Ringwald static const char * avrcp_play_status_name[] = { 140be32e7f1SMilanka Ringwald "STOPPED", "PLAYING", "PAUSED", "FORWARD SEEK", "REVERSE SEEK", 141be32e7f1SMilanka Ringwald "ERROR" // 0xFF 142be32e7f1SMilanka Ringwald }; 143be32e7f1SMilanka Ringwald const char * avrcp_play_status2str(uint8_t index){ 144be32e7f1SMilanka Ringwald if (index >= 1 && index <= 4) return avrcp_play_status_name[index]; 145be32e7f1SMilanka Ringwald return avrcp_play_status_name[5]; 146be32e7f1SMilanka Ringwald } 147be32e7f1SMilanka Ringwald 148be32e7f1SMilanka Ringwald static const char * avrcp_ctype_name[] = { 149be32e7f1SMilanka Ringwald "CONTROL", 150be32e7f1SMilanka Ringwald "STATUS", 151be32e7f1SMilanka Ringwald "SPECIFIC_INQUIRY", 152be32e7f1SMilanka Ringwald "NOTIFY", 153be32e7f1SMilanka Ringwald "GENERAL_INQUIRY", 154be32e7f1SMilanka Ringwald "RESERVED5", 155be32e7f1SMilanka Ringwald "RESERVED6", 156be32e7f1SMilanka Ringwald "RESERVED7", 1579cc1f3ceSMilanka Ringwald "NOT IMPLEMENTED IN REMOTE", 1589cc1f3ceSMilanka Ringwald "ACCEPTED BY REMOTE", 1599cc1f3ceSMilanka Ringwald "REJECTED BY REMOTE", 160be32e7f1SMilanka Ringwald "IN_TRANSITION", 161be32e7f1SMilanka Ringwald "IMPLEMENTED_STABLE", 162be32e7f1SMilanka Ringwald "CHANGED_STABLE", 163be32e7f1SMilanka Ringwald "RESERVED", 164be32e7f1SMilanka Ringwald "INTERIM" 165be32e7f1SMilanka Ringwald }; 166be32e7f1SMilanka Ringwald const char * avrcp_ctype2str(uint8_t index){ 1673982eab9SMatthias Ringwald if (index < sizeof(avrcp_ctype_name)){ 168be32e7f1SMilanka Ringwald return avrcp_ctype_name[index]; 169be32e7f1SMilanka Ringwald } 170be32e7f1SMilanka Ringwald return "NONE"; 171be32e7f1SMilanka Ringwald } 172be32e7f1SMilanka Ringwald 173be32e7f1SMilanka Ringwald static const char * avrcp_shuffle_mode_name[] = { 174be32e7f1SMilanka Ringwald "SHUFFLE OFF", 175be32e7f1SMilanka Ringwald "SHUFFLE ALL TRACKS", 176be32e7f1SMilanka Ringwald "SHUFFLE GROUP" 177be32e7f1SMilanka Ringwald }; 178be32e7f1SMilanka Ringwald 179be32e7f1SMilanka Ringwald const char * avrcp_shuffle2str(uint8_t index){ 180be32e7f1SMilanka Ringwald if (index >= 1 && index <= 3) return avrcp_shuffle_mode_name[index-1]; 181be32e7f1SMilanka Ringwald return "NONE"; 182be32e7f1SMilanka Ringwald } 183be32e7f1SMilanka Ringwald 184be32e7f1SMilanka Ringwald static const char * avrcp_repeat_mode_name[] = { 185be32e7f1SMilanka Ringwald "REPEAT OFF", 186be32e7f1SMilanka Ringwald "REPEAT SINGLE TRACK", 187be32e7f1SMilanka Ringwald "REPEAT ALL TRACKS", 188be32e7f1SMilanka Ringwald "REPEAT GROUP" 189be32e7f1SMilanka Ringwald }; 190be32e7f1SMilanka Ringwald 191be32e7f1SMilanka Ringwald const char * avrcp_repeat2str(uint8_t index){ 192be32e7f1SMilanka Ringwald if (index >= 1 && index <= 4) return avrcp_repeat_mode_name[index-1]; 193be32e7f1SMilanka Ringwald return "NONE"; 194be32e7f1SMilanka Ringwald } 1956086246cSMilanka Ringwald 1964b338011SMilanka Ringwald uint8_t avrcp_cmd_opcode(uint8_t *packet, uint16_t size){ 1974b338011SMilanka Ringwald uint8_t cmd_opcode_index = 5; 1984b338011SMilanka Ringwald if (cmd_opcode_index > size) return AVRCP_CMD_OPCODE_UNDEFINED; 1994b338011SMilanka Ringwald return packet[cmd_opcode_index]; 2004b338011SMilanka Ringwald } 2014b338011SMilanka Ringwald 202654724deSMilanka Ringwald void avrcp_create_sdp_record(uint8_t controller, uint8_t * service, uint32_t service_record_handle, uint8_t browsing, uint16_t supported_features, 203654724deSMilanka Ringwald const char * service_name, const char * service_provider_name){ 204be32e7f1SMilanka Ringwald uint8_t* attribute; 205be32e7f1SMilanka Ringwald de_create_sequence(service); 206be32e7f1SMilanka Ringwald 207be32e7f1SMilanka Ringwald // 0x0000 "Service Record Handle" 208235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_RECORD_HANDLE); 209be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_32, service_record_handle); 210be32e7f1SMilanka Ringwald 211be32e7f1SMilanka Ringwald // 0x0001 "Service Class ID List" 212235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST); 213be32e7f1SMilanka Ringwald attribute = de_push_sequence(service); 214be32e7f1SMilanka Ringwald { 215be32e7f1SMilanka Ringwald if (controller){ 2166086246cSMilanka Ringwald de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL); 2176086246cSMilanka Ringwald de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL_CONTROLLER); 218be32e7f1SMilanka Ringwald } else { 2196086246cSMilanka Ringwald de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET); 220be32e7f1SMilanka Ringwald } 221be32e7f1SMilanka Ringwald } 222be32e7f1SMilanka Ringwald de_pop_sequence(service, attribute); 223be32e7f1SMilanka Ringwald 224be32e7f1SMilanka Ringwald // 0x0004 "Protocol Descriptor List" 225235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST); 226be32e7f1SMilanka Ringwald attribute = de_push_sequence(service); 227be32e7f1SMilanka Ringwald { 228be32e7f1SMilanka Ringwald uint8_t* l2cpProtocol = de_push_sequence(attribute); 229be32e7f1SMilanka Ringwald { 230235946f1SMatthias Ringwald de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP); 231235946f1SMatthias Ringwald de_add_number(l2cpProtocol, DE_UINT, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVCTP); 232be32e7f1SMilanka Ringwald } 233be32e7f1SMilanka Ringwald de_pop_sequence(attribute, l2cpProtocol); 234be32e7f1SMilanka Ringwald 235be32e7f1SMilanka Ringwald uint8_t* avctpProtocol = de_push_sequence(attribute); 236be32e7f1SMilanka Ringwald { 237235946f1SMatthias Ringwald de_add_number(avctpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVCTP); // avctpProtocol_service 238be32e7f1SMilanka Ringwald de_add_number(avctpProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version 239be32e7f1SMilanka Ringwald } 240be32e7f1SMilanka Ringwald de_pop_sequence(attribute, avctpProtocol); 241be32e7f1SMilanka Ringwald } 242be32e7f1SMilanka Ringwald de_pop_sequence(service, attribute); 243be32e7f1SMilanka Ringwald 244be32e7f1SMilanka Ringwald // 0x0005 "Public Browse Group" 245235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BROWSE_GROUP_LIST); // public browse group 246be32e7f1SMilanka Ringwald attribute = de_push_sequence(service); 247be32e7f1SMilanka Ringwald { 248235946f1SMatthias Ringwald de_add_number(attribute, DE_UUID, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_PUBLIC_BROWSE_ROOT); 249be32e7f1SMilanka Ringwald } 250be32e7f1SMilanka Ringwald de_pop_sequence(service, attribute); 251be32e7f1SMilanka Ringwald 252be32e7f1SMilanka Ringwald // 0x0009 "Bluetooth Profile Descriptor List" 253235946f1SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST); 254be32e7f1SMilanka Ringwald attribute = de_push_sequence(service); 255be32e7f1SMilanka Ringwald { 256be32e7f1SMilanka Ringwald uint8_t *avrcProfile = de_push_sequence(attribute); 257be32e7f1SMilanka Ringwald { 2586086246cSMilanka Ringwald de_add_number(avrcProfile, DE_UUID, DE_SIZE_16, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL); 259be32e7f1SMilanka Ringwald de_add_number(avrcProfile, DE_UINT, DE_SIZE_16, 0x0105); 260be32e7f1SMilanka Ringwald } 261be32e7f1SMilanka Ringwald de_pop_sequence(attribute, avrcProfile); 262be32e7f1SMilanka Ringwald } 263be32e7f1SMilanka Ringwald de_pop_sequence(service, attribute); 264be32e7f1SMilanka Ringwald 265a0f524f0SMatthias Ringwald // 0x000d "Additional Bluetooth Profile Descriptor List" 2665c806868SMatthias Ringwald if (browsing){ 267a0f524f0SMatthias Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS); 268a0f524f0SMatthias Ringwald attribute = de_push_sequence(service); 2695c806868SMatthias Ringwald { 2705c806868SMatthias Ringwald uint8_t * des = de_push_sequence(attribute); 2715c806868SMatthias Ringwald { 2725c806868SMatthias Ringwald uint8_t* browsing_l2cpProtocol = de_push_sequence(des); 273a0f524f0SMatthias Ringwald { 274a0f524f0SMatthias Ringwald de_add_number(browsing_l2cpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_L2CAP); 275a0f524f0SMatthias Ringwald de_add_number(browsing_l2cpProtocol, DE_UINT, DE_SIZE_16, PSM_AVCTP_BROWSING); 276a0f524f0SMatthias Ringwald } 2775c806868SMatthias Ringwald de_pop_sequence(des, browsing_l2cpProtocol); 278a0f524f0SMatthias Ringwald 2795c806868SMatthias Ringwald uint8_t* browsing_avctpProtocol = de_push_sequence(des); 280a0f524f0SMatthias Ringwald { 281a0f524f0SMatthias Ringwald de_add_number(browsing_avctpProtocol, DE_UUID, DE_SIZE_16, BLUETOOTH_PROTOCOL_AVCTP); // browsing_avctpProtocol_service 282a0f524f0SMatthias Ringwald de_add_number(browsing_avctpProtocol, DE_UINT, DE_SIZE_16, 0x0103); // version 283a0f524f0SMatthias Ringwald } 2845c806868SMatthias Ringwald de_pop_sequence(des, browsing_avctpProtocol); 2855c806868SMatthias Ringwald } 2865c806868SMatthias Ringwald de_pop_sequence(attribute, des); 287a0f524f0SMatthias Ringwald } 288a0f524f0SMatthias Ringwald de_pop_sequence(service, attribute); 2895c806868SMatthias Ringwald } 290a0f524f0SMatthias Ringwald 291be32e7f1SMilanka Ringwald 292be32e7f1SMilanka Ringwald // 0x0100 "Service Name" 293be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); 294be32e7f1SMilanka Ringwald if (service_name){ 295be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(service_name), (uint8_t *) service_name); 296be32e7f1SMilanka Ringwald } else { 297be32e7f1SMilanka Ringwald if (controller){ 298be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(default_avrcp_controller_service_name), (uint8_t *) default_avrcp_controller_service_name); 299be32e7f1SMilanka Ringwald } else { 300be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(default_avrcp_target_service_name), (uint8_t *) default_avrcp_target_service_name); 301be32e7f1SMilanka Ringwald } 302be32e7f1SMilanka Ringwald } 303be32e7f1SMilanka Ringwald 304be32e7f1SMilanka Ringwald // 0x0100 "Provider Name" 305be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, 0x0102); 306be32e7f1SMilanka Ringwald if (service_provider_name){ 307be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(service_provider_name), (uint8_t *) service_provider_name); 308be32e7f1SMilanka Ringwald } else { 309be32e7f1SMilanka Ringwald if (controller){ 310be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(default_avrcp_controller_service_provider_name), (uint8_t *) default_avrcp_controller_service_provider_name); 311be32e7f1SMilanka Ringwald } else { 312be32e7f1SMilanka Ringwald de_add_data(service, DE_STRING, strlen(default_avrcp_target_service_provider_name), (uint8_t *) default_avrcp_target_service_provider_name); 313be32e7f1SMilanka Ringwald } 314be32e7f1SMilanka Ringwald } 315be32e7f1SMilanka Ringwald 316be32e7f1SMilanka Ringwald // 0x0311 "Supported Features" 317be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, 0x0311); 318be32e7f1SMilanka Ringwald de_add_number(service, DE_UINT, DE_SIZE_16, supported_features); 319be32e7f1SMilanka Ringwald } 320be32e7f1SMilanka Ringwald 321247956eaSMilanka Ringwald avrcp_connection_t * get_avrcp_connection_for_bd_addr(bd_addr_t addr, avrcp_context_t * context){ 3226983e65eSMilanka Ringwald btstack_linked_list_iterator_t it; 3236983e65eSMilanka Ringwald btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &context->connections); 3246983e65eSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 3256983e65eSMilanka Ringwald avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it); 3266983e65eSMilanka Ringwald if (memcmp(addr, connection->remote_addr, 6) != 0) continue; 3276983e65eSMilanka Ringwald return connection; 3286983e65eSMilanka Ringwald } 3296983e65eSMilanka Ringwald return NULL; 330be32e7f1SMilanka Ringwald } 331be32e7f1SMilanka Ringwald 3326983e65eSMilanka Ringwald avrcp_connection_t * get_avrcp_connection_for_l2cap_signaling_cid(uint16_t l2cap_cid, avrcp_context_t * context){ 3336983e65eSMilanka Ringwald btstack_linked_list_iterator_t it; 3346983e65eSMilanka Ringwald btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &context->connections); 3356983e65eSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 3366983e65eSMilanka Ringwald avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it); 3376983e65eSMilanka Ringwald if (connection->l2cap_signaling_cid != l2cap_cid) continue; 3386983e65eSMilanka Ringwald return connection; 3396983e65eSMilanka Ringwald } 3406983e65eSMilanka Ringwald return NULL; 341be32e7f1SMilanka Ringwald } 342be32e7f1SMilanka Ringwald 34301dc6e35SMilanka Ringwald avrcp_connection_t * get_avrcp_connection_for_avrcp_cid(uint16_t avrcp_cid, avrcp_context_t * context){ 3446983e65eSMilanka Ringwald btstack_linked_list_iterator_t it; 3456983e65eSMilanka Ringwald btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *) &context->connections); 3466983e65eSMilanka Ringwald while (btstack_linked_list_iterator_has_next(&it)){ 3476983e65eSMilanka Ringwald avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it); 34801dc6e35SMilanka Ringwald if (connection->avrcp_cid != avrcp_cid) continue; 3496983e65eSMilanka Ringwald return connection; 3506983e65eSMilanka Ringwald } 3516983e65eSMilanka Ringwald return NULL; 3526983e65eSMilanka Ringwald } 3536983e65eSMilanka Ringwald 3546983e65eSMilanka Ringwald void avrcp_request_can_send_now(avrcp_connection_t * connection, uint16_t l2cap_cid){ 3556983e65eSMilanka Ringwald connection->wait_to_send = 1; 3566983e65eSMilanka Ringwald l2cap_request_can_send_now_event(l2cap_cid); 3576983e65eSMilanka Ringwald } 3586983e65eSMilanka Ringwald 3596983e65eSMilanka Ringwald 360247956eaSMilanka Ringwald uint16_t avrcp_get_next_cid(void){ 3616983e65eSMilanka Ringwald avrcp_cid_counter++; 3626983e65eSMilanka Ringwald if (avrcp_cid_counter == 0){ 3636983e65eSMilanka Ringwald avrcp_cid_counter = 1; 3646983e65eSMilanka Ringwald } 3656983e65eSMilanka Ringwald return avrcp_cid_counter; 3666983e65eSMilanka Ringwald } 3676983e65eSMilanka Ringwald 3686983e65eSMilanka Ringwald static avrcp_connection_t * avrcp_create_connection(bd_addr_t remote_addr, avrcp_context_t * context){ 3696983e65eSMilanka Ringwald avrcp_connection_t * connection = btstack_memory_avrcp_connection_get(); 3704567cc17SMilanka Ringwald if (!connection){ 3714567cc17SMilanka Ringwald log_error("avrcp: not enough memory to create connection"); 3724567cc17SMilanka Ringwald return NULL; 3734567cc17SMilanka Ringwald } 3746983e65eSMilanka Ringwald memset(connection, 0, sizeof(avrcp_connection_t)); 3756983e65eSMilanka Ringwald connection->state = AVCTP_CONNECTION_IDLE; 3766983e65eSMilanka Ringwald connection->transaction_label = 0xFF; 3778b2b4034SMilanka Ringwald connection->max_num_fragments = 0xFF; 378f12a3722SMilanka Ringwald connection->avrcp_cid = avrcp_get_next_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 412247956eaSMilanka Ringwald 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; 415f12a3722SMilanka Ringwald if (connection->state != AVCTP_CONNECTION_W4_SDP_QUERY_COMPLETE) return; 416247956eaSMilanka Ringwald 4176086246cSMilanka Ringwald UNUSED(packet_type); 4186086246cSMilanka Ringwald UNUSED(channel); 4196086246cSMilanka Ringwald UNUSED(size); 4205448c259SMilanka Ringwald uint8_t status; 4216086246cSMilanka Ringwald des_iterator_t des_list_it; 4226086246cSMilanka Ringwald des_iterator_t prot_it; 4236086246cSMilanka Ringwald // uint32_t avdtp_remote_uuid = 0; 4246086246cSMilanka Ringwald 4256086246cSMilanka Ringwald switch (hci_event_packet_get_type(packet)){ 4266086246cSMilanka Ringwald case SDP_EVENT_QUERY_ATTRIBUTE_VALUE: 4276086246cSMilanka Ringwald // Handle new SDP record 428f12a3722SMilanka Ringwald if (sdp_event_query_attribute_byte_get_record_id(packet) != sdp_query_context->record_id) { 429f12a3722SMilanka Ringwald sdp_query_context->record_id = sdp_event_query_attribute_byte_get_record_id(packet); 430f12a3722SMilanka Ringwald sdp_query_context->parse_sdp_record = 0; 4316086246cSMilanka Ringwald // log_info("SDP Record: Nr: %d", record_id); 4326086246cSMilanka Ringwald } 4336086246cSMilanka Ringwald 4346086246cSMilanka Ringwald if (sdp_event_query_attribute_byte_get_attribute_length(packet) <= attribute_value_buffer_size) { 4356086246cSMilanka Ringwald attribute_value[sdp_event_query_attribute_byte_get_data_offset(packet)] = sdp_event_query_attribute_byte_get_data(packet); 4366086246cSMilanka Ringwald 4376086246cSMilanka Ringwald if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)) { 4386086246cSMilanka Ringwald switch(sdp_event_query_attribute_byte_get_attribute_id(packet)) { 4396086246cSMilanka Ringwald case BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST: 4406086246cSMilanka Ringwald if (de_get_element_type(attribute_value) != DE_DES) break; 4416086246cSMilanka Ringwald for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) { 4426086246cSMilanka Ringwald uint8_t * element = des_iterator_get_element(&des_list_it); 4436086246cSMilanka Ringwald if (de_get_element_type(element) != DE_UUID) continue; 4446086246cSMilanka Ringwald uint32_t uuid = de_get_uuid32(element); 4456086246cSMilanka Ringwald switch (uuid){ 4466086246cSMilanka Ringwald case BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET: 4476983e65eSMilanka Ringwald if (sdp_query_context->role == AVRCP_CONTROLLER) { 448f12a3722SMilanka Ringwald sdp_query_context->parse_sdp_record = 1; 4496086246cSMilanka Ringwald break; 4506086246cSMilanka Ringwald } 4516086246cSMilanka Ringwald break; 4526086246cSMilanka Ringwald case BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL: 453df642728SMilanka Ringwald case BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL_CONTROLLER: 4546983e65eSMilanka Ringwald if (sdp_query_context->role == AVRCP_TARGET) { 455f12a3722SMilanka Ringwald sdp_query_context->parse_sdp_record = 1; 4566086246cSMilanka Ringwald break; 4576086246cSMilanka Ringwald } 4586086246cSMilanka Ringwald break; 4596086246cSMilanka Ringwald default: 4606086246cSMilanka Ringwald break; 4616086246cSMilanka Ringwald } 4626086246cSMilanka Ringwald } 4636086246cSMilanka Ringwald break; 4646086246cSMilanka Ringwald 4656086246cSMilanka Ringwald case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST: { 466f12a3722SMilanka Ringwald if (!sdp_query_context->parse_sdp_record) break; 4676086246cSMilanka Ringwald // log_info("SDP Attribute: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet)); 4686086246cSMilanka Ringwald for (des_iterator_init(&des_list_it, attribute_value); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) { 4696086246cSMilanka Ringwald uint8_t *des_element; 4706086246cSMilanka Ringwald uint8_t *element; 4716086246cSMilanka Ringwald uint32_t uuid; 4726086246cSMilanka Ringwald 4736086246cSMilanka Ringwald if (des_iterator_get_type(&des_list_it) != DE_DES) continue; 4746086246cSMilanka Ringwald 4756086246cSMilanka Ringwald des_element = des_iterator_get_element(&des_list_it); 4766086246cSMilanka Ringwald des_iterator_init(&prot_it, des_element); 4776086246cSMilanka Ringwald element = des_iterator_get_element(&prot_it); 4786086246cSMilanka Ringwald 4796086246cSMilanka Ringwald if (de_get_element_type(element) != DE_UUID) continue; 4806086246cSMilanka Ringwald 4816086246cSMilanka Ringwald uuid = de_get_uuid32(element); 4826086246cSMilanka Ringwald switch (uuid){ 4836086246cSMilanka Ringwald case BLUETOOTH_PROTOCOL_L2CAP: 4846086246cSMilanka Ringwald if (!des_iterator_has_more(&prot_it)) continue; 4856086246cSMilanka Ringwald des_iterator_next(&prot_it); 4866983e65eSMilanka Ringwald de_element_get_uint16(des_iterator_get_element(&prot_it), &sdp_query_context->avrcp_l2cap_psm); 4876086246cSMilanka Ringwald break; 4886086246cSMilanka Ringwald case BLUETOOTH_PROTOCOL_AVCTP: 4896086246cSMilanka Ringwald if (!des_iterator_has_more(&prot_it)) continue; 4906086246cSMilanka Ringwald des_iterator_next(&prot_it); 4916983e65eSMilanka Ringwald de_element_get_uint16(des_iterator_get_element(&prot_it), &sdp_query_context->avrcp_version); 4926086246cSMilanka Ringwald break; 4936086246cSMilanka Ringwald default: 4946086246cSMilanka Ringwald break; 4956086246cSMilanka Ringwald } 4966086246cSMilanka Ringwald } 4976086246cSMilanka Ringwald } 4986086246cSMilanka Ringwald break; 499227d16a5SMatthias Ringwald case BLUETOOTH_ATTRIBUTE_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS: { 500227d16a5SMatthias Ringwald // log_info("SDP Attribute: 0x%04x", sdp_event_query_attribute_byte_get_attribute_id(packet)); 501f12a3722SMilanka Ringwald if (!sdp_query_context->parse_sdp_record) break; 502227d16a5SMatthias Ringwald if (de_get_element_type(attribute_value) != DE_DES) break; 503227d16a5SMatthias Ringwald 504227d16a5SMatthias Ringwald des_iterator_t des_list_0_it; 505227d16a5SMatthias Ringwald uint8_t *element_0; 506227d16a5SMatthias Ringwald 507227d16a5SMatthias Ringwald des_iterator_init(&des_list_0_it, attribute_value); 508227d16a5SMatthias Ringwald element_0 = des_iterator_get_element(&des_list_0_it); 509227d16a5SMatthias Ringwald 510227d16a5SMatthias Ringwald for (des_iterator_init(&des_list_it, element_0); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) { 511227d16a5SMatthias Ringwald uint8_t *des_element; 512227d16a5SMatthias Ringwald uint8_t *element; 513227d16a5SMatthias Ringwald uint32_t uuid; 514227d16a5SMatthias Ringwald 515227d16a5SMatthias Ringwald if (des_iterator_get_type(&des_list_it) != DE_DES) continue; 516227d16a5SMatthias Ringwald 517227d16a5SMatthias Ringwald des_element = des_iterator_get_element(&des_list_it); 518227d16a5SMatthias Ringwald des_iterator_init(&prot_it, des_element); 519227d16a5SMatthias Ringwald element = des_iterator_get_element(&prot_it); 520227d16a5SMatthias Ringwald 521227d16a5SMatthias Ringwald if (de_get_element_type(element) != DE_UUID) continue; 522227d16a5SMatthias Ringwald 523227d16a5SMatthias Ringwald uuid = de_get_uuid32(element); 524227d16a5SMatthias Ringwald switch (uuid){ 525227d16a5SMatthias Ringwald case BLUETOOTH_PROTOCOL_L2CAP: 526227d16a5SMatthias Ringwald if (!des_iterator_has_more(&prot_it)) continue; 527227d16a5SMatthias Ringwald des_iterator_next(&prot_it); 528247956eaSMilanka Ringwald de_element_get_uint16(des_iterator_get_element(&prot_it), &connection->browsing_l2cap_psm); 529227d16a5SMatthias Ringwald break; 530227d16a5SMatthias Ringwald case BLUETOOTH_PROTOCOL_AVCTP: 531227d16a5SMatthias Ringwald if (!des_iterator_has_more(&prot_it)) continue; 532227d16a5SMatthias Ringwald des_iterator_next(&prot_it); 533247956eaSMilanka Ringwald de_element_get_uint16(des_iterator_get_element(&prot_it), &connection->browsing_version); 534227d16a5SMatthias Ringwald break; 535227d16a5SMatthias Ringwald default: 536227d16a5SMatthias Ringwald break; 537227d16a5SMatthias Ringwald } 538227d16a5SMatthias Ringwald } 539227d16a5SMatthias Ringwald } 540227d16a5SMatthias Ringwald break; 5416086246cSMilanka Ringwald default: 5426086246cSMilanka Ringwald break; 5436086246cSMilanka Ringwald } 5446086246cSMilanka Ringwald } 5456086246cSMilanka Ringwald } else { 5466086246cSMilanka 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)); 5476086246cSMilanka Ringwald } 5486086246cSMilanka Ringwald break; 5496086246cSMilanka Ringwald 550247956eaSMilanka Ringwald case SDP_EVENT_QUERY_COMPLETE:{ 5515448c259SMilanka Ringwald status = sdp_event_query_complete_get_status(packet); 552247956eaSMilanka Ringwald 5535448c259SMilanka Ringwald if (status != ERROR_CODE_SUCCESS){ 5545448c259SMilanka Ringwald avrcp_emit_connection_established(sdp_query_context->avrcp_callback, connection->avrcp_cid, connection->remote_addr, status); 5555448c259SMilanka Ringwald btstack_linked_list_remove(&sdp_query_context->connections, (btstack_linked_item_t*) connection); 5565448c259SMilanka Ringwald btstack_memory_avrcp_connection_free(connection); 5575448c259SMilanka Ringwald log_info("AVRCP: SDP query failed with status 0x%02x.", status); 5585448c259SMilanka Ringwald break; 5595448c259SMilanka Ringwald } 5605448c259SMilanka Ringwald 561247956eaSMilanka Ringwald if (!sdp_query_context->parse_sdp_record){ 562be32e7f1SMilanka Ringwald connection->state = AVCTP_CONNECTION_IDLE; 5636983e65eSMilanka Ringwald avrcp_emit_connection_established(sdp_query_context->avrcp_callback, connection->avrcp_cid, connection->remote_addr, SDP_SERVICE_NOT_FOUND); 5645448c259SMilanka Ringwald btstack_linked_list_remove(&sdp_query_context->connections, (btstack_linked_item_t*) connection); 5655448c259SMilanka Ringwald btstack_memory_avrcp_connection_free(connection); 5666983e65eSMilanka Ringwald break; 5676983e65eSMilanka Ringwald } 568247956eaSMilanka Ringwald // log_info("AVRCP Control PSM 0x%02x, Browsing PSM 0x%02x", sdp_query_context->avrcp_l2cap_psm, sdp_query_context->browsing_l2cap_psm); 5696983e65eSMilanka Ringwald connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED; 5706983e65eSMilanka Ringwald l2cap_create_channel(sdp_query_context->packet_handler, connection->remote_addr, sdp_query_context->avrcp_l2cap_psm, l2cap_max_mtu(), NULL); 5716983e65eSMilanka Ringwald break; 5726983e65eSMilanka Ringwald } 573be32e7f1SMilanka Ringwald } 574247956eaSMilanka Ringwald } 575be32e7f1SMilanka Ringwald 5766983e65eSMilanka Ringwald void avrcp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context){ 5776983e65eSMilanka Ringwald UNUSED(channel); 5786983e65eSMilanka Ringwald UNUSED(size); 579be32e7f1SMilanka Ringwald bd_addr_t event_addr; 580be32e7f1SMilanka Ringwald uint16_t local_cid; 581b0d75c91SMilanka Ringwald uint8_t status; 582be32e7f1SMilanka Ringwald avrcp_connection_t * connection = NULL; 583654724deSMilanka Ringwald uint16_t psm; 584be32e7f1SMilanka Ringwald 5856983e65eSMilanka Ringwald if (packet_type != HCI_EVENT_PACKET) return; 586be32e7f1SMilanka Ringwald 587be32e7f1SMilanka Ringwald switch (hci_event_packet_get_type(packet)) { 58834b22aacSMilanka Ringwald case HCI_EVENT_DISCONNECTION_COMPLETE: 5896983e65eSMilanka Ringwald avrcp_emit_connection_closed(context->avrcp_callback, 0); 59034b22aacSMilanka Ringwald break; 591be32e7f1SMilanka Ringwald case L2CAP_EVENT_INCOMING_CONNECTION: 592be32e7f1SMilanka Ringwald l2cap_event_incoming_connection_get_address(packet, event_addr); 593be32e7f1SMilanka Ringwald local_cid = l2cap_event_incoming_connection_get_local_cid(packet); 5946086246cSMilanka Ringwald connection = avrcp_create_connection(event_addr, context); 5950f76c2d7SMatthias Ringwald if (!connection) { 5960f76c2d7SMatthias Ringwald log_error("Failed to alloc connection structure"); 5970f76c2d7SMatthias Ringwald l2cap_decline_connection(local_cid); 598be32e7f1SMilanka Ringwald break; 599be32e7f1SMilanka Ringwald } 600654724deSMilanka Ringwald 601654724deSMilanka Ringwald psm = l2cap_event_incoming_connection_get_psm(packet); 602654724deSMilanka Ringwald if (psm == PSM_AVCTP){ 603654724deSMilanka Ringwald if (!connection->l2cap_signaling_cid){ 6040f76c2d7SMatthias Ringwald connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED; 6050f76c2d7SMatthias Ringwald connection->l2cap_signaling_cid = local_cid; 606b0d75c91SMilanka Ringwald log_info("L2CAP_EVENT_INCOMING_CONNECTION avrcp_cid 0x%02x, l2cap_signaling_cid 0x%02x", connection->avrcp_cid, connection->l2cap_signaling_cid); 6070f76c2d7SMatthias Ringwald l2cap_accept_connection(local_cid); 608be32e7f1SMilanka Ringwald break; 609654724deSMilanka Ringwald } 610654724deSMilanka Ringwald } 611654724deSMilanka Ringwald log_info("L2CAP_EVENT_INCOMING_CONNECTION local_cid 0x%02x, psm 0x%2x, decline connection", local_cid, psm); 612654724deSMilanka Ringwald l2cap_decline_connection(local_cid); 613654724deSMilanka Ringwald break; 614be32e7f1SMilanka Ringwald 615be32e7f1SMilanka Ringwald case L2CAP_EVENT_CHANNEL_OPENED: 616be32e7f1SMilanka Ringwald l2cap_event_channel_opened_get_address(packet, event_addr); 617b0d75c91SMilanka Ringwald status = l2cap_event_channel_opened_get_status(packet); 6180f76c2d7SMatthias Ringwald local_cid = l2cap_event_channel_opened_get_local_cid(packet); 6190f76c2d7SMatthias Ringwald 620b0d75c91SMilanka Ringwald connection = get_avrcp_connection_for_bd_addr(event_addr, context); 6216086246cSMilanka Ringwald if (!connection){ 622b0d75c91SMilanka Ringwald log_error("Failed to alloc AVRCP connection structure"); 6236983e65eSMilanka Ringwald avrcp_emit_connection_established(context->avrcp_callback, connection->avrcp_cid, event_addr, BTSTACK_MEMORY_ALLOC_FAILED); 6240f76c2d7SMatthias Ringwald l2cap_disconnect(local_cid, 0); // reason isn't used 625b193c45eSMilanka Ringwald break; 626b193c45eSMilanka Ringwald } 627b0d75c91SMilanka Ringwald if (status != ERROR_CODE_SUCCESS){ 628b0d75c91SMilanka Ringwald log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status); 6296983e65eSMilanka Ringwald avrcp_emit_connection_established(context->avrcp_callback, connection->avrcp_cid, event_addr, status); 6306086246cSMilanka Ringwald btstack_linked_list_remove(&context->connections, (btstack_linked_item_t*) connection); 6316086246cSMilanka Ringwald btstack_memory_avrcp_connection_free(connection); 6326086246cSMilanka Ringwald break; 6336086246cSMilanka Ringwald } 634654724deSMilanka Ringwald 635654724deSMilanka Ringwald psm = l2cap_event_channel_opened_get_psm(packet); 636654724deSMilanka Ringwald if (psm == PSM_AVCTP){ 637be32e7f1SMilanka Ringwald connection->l2cap_signaling_cid = local_cid; 638*86c0eebdSMatthias Ringwald connection->l2cap_mtu = l2cap_event_channel_opened_get_remote_mtu(packet); 639d1207cd8SMilanka Ringwald connection->song_length_ms = 0xFFFFFFFF; 640d1207cd8SMilanka Ringwald connection->song_position_ms = 0xFFFFFFFF; 641d1207cd8SMilanka Ringwald connection->playback_status = AVRCP_PLAYBACK_STATUS_ERROR; 642d1207cd8SMilanka Ringwald 6436086246cSMilanka Ringwald log_info("L2CAP_EVENT_CHANNEL_OPENED avrcp_cid 0x%02x, l2cap_signaling_cid 0x%02x", connection->avrcp_cid, connection->l2cap_signaling_cid); 644be32e7f1SMilanka Ringwald connection->state = AVCTP_CONNECTION_OPENED; 6456983e65eSMilanka Ringwald avrcp_emit_connection_established(context->avrcp_callback, connection->avrcp_cid, event_addr, ERROR_CODE_SUCCESS); 646654724deSMilanka Ringwald } 647be32e7f1SMilanka Ringwald break; 648be32e7f1SMilanka Ringwald 649be32e7f1SMilanka Ringwald case L2CAP_EVENT_CHANNEL_CLOSED: 650be32e7f1SMilanka Ringwald // data: event (8), len(8), channel (16) 651be32e7f1SMilanka Ringwald local_cid = l2cap_event_channel_closed_get_local_cid(packet); 6526086246cSMilanka Ringwald connection = get_avrcp_connection_for_l2cap_signaling_cid(local_cid, context); 653be32e7f1SMilanka Ringwald if (connection){ 6546983e65eSMilanka Ringwald avrcp_emit_connection_closed(context->avrcp_callback, connection->avrcp_cid); 6556f43fcd7SMatthias Ringwald // free connection 6566086246cSMilanka Ringwald btstack_linked_list_remove(&context->connections, (btstack_linked_item_t*) connection); 6576f43fcd7SMatthias Ringwald btstack_memory_avrcp_connection_free(connection); 658be32e7f1SMilanka Ringwald break; 659be32e7f1SMilanka Ringwald } 660be32e7f1SMilanka Ringwald break; 661be32e7f1SMilanka Ringwald default: 662be32e7f1SMilanka Ringwald break; 663be32e7f1SMilanka Ringwald } 664be32e7f1SMilanka Ringwald } 665be32e7f1SMilanka Ringwald 6666086246cSMilanka Ringwald uint8_t avrcp_connect(bd_addr_t bd_addr, avrcp_context_t * context, uint16_t * avrcp_cid){ 6676086246cSMilanka Ringwald avrcp_connection_t * connection = get_avrcp_connection_for_bd_addr(bd_addr, context); 6688a2c6c7cSMilanka Ringwald if (connection){ 6698a2c6c7cSMilanka Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 6708a2c6c7cSMilanka Ringwald } 6716086246cSMilanka Ringwald connection = avrcp_create_connection(bd_addr, context); 672be32e7f1SMilanka Ringwald if (!connection){ 6738a2c6c7cSMilanka Ringwald log_error("avrcp: could not allocate connection struct."); 6748a2c6c7cSMilanka Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 675be32e7f1SMilanka Ringwald } 6768a2c6c7cSMilanka Ringwald 6776086246cSMilanka Ringwald if (!avrcp_cid) return L2CAP_LOCAL_CID_DOES_NOT_EXIST; 6786086246cSMilanka Ringwald 679b0d75c91SMilanka Ringwald *avrcp_cid = connection->avrcp_cid; 680f12a3722SMilanka Ringwald connection->state = AVCTP_CONNECTION_W4_SDP_QUERY_COMPLETE; 6816983e65eSMilanka Ringwald 6826983e65eSMilanka Ringwald context->avrcp_l2cap_psm = 0; 6836983e65eSMilanka Ringwald context->avrcp_version = 0; 6846983e65eSMilanka Ringwald context->avrcp_cid = connection->avrcp_cid; 685247956eaSMilanka Ringwald connection->browsing_l2cap_psm = 0; 6866983e65eSMilanka Ringwald sdp_query_context = context; 6875448c259SMilanka Ringwald return sdp_client_query_uuid16(&avrcp_handle_sdp_client_query_result, bd_addr, BLUETOOTH_PROTOCOL_AVCTP); 688be32e7f1SMilanka Ringwald } 689