xref: /btstack/src/classic/avrcp_browsing_target.c (revision 881a49d59a07b24d6e642b29c1b67e7e92358514)
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     // printf("avrcp_browsing_target_handle_can_send_now, cmd_operands_length %d\n", connection->cmd_operands_length);
62     // printf_hexdump(connection->cmd_operands, connection->cmd_operands_length);
63 
64     // l2cap_reserve_packet_buffer();
65     // uint8_t * packet = l2cap_get_outgoing_buffer();
66     uint8_t packet[300];
67     connection->packet_type = AVRCP_SINGLE_PACKET;
68 
69     packet[pos++] = (connection->transaction_label << 4) | (connection->packet_type << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0;
70     // Profile IDentifier (PID)
71     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
72     packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
73     memcpy(packet+pos, connection->cmd_operands, connection->cmd_operands_length);
74 
75     pos += connection->cmd_operands_length;
76     connection->wait_to_send = 0;
77     // return l2cap_send_prepared(connection->l2cap_browsing_cid, pos);
78     return l2cap_send(connection->l2cap_browsing_cid, packet, pos);
79 }
80 
81 
82 static uint8_t avrcp_browsing_target_response_general_reject(avrcp_browsing_connection_t * connection, avrcp_status_code_t status){
83     // AVRCP_CTYPE_RESPONSE_REJECTED
84     int pos = 0;
85     connection->cmd_operands[pos++] = AVRCP_PDU_ID_GENERAL_REJECT;
86     // connection->cmd_operands[pos++] = 0;
87     // param length
88     big_endian_store_16(connection->cmd_operands, pos, 1);
89     pos += 2;
90     connection->cmd_operands[pos++] = status;
91     connection->cmd_operands_length = 4;
92     connection->state = AVCTP_W2_SEND_RESPONSE;
93     avrcp_browsing_target_request_can_send_now(connection, connection->l2cap_browsing_cid);
94     return ERROR_CODE_SUCCESS;
95 }
96 
97 static avrcp_connection_t * get_avrcp_connection_for_browsing_cid(uint16_t browsing_cid, avrcp_context_t * context){
98     btstack_linked_list_iterator_t it;
99     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
100     while (btstack_linked_list_iterator_has_next(&it)){
101         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
102         if (connection->avrcp_browsing_cid != browsing_cid) continue;
103         return connection;
104     }
105     return NULL;
106 }
107 
108 static avrcp_connection_t * get_avrcp_connection_for_browsing_l2cap_cid(uint16_t browsing_l2cap_cid, avrcp_context_t * context){
109     btstack_linked_list_iterator_t it;
110     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
111     while (btstack_linked_list_iterator_has_next(&it)){
112         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
113         if (connection->browsing_connection &&  connection->browsing_connection->l2cap_browsing_cid != browsing_l2cap_cid) continue;
114         return connection;
115     }
116     return NULL;
117 }
118 
119 static avrcp_browsing_connection_t * get_avrcp_browsing_connection_for_l2cap_cid(uint16_t l2cap_cid, avrcp_context_t * context){
120     btstack_linked_list_iterator_t it;
121     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
122     while (btstack_linked_list_iterator_has_next(&it)){
123         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
124         if (connection->browsing_connection && connection->browsing_connection->l2cap_browsing_cid != l2cap_cid) continue;
125         return connection->browsing_connection;
126     }
127     return NULL;
128 }
129 
130 static void avrcp_browsing_target_emit_get_folder_items(btstack_packet_handler_t callback, uint16_t browsing_cid, avrcp_browsing_connection_t * connection){
131     if (!callback) return;
132     uint8_t event[10];
133     int pos = 0;
134     event[pos++] = HCI_EVENT_AVRCP_META;
135     event[pos++] = sizeof(event) - 2;
136     event[pos++] = AVRCP_SUBEVENT_BROWSING_GET_FOLDER_ITEMS;
137     little_endian_store_16(event, pos, browsing_cid);
138     pos += 2;
139     event[pos++] = connection->scope;
140     big_endian_store_32(event, pos, connection->attr_bitmap);
141     pos += 4;
142     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
143 }
144 
145 static void avrcp_browsing_target_emit_get_total_num_items(btstack_packet_handler_t callback, uint16_t browsing_cid, avrcp_browsing_connection_t * connection){
146     if (!callback) return;
147     uint8_t event[10];
148     int pos = 0;
149     event[pos++] = HCI_EVENT_AVRCP_META;
150     event[pos++] = sizeof(event) - 2;
151     event[pos++] = AVRCP_SUBEVENT_BROWSING_GET_TOTAL_NUM_ITEMS;
152     little_endian_store_16(event, pos, browsing_cid);
153     pos += 2;
154     event[pos++] = connection->scope;
155     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
156 }
157 
158 static void avrcp_emit_browsing_connection_established(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr, uint8_t status){
159     if (!callback) return;
160     uint8_t event[12];
161     int pos = 0;
162     event[pos++] = HCI_EVENT_AVRCP_META;
163     event[pos++] = sizeof(event) - 2;
164     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_ESTABLISHED;
165     event[pos++] = status;
166     reverse_bd_addr(addr,&event[pos]);
167     pos += 6;
168     little_endian_store_16(event, pos, browsing_cid);
169     pos += 2;
170     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
171 }
172 
173 static void avrcp_emit_incoming_browsing_connection(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr){
174     if (!callback) return;
175     uint8_t event[11];
176     int pos = 0;
177     event[pos++] = HCI_EVENT_AVRCP_META;
178     event[pos++] = sizeof(event) - 2;
179     event[pos++] = AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION;
180     reverse_bd_addr(addr,&event[pos]);
181     pos += 6;
182     little_endian_store_16(event, pos, browsing_cid);
183     pos += 2;
184     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
185 }
186 
187 static void avrcp_emit_browsing_connection_closed(btstack_packet_handler_t callback, uint16_t browsing_cid){
188     if (!callback) return;
189     uint8_t event[5];
190     int pos = 0;
191     event[pos++] = HCI_EVENT_AVRCP_META;
192     event[pos++] = sizeof(event) - 2;
193     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_RELEASED;
194     little_endian_store_16(event, pos, browsing_cid);
195     pos += 2;
196     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
197 }
198 
199 static avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection){
200     avrcp_browsing_connection_t * connection = btstack_memory_avrcp_browsing_connection_get();
201     memset(connection, 0, sizeof(avrcp_browsing_connection_t));
202     connection->state = AVCTP_CONNECTION_IDLE;
203     connection->transaction_label = 0xFF;
204     avrcp_connection->avrcp_browsing_cid = avrcp_get_next_cid();
205     avrcp_connection->browsing_connection = connection;
206     return connection;
207 }
208 
209 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){
210     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_bd_addr(remote_addr, context);
211 
212     if (!avrcp_connection){
213         log_error("avrcp: there is no previously established AVRCP controller connection.");
214         return ERROR_CODE_COMMAND_DISALLOWED;
215     }
216 
217     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
218     if (connection){
219         log_error(" avrcp_browsing_connect connection exists.");
220         return ERROR_CODE_SUCCESS;
221     }
222 
223     connection = avrcp_browsing_create_connection(avrcp_connection);
224     if (!connection){
225         log_error("avrcp: could not allocate connection struct.");
226         return BTSTACK_MEMORY_ALLOC_FAILED;
227     }
228 
229     if (!browsing_cid) return L2CAP_LOCAL_CID_DOES_NOT_EXIST;
230 
231     *browsing_cid = avrcp_connection->avrcp_browsing_cid;
232     connection->ertm_buffer = ertm_buffer;
233     connection->ertm_buffer_size = size;
234     avrcp_connection->browsing_connection = connection;
235 
236     memcpy(&connection->ertm_config, ertm_config, sizeof(l2cap_ertm_config_t));
237 
238     return l2cap_create_ertm_channel(avrcp_browsing_target_packet_handler, remote_addr, avrcp_connection->browsing_l2cap_psm,
239                     &connection->ertm_config, connection->ertm_buffer, connection->ertm_buffer_size, NULL);
240 
241 }
242 
243 static void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context){
244     UNUSED(channel);
245     UNUSED(size);
246     bd_addr_t event_addr;
247     uint16_t local_cid;
248     uint8_t  status;
249     avrcp_browsing_connection_t * browsing_connection = NULL;
250     avrcp_connection_t * avrcp_connection = NULL;
251 
252     if (packet_type != HCI_EVENT_PACKET) return;
253 
254     switch (hci_event_packet_get_type(packet)) {
255         case HCI_EVENT_DISCONNECTION_COMPLETE:
256             avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, 0);
257             break;
258         case L2CAP_EVENT_INCOMING_CONNECTION:
259             l2cap_event_incoming_connection_get_address(packet, event_addr);
260             local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
261             avrcp_connection = get_avrcp_connection_for_bd_addr(event_addr, context);
262             if (!avrcp_connection) {
263                 log_error("No previously created AVRCP controller connections");
264                 l2cap_decline_connection(local_cid);
265                 break;
266             }
267             browsing_connection = avrcp_browsing_create_connection(avrcp_connection);
268             browsing_connection->l2cap_browsing_cid = local_cid;
269             browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION;
270             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);
271             avrcp_emit_incoming_browsing_connection(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr);
272             break;
273 
274         case L2CAP_EVENT_CHANNEL_OPENED:
275             l2cap_event_channel_opened_get_address(packet, event_addr);
276             status = l2cap_event_channel_opened_get_status(packet);
277             local_cid = l2cap_event_channel_opened_get_local_cid(packet);
278 
279             avrcp_connection = get_avrcp_connection_for_bd_addr(event_addr, context);
280             if (!avrcp_connection){
281                 log_error("Failed to find AVRCP connection for bd_addr %s", bd_addr_to_str(event_addr));
282                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, local_cid, event_addr, L2CAP_LOCAL_CID_DOES_NOT_EXIST);
283                 l2cap_disconnect(local_cid, 0); // reason isn't used
284                 break;
285             }
286 
287             browsing_connection = avrcp_connection->browsing_connection;
288             if (status != ERROR_CODE_SUCCESS){
289                 log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status);
290                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, status);
291                 btstack_memory_avrcp_browsing_connection_free(browsing_connection);
292                 avrcp_connection->browsing_connection = NULL;
293                 break;
294             }
295             if (browsing_connection->state != AVCTP_CONNECTION_W4_L2CAP_CONNECTED) break;
296 
297             browsing_connection->l2cap_browsing_cid = local_cid;
298 
299             log_info("L2CAP_EVENT_CHANNEL_OPENED browsing cid 0x%02x, l2cap cid 0x%02x", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid);
300             browsing_connection->state = AVCTP_CONNECTION_OPENED;
301             avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, ERROR_CODE_SUCCESS);
302             break;
303 
304         case L2CAP_EVENT_CHANNEL_CLOSED:
305             // data: event (8), len(8), channel (16)
306             local_cid = l2cap_event_channel_closed_get_local_cid(packet);
307             avrcp_connection = get_avrcp_connection_for_browsing_l2cap_cid(local_cid, context);
308 
309             if (avrcp_connection && avrcp_connection->browsing_connection){
310                 avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid);
311                 // free connection
312                 btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
313                 avrcp_connection->browsing_connection = NULL;
314                 break;
315             }
316             break;
317         default:
318             break;
319     }
320 }
321 
322 
323 static void avrcp_browsing_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
324     avrcp_browsing_connection_t * browsing_connection;
325 
326     switch (packet_type) {
327         case L2CAP_DATA_PACKET:{
328             browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_target_context);
329             if (!browsing_connection) break;
330             // printf_hexdump(packet,size);
331             int pos = 0;
332             uint8_t transport_header = packet[pos++];
333             // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
334             browsing_connection->transaction_label = transport_header >> 4;
335             avrcp_packet_type_t avctp_packet_type = (transport_header & 0x0F) >> 2;
336             // printf("L2CAP_DATA_PACKET, transaction_label %d\n", browsing_connection->transaction_label);
337             switch (avctp_packet_type){
338                 case AVRCP_SINGLE_PACKET:
339                 case AVRCP_START_PACKET:
340                     // uint8_t frame_type = (transport_header & 0x03) >> 1;
341                     // uint8_t ipid = transport_header & 0x01;
342                     browsing_connection->subunit_type = packet[pos++] >> 2;
343                     browsing_connection->subunit_id = 0;
344                     browsing_connection->command_opcode = packet[pos++];
345                     // printf("subunit_id")
346                     // pos += 2;
347                     browsing_connection->num_packets = 1;
348                     if (avctp_packet_type == AVRCP_START_PACKET){
349                         browsing_connection->num_packets = packet[pos++];
350                     }
351                     browsing_connection->pdu_id = packet[pos++];
352                     // uint16_t length = big_endian_read_16(packet, pos);
353                     // pos += 2;
354                     break;
355                 default:
356                     break;
357             }
358             // printf("pdu id 0x%2x\n", browsing_connection->pdu_id);
359             // uint32_t i;
360             switch (avctp_packet_type){
361                 case AVRCP_SINGLE_PACKET:
362                 case AVRCP_END_PACKET:
363                     switch(browsing_connection->pdu_id){
364                         case AVRCP_PDU_ID_GET_FOLDER_ITEMS:
365                             printf("\n");
366                             browsing_connection->scope = packet[pos++];
367                             browsing_connection->start_item = big_endian_read_32(packet, pos);
368                             pos += 4;
369                             browsing_connection->end_item = big_endian_read_32(packet, pos);
370                             pos += 4;
371                             uint8_t attr_count = packet[pos++];
372 
373                             while (attr_count){
374                                 uint32_t attr_id = big_endian_read_32(packet, pos);
375                                 pos += 4;
376                                 browsing_connection->attr_bitmap |= (1 << attr_id);
377                                 attr_count--;
378                             }
379                             avrcp_browsing_target_emit_get_folder_items(avrcp_target_context.browsing_avrcp_callback, channel, browsing_connection);
380                             break;
381                         case AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS:{
382                             // send total num items
383                             browsing_connection->scope = packet[pos++];
384                             avrcp_browsing_target_emit_get_total_num_items(avrcp_target_context.browsing_avrcp_callback, channel, browsing_connection);
385                             // uint32_t num_items = big_endian_read_32(packet, pos);
386                             // pos += 4;
387                             break;
388                         }
389                         default:
390                             // printf("send avrcp_browsing_target_response_general_reject\n");
391                             avrcp_browsing_target_response_general_reject(browsing_connection, AVRCP_STATUS_INVALID_COMMAND);
392                             log_info(" not parsed pdu ID 0x%02x", browsing_connection->pdu_id);
393                             break;
394                     }
395                     browsing_connection->state = AVCTP_CONNECTION_OPENED;
396                     // 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);
397                     break;
398                 default:
399                     break;
400             }
401             // printf(" paket done\n");
402             break;
403         }
404 
405         case HCI_EVENT_PACKET:
406             switch (hci_event_packet_get_type(packet)){
407                 case L2CAP_EVENT_CAN_SEND_NOW:
408                     browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_target_context);
409                     if (!browsing_connection) break;
410                     if (browsing_connection->state != AVCTP_W2_SEND_RESPONSE) return;
411                     browsing_connection->state = AVCTP_CONNECTION_OPENED;
412                     avrcp_browsing_target_handle_can_send_now(browsing_connection);
413                     break;
414                 default:
415                     avrcp_browser_packet_handler(packet_type, channel, packet, size, &avrcp_target_context);
416                     break;
417             }
418             break;
419 
420         default:
421             break;
422     }
423 }
424 
425 void avrcp_browsing_target_init(void){
426     avrcp_target_context.browsing_packet_handler = avrcp_browsing_target_packet_handler;
427     l2cap_register_service(&avrcp_browsing_target_packet_handler, PSM_AVCTP_BROWSING, 0xffff, LEVEL_2);
428 }
429 
430 void avrcp_browsing_target_register_packet_handler(btstack_packet_handler_t callback){
431     if (callback == NULL){
432         log_error("avrcp_browsing_target_register_packet_handler called with NULL callback");
433         return;
434     }
435     avrcp_target_context.browsing_avrcp_callback = callback;
436 }
437 
438 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){
439     return avrcp_browsing_connect(bd_addr, &avrcp_target_context, ertm_buffer, size, ertm_config, avrcp_browsing_cid);
440 }
441 
442 uint8_t avrcp_browsing_target_disconnect(uint16_t avrcp_browsing_cid){
443     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_target_context);
444     if (!avrcp_connection){
445         log_error("avrcp_browsing_target_disconnect: could not find a connection.");
446         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
447     }
448     if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
449 
450     l2cap_disconnect(avrcp_connection->browsing_connection->l2cap_browsing_cid, 0);
451     return ERROR_CODE_SUCCESS;
452 }
453 
454 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){
455     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_target_context);
456     if (!avrcp_connection){
457         log_error("avrcp_browsing_decline_incoming_connection: could not find a connection.");
458         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
459     }
460     if (!avrcp_connection->browsing_connection){
461         log_error("avrcp_browsing_decline_incoming_connection: no browsing connection.");
462         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
463     }
464 
465     if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_W4_ERTM_CONFIGURATION){
466         log_error("avrcp_browsing_decline_incoming_connection: browsing connection in a wrong state.");
467         return ERROR_CODE_COMMAND_DISALLOWED;
468     }
469 
470     avrcp_connection->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
471     avrcp_connection->browsing_connection->ertm_buffer = ertm_buffer;
472     avrcp_connection->browsing_connection->ertm_buffer_size = size;
473     memcpy(&avrcp_connection->browsing_connection->ertm_config, ertm_config, sizeof(l2cap_ertm_config_t));
474     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);
475     return ERROR_CODE_SUCCESS;
476 }
477 
478 uint8_t avrcp_browsing_target_decline_incoming_connection(uint16_t avrcp_browsing_cid){
479     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_target_context);
480     if (!avrcp_connection){
481         log_error("avrcp_browsing_decline_incoming_connection: could not find a connection.");
482         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
483     }
484     if (!avrcp_connection->browsing_connection) return ERROR_CODE_SUCCESS;
485     if (avrcp_connection->browsing_connection->state > AVCTP_CONNECTION_W4_ERTM_CONFIGURATION) return ERROR_CODE_COMMAND_DISALLOWED;
486 
487     l2cap_decline_connection(avrcp_connection->browsing_connection->l2cap_browsing_cid);
488     // free connection
489     btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
490     avrcp_connection->browsing_connection = NULL;
491     return ERROR_CODE_SUCCESS;
492 }
493 
494 uint8_t avrcp_subevent_browsing_get_folder_items_response(uint16_t avrcp_browsing_cid, uint16_t uid_counter, uint8_t * attr_list, uint16_t attr_list_size){
495     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_target_context);
496     if (!avrcp_connection){
497         log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
498         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
499     }
500 
501     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
502     if (!connection){
503         log_info("avrcp_subevent_browsing_get_folder_items_response: could not find a connection.");
504         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
505     }
506     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
507 
508     if (connection->state != AVCTP_CONNECTION_OPENED) {
509         log_info("avrcp_subevent_browsing_get_folder_items_response: wrong state.");
510         return ERROR_CODE_COMMAND_DISALLOWED;
511     }
512     int pos = 0;
513 
514     connection->cmd_operands[pos++] = AVRCP_PDU_ID_GET_FOLDER_ITEMS;
515     big_endian_store_16(connection->cmd_operands, pos, attr_list_size);
516     pos += 2;
517 
518     connection->cmd_operands[pos++] = AVRCP_STATUS_SUCCESS;
519     big_endian_store_16(connection->cmd_operands, pos, uid_counter);
520     pos += 2;
521 
522     // TODO: fragmentation
523     if (attr_list_size >  sizeof(connection->cmd_operands)){
524         connection->attr_list = attr_list;
525         connection->attr_list_size = attr_list_size;
526         log_info(" todo: list too big, invoke fragmentation");
527         return 1;
528     }
529     memcpy(&connection->cmd_operands[pos], attr_list, attr_list_size);
530     pos += attr_list_size;
531     connection->cmd_operands_length = pos;
532     // printf_hexdump(connection->cmd_operands, connection->cmd_operands_length);
533 
534     connection->state = AVCTP_W2_SEND_RESPONSE;
535     avrcp_browsing_target_request_can_send_now(connection, connection->l2cap_browsing_cid);
536     return ERROR_CODE_SUCCESS;
537 }
538 
539 
540 uint8_t avrcp_subevent_browsing_get_total_num_items_response(uint16_t avrcp_browsing_cid, uint16_t uid_counter, uint32_t total_num_items){
541     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_target_context);
542     if (!avrcp_connection){
543         log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
544         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
545     }
546 
547     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
548     if (!connection){
549         log_info("avrcp_subevent_browsing_get_folder_items_response: could not find a connection.");
550         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
551     }
552     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
553 
554     if (connection->state != AVCTP_CONNECTION_OPENED) {
555         log_info("avrcp_subevent_browsing_get_folder_items_response: wrong state.");
556         return ERROR_CODE_COMMAND_DISALLOWED;
557     }
558 
559     int pos = 0;
560     connection->cmd_operands[pos++] = AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
561     big_endian_store_16(connection->cmd_operands, pos, 7);
562     pos += 2;
563     connection->cmd_operands[pos++] = AVRCP_STATUS_SUCCESS;
564     big_endian_store_16(connection->cmd_operands, pos, uid_counter);
565     pos += 2;
566     big_endian_store_32(connection->cmd_operands, pos, total_num_items);
567     pos += 4;
568     connection->cmd_operands_length = pos;
569     // printf_hexdump(connection->cmd_operands, connection->cmd_operands_length);
570 
571     connection->state = AVCTP_W2_SEND_RESPONSE;
572     avrcp_browsing_target_request_can_send_now(connection, connection->l2cap_browsing_cid);
573     return ERROR_CODE_SUCCESS;
574 }
575 
576 
577 
578 /*
579 int pos = 0;
580     connection->cmd_operands[pos++] = AVRCP_PDU_ID_GENERAL_REJECT;
581     // connection->cmd_operands[pos++] = 0;
582     // param length
583     big_endian_store_16(connection->cmd_operands, pos, 1);
584     pos += 2;
585     connection->cmd_operands[pos++] = status;
586     connection->cmd_operands_length = 4;
587     connection->state = AVCTP_W2_SEND_RESPONSE;
588 */
589 
590