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