xref: /btstack/src/classic/avrcp_browsing_target.c (revision 8ed86b4658ce4bbfe613e16cdfa2dcf97b4457fe)
1 /*
2  * Copyright (C) 2016 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define __BTSTACK_FILE__ "avrcp_browsing_target.c"
39 
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <inttypes.h>
45 #include "btstack.h"
46 #include "classic/avrcp.h"
47 #include "classic/avrcp_browsing_target.h"
48 
49 #define PSM_AVCTP_BROWSING              0x001b
50 
51 static void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context);
52 static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
53 
54 static void avrcp_browsing_target_request_can_send_now(avrcp_browsing_connection_t * connection, uint16_t l2cap_cid){
55     connection->wait_to_send = 1;
56     l2cap_request_can_send_now_event(l2cap_cid);
57 }
58 
59 static int avrcp_browsing_target_handle_can_send_now(avrcp_browsing_connection_t * connection){
60     int pos = 0;
61     // l2cap_reserve_packet_buffer();
62     // uint8_t * packet = l2cap_get_outgoing_buffer();
63     uint8_t packet[100];
64     connection->packet_type = AVRCP_SINGLE_PACKET;
65 
66     packet[pos++] = (connection->transaction_label << 4) | (connection->packet_type << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
67     // Profile IDentifier (PID)
68     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
69     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
70     memcpy(packet+pos, connection->cmd_operands, connection->cmd_operands_length);
71     // printf_hexdump(packet+pos, connection->cmd_operands_length);
72 
73     pos += connection->cmd_operands_length;
74     connection->wait_to_send = 0;
75     // return l2cap_send_prepared(connection->l2cap_browsing_cid, pos);
76     return l2cap_send(connection->l2cap_browsing_cid, packet, pos);
77 }
78 
79 
80 static uint8_t avrcp_browsing_target_response_general_reject(avrcp_browsing_connection_t * connection, avrcp_status_code_t status){
81     // AVRCP_CTYPE_RESPONSE_REJECTED
82     int pos = 0;
83     connection->cmd_operands[pos++] = AVRCP_PDU_ID_GENERAL_REJECT;
84     // connection->cmd_operands[pos++] = 0;
85     // param length
86     big_endian_store_16(connection->cmd_operands, pos, 1);
87     pos += 2;
88     connection->cmd_operands[pos++] = status;
89     connection->cmd_operands_length = 4;
90     connection->state = AVCTP_W2_SEND_RESPONSE;
91     avrcp_browsing_target_request_can_send_now(connection, connection->l2cap_browsing_cid);
92     return ERROR_CODE_SUCCESS;
93 }
94 
95 static avrcp_connection_t * get_avrcp_connection_for_browsing_cid(uint16_t browsing_cid, avrcp_context_t * context){
96     btstack_linked_list_iterator_t it;
97     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
98     while (btstack_linked_list_iterator_has_next(&it)){
99         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
100         if (connection->avrcp_browsing_cid != browsing_cid) continue;
101         return connection;
102     }
103     return NULL;
104 }
105 
106 static avrcp_connection_t * get_avrcp_connection_for_browsing_l2cap_cid(uint16_t browsing_l2cap_cid, avrcp_context_t * context){
107     btstack_linked_list_iterator_t it;
108     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
109     while (btstack_linked_list_iterator_has_next(&it)){
110         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
111         if (connection->browsing_connection &&  connection->browsing_connection->l2cap_browsing_cid != browsing_l2cap_cid) continue;
112         return connection;
113     }
114     return NULL;
115 }
116 
117 static avrcp_browsing_connection_t * get_avrcp_browsing_connection_for_l2cap_cid(uint16_t l2cap_cid, avrcp_context_t * context){
118     btstack_linked_list_iterator_t it;
119     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
120     while (btstack_linked_list_iterator_has_next(&it)){
121         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
122         if (connection->browsing_connection && connection->browsing_connection->l2cap_browsing_cid != l2cap_cid) continue;
123         return connection->browsing_connection;
124     }
125     return NULL;
126 }
127 
128 static void avrcp_browsing_target_emit_get_folder_items(btstack_packet_handler_t callback, uint16_t browsing_cid, avrcp_browsing_connection_t * connection){
129     if (!callback) return;
130     uint8_t event[10];
131     int pos = 0;
132     event[pos++] = HCI_EVENT_AVRCP_META;
133     event[pos++] = sizeof(event) - 2;
134     event[pos++] = AVRCP_SUBEVENT_BROWSING_GET_FOLDER_ITEMS;
135     little_endian_store_16(event, pos, browsing_cid);
136     pos += 2;
137     event[pos++] = connection->scope;
138     big_endian_store_32(event, pos, connection->attr_bitmap);
139     pos += 4;
140     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
141 }
142 
143 static void avrcp_emit_browsing_connection_established(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr, uint8_t status){
144     if (!callback) return;
145     uint8_t event[12];
146     int pos = 0;
147     event[pos++] = HCI_EVENT_AVRCP_META;
148     event[pos++] = sizeof(event) - 2;
149     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_ESTABLISHED;
150     event[pos++] = status;
151     reverse_bd_addr(addr,&event[pos]);
152     pos += 6;
153     little_endian_store_16(event, pos, browsing_cid);
154     pos += 2;
155     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
156 }
157 
158 static void avrcp_emit_incoming_browsing_connection(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr){
159     if (!callback) return;
160     uint8_t event[11];
161     int pos = 0;
162     event[pos++] = HCI_EVENT_AVRCP_META;
163     event[pos++] = sizeof(event) - 2;
164     event[pos++] = AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION;
165     reverse_bd_addr(addr,&event[pos]);
166     pos += 6;
167     little_endian_store_16(event, pos, browsing_cid);
168     pos += 2;
169     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
170 }
171 
172 static void avrcp_emit_browsing_connection_closed(btstack_packet_handler_t callback, uint16_t browsing_cid){
173     if (!callback) return;
174     uint8_t event[5];
175     int pos = 0;
176     event[pos++] = HCI_EVENT_AVRCP_META;
177     event[pos++] = sizeof(event) - 2;
178     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_RELEASED;
179     little_endian_store_16(event, pos, browsing_cid);
180     pos += 2;
181     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
182 }
183 
184 static avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection){
185     avrcp_browsing_connection_t * connection = btstack_memory_avrcp_browsing_connection_get();
186     memset(connection, 0, sizeof(avrcp_browsing_connection_t));
187     connection->state = AVCTP_CONNECTION_IDLE;
188     connection->transaction_label = 0xFF;
189     avrcp_connection->avrcp_browsing_cid = avrcp_get_next_cid();
190     avrcp_connection->browsing_connection = connection;
191     return connection;
192 }
193 
194 static uint8_t avrcp_browsing_connect(bd_addr_t remote_addr, avrcp_context_t * context, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config, uint16_t * browsing_cid){
195     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_bd_addr(remote_addr, context);
196 
197     if (!avrcp_connection){
198         log_error("avrcp: there is no previously established AVRCP controller connection.");
199         return ERROR_CODE_COMMAND_DISALLOWED;
200     }
201 
202     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
203     if (connection){
204         log_error(" avrcp_browsing_connect connection exists.");
205         return ERROR_CODE_SUCCESS;
206     }
207 
208     connection = avrcp_browsing_create_connection(avrcp_connection);
209     if (!connection){
210         log_error("avrcp: could not allocate connection struct.");
211         return BTSTACK_MEMORY_ALLOC_FAILED;
212     }
213 
214     if (!browsing_cid) return L2CAP_LOCAL_CID_DOES_NOT_EXIST;
215 
216     *browsing_cid = avrcp_connection->avrcp_browsing_cid;
217     connection->ertm_buffer = ertm_buffer;
218     connection->ertm_buffer_size = size;
219     avrcp_connection->browsing_connection = connection;
220 
221     memcpy(&connection->ertm_config, ertm_config, sizeof(l2cap_ertm_config_t));
222 
223     return l2cap_create_ertm_channel(avrcp_browsing_target_packet_handler, remote_addr, avrcp_connection->browsing_l2cap_psm,
224                     &connection->ertm_config, connection->ertm_buffer, connection->ertm_buffer_size, NULL);
225 
226 }
227 
228 static void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context){
229     UNUSED(channel);
230     UNUSED(size);
231     bd_addr_t event_addr;
232     uint16_t local_cid;
233     uint8_t  status;
234     avrcp_browsing_connection_t * browsing_connection = NULL;
235     avrcp_connection_t * avrcp_connection = NULL;
236 
237     if (packet_type != HCI_EVENT_PACKET) return;
238 
239     switch (hci_event_packet_get_type(packet)) {
240         case HCI_EVENT_DISCONNECTION_COMPLETE:
241             avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, 0);
242             break;
243         case L2CAP_EVENT_INCOMING_CONNECTION:
244             l2cap_event_incoming_connection_get_address(packet, event_addr);
245             local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
246             avrcp_connection = get_avrcp_connection_for_bd_addr(event_addr, context);
247             if (!avrcp_connection) {
248                 log_error("No previously created AVRCP controller connections");
249                 l2cap_decline_connection(local_cid);
250                 break;
251             }
252             browsing_connection = avrcp_browsing_create_connection(avrcp_connection);
253             browsing_connection->l2cap_browsing_cid = local_cid;
254             browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION;
255             log_info("Emit AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION browsing_cid 0x%02x, l2cap_signaling_cid 0x%02x\n", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid);
256             avrcp_emit_incoming_browsing_connection(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr);
257             break;
258 
259         case L2CAP_EVENT_CHANNEL_OPENED:
260             l2cap_event_channel_opened_get_address(packet, event_addr);
261             status = l2cap_event_channel_opened_get_status(packet);
262             local_cid = l2cap_event_channel_opened_get_local_cid(packet);
263 
264             avrcp_connection = get_avrcp_connection_for_bd_addr(event_addr, context);
265             if (!avrcp_connection){
266                 log_error("Failed to find AVRCP connection for bd_addr %s", bd_addr_to_str(event_addr));
267                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, local_cid, event_addr, L2CAP_LOCAL_CID_DOES_NOT_EXIST);
268                 l2cap_disconnect(local_cid, 0); // reason isn't used
269                 break;
270             }
271 
272             browsing_connection = avrcp_connection->browsing_connection;
273             if (status != ERROR_CODE_SUCCESS){
274                 log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status);
275                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, status);
276                 btstack_memory_avrcp_browsing_connection_free(browsing_connection);
277                 avrcp_connection->browsing_connection = NULL;
278                 break;
279             }
280             if (browsing_connection->state != AVCTP_CONNECTION_W4_L2CAP_CONNECTED) break;
281 
282             browsing_connection->l2cap_browsing_cid = local_cid;
283 
284             log_info("L2CAP_EVENT_CHANNEL_OPENED browsing cid 0x%02x, l2cap cid 0x%02x", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid);
285             browsing_connection->state = AVCTP_CONNECTION_OPENED;
286             avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, ERROR_CODE_SUCCESS);
287             break;
288 
289         case L2CAP_EVENT_CHANNEL_CLOSED:
290             // data: event (8), len(8), channel (16)
291             local_cid = l2cap_event_channel_closed_get_local_cid(packet);
292             avrcp_connection = get_avrcp_connection_for_browsing_l2cap_cid(local_cid, context);
293 
294             if (avrcp_connection && avrcp_connection->browsing_connection){
295                 avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid);
296                 // free connection
297                 btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
298                 avrcp_connection->browsing_connection = NULL;
299                 break;
300             }
301             break;
302         default:
303             break;
304     }
305 }
306 
307 
308 static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
309     avrcp_browsing_connection_t * browsing_connection;
310 
311     switch (packet_type) {
312         case L2CAP_DATA_PACKET:{
313             browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_target_context);
314             if (!browsing_connection) break;
315             printf_hexdump(packet,size);
316 
317             int pos = 0;
318             uint8_t transport_header = packet[pos++];
319             // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
320             browsing_connection->transaction_label = transport_header >> 4;
321             avrcp_packet_type_t avctp_packet_type = (transport_header & 0x0F) >> 2;
322             printf("L2CAP_DATA_PACKET, transaction_label %d\n", browsing_connection->transaction_label);
323             switch (avctp_packet_type){
324                 case AVRCP_SINGLE_PACKET:
325                 case AVRCP_START_PACKET:
326                     // uint8_t frame_type = (transport_header & 0x03) >> 1;
327                     // uint8_t ipid = transport_header & 0x01;
328                     browsing_connection->subunit_type = packet[pos++] >> 2;
329                     browsing_connection->subunit_id = 0;
330                     browsing_connection->command_opcode = packet[pos++];
331                     // printf("subunit_id")
332                     // pos += 2;
333                     browsing_connection->num_packets = 1;
334                     if (avctp_packet_type == AVRCP_START_PACKET){
335                         browsing_connection->num_packets = packet[pos++];
336                     }
337                     browsing_connection->pdu_id = packet[pos++];
338                     // uint16_t length = big_endian_read_16(packet, pos);
339                     // pos += 2;
340                     break;
341                 default:
342                     break;
343             }
344             printf("pdu id 0x%2x\n", browsing_connection->pdu_id);
345             // uint32_t i;
346             switch(browsing_connection->pdu_id){
347                 case AVRCP_PDU_ID_GET_FOLDER_ITEMS:
348                     printf("\n");
349                     browsing_connection->scope = packet[pos++];
350                     browsing_connection->start_item = big_endian_read_32(packet, pos);
351                     pos += 4;
352                     browsing_connection->end_item = big_endian_read_32(packet, pos);
353                     pos += 4;
354                     uint8_t attr_count = packet[pos++];
355 
356                     while (attr_count){
357                         uint32_t attr_id = big_endian_read_32(packet, pos);
358                         pos += 4;
359                         browsing_connection->attr_bitmap |= (1 << attr_id);
360                         attr_count--;
361                     }
362                     avrcp_browsing_target_emit_get_folder_items(avrcp_target_context.browsing_avrcp_callback, channel, browsing_connection);
363 
364                     break;
365                 default:
366                     printf(" not parsed pdu ID 0x%02x\n", browsing_connection->pdu_id);
367                     break;
368             }
369 
370             switch (avctp_packet_type){
371                 case AVRCP_SINGLE_PACKET:
372                 case AVRCP_END_PACKET:
373                     printf("send avrcp_browsing_target_response_general_reject\n");
374                     browsing_connection->state = AVCTP_CONNECTION_OPENED;
375                     avrcp_browsing_target_response_general_reject(browsing_connection, AVRCP_STATUS_INVALID_COMMAND);
376                     // avrcp_browsing_target_emit_done_with_uid_counter(avrcp_target_context.browsing_avrcp_callback, channel, browsing_connection->uid_counter, browsing_connection->browsing_status, ERROR_CODE_SUCCESS);
377                     break;
378                 default:
379                     break;
380             }
381             // printf(" paket done\n");
382             break;
383         }
384 
385         case HCI_EVENT_PACKET:
386             switch (hci_event_packet_get_type(packet)){
387                 case L2CAP_EVENT_CAN_SEND_NOW:
388                     browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_target_context);
389                     if (!browsing_connection) break;
390                     if (browsing_connection->state != AVCTP_W2_SEND_RESPONSE) return;
391                     browsing_connection->state = AVCTP_CONNECTION_OPENED;
392                     avrcp_browsing_target_handle_can_send_now(browsing_connection);
393                     break;
394                 default:
395                     avrcp_browser_packet_handler(packet_type, channel, packet, size, &avrcp_target_context);
396                     break;
397             }
398             break;
399 
400         default:
401             break;
402     }
403 }
404 
405 void avrcp_browsing_target_init(void){
406     avrcp_target_context.browsing_packet_handler = avrcp_browsing_target_packet_handler;
407     l2cap_register_service(&avrcp_browsing_target_packet_handler, PSM_AVCTP_BROWSING, 0xffff, LEVEL_0);
408 }
409 
410 void avrcp_browsing_target_register_packet_handler(btstack_packet_handler_t callback){
411     if (callback == NULL){
412         log_error("avrcp_browsing_target_register_packet_handler called with NULL callback");
413         return;
414     }
415     avrcp_target_context.browsing_avrcp_callback = callback;
416 }
417 
418 uint8_t avrcp_browsing_target_connect(bd_addr_t bd_addr, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid){
419     return avrcp_browsing_connect(bd_addr, &avrcp_target_context, ertm_buffer, size, ertm_config, avrcp_browsing_cid);
420 }
421 
422 uint8_t avrcp_browsing_target_disconnect(uint16_t avrcp_browsing_cid){
423     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_target_context);
424     if (!avrcp_connection){
425         log_error("avrcp_browsing_target_disconnect: could not find a connection.");
426         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
427     }
428     if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
429 
430     l2cap_disconnect(avrcp_connection->browsing_connection->l2cap_browsing_cid, 0);
431     return ERROR_CODE_SUCCESS;
432 }
433 
434 uint8_t avrcp_browsing_target_configure_incoming_connection(uint16_t avrcp_browsing_cid, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config){
435     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_target_context);
436     if (!avrcp_connection){
437         log_error("avrcp_browsing_decline_incoming_connection: could not find a connection.");
438         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
439     }
440     if (!avrcp_connection->browsing_connection){
441         log_error("avrcp_browsing_decline_incoming_connection: no browsing connection.");
442         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
443     }
444 
445     if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_W4_ERTM_CONFIGURATION){
446         log_error("avrcp_browsing_decline_incoming_connection: browsing connection in a wrong state.");
447         return ERROR_CODE_COMMAND_DISALLOWED;
448     }
449 
450     avrcp_connection->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
451     avrcp_connection->browsing_connection->ertm_buffer = ertm_buffer;
452     avrcp_connection->browsing_connection->ertm_buffer_size = size;
453     memcpy(&avrcp_connection->browsing_connection->ertm_config, ertm_config, sizeof(l2cap_ertm_config_t));
454     l2cap_accept_ertm_connection(avrcp_connection->browsing_connection->l2cap_browsing_cid, &avrcp_connection->browsing_connection->ertm_config, avrcp_connection->browsing_connection->ertm_buffer, avrcp_connection->browsing_connection->ertm_buffer_size);
455     return ERROR_CODE_SUCCESS;
456 }
457 
458 uint8_t avrcp_browsing_target_decline_incoming_connection(uint16_t avrcp_browsing_cid){
459     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_target_context);
460     if (!avrcp_connection){
461         log_error("avrcp_browsing_decline_incoming_connection: could not find a connection.");
462         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
463     }
464     if (!avrcp_connection->browsing_connection) return ERROR_CODE_SUCCESS;
465     if (avrcp_connection->browsing_connection->state > AVCTP_CONNECTION_W4_ERTM_CONFIGURATION) return ERROR_CODE_COMMAND_DISALLOWED;
466 
467     l2cap_decline_connection(avrcp_connection->browsing_connection->l2cap_browsing_cid);
468     // free connection
469     btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
470     avrcp_connection->browsing_connection = NULL;
471     return ERROR_CODE_SUCCESS;
472 }
473