xref: /btstack/src/classic/avrcp_browsing_controller.c (revision 65ca3506ca5bd78b117b7aa328915aa76e3fc61b)
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_controller.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_controller.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_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
53 
54 static avrcp_connection_t * get_avrcp_connection_for_browsing_cid(uint16_t browsing_cid, avrcp_context_t * context){
55     btstack_linked_list_iterator_t it;
56     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
57     while (btstack_linked_list_iterator_has_next(&it)){
58         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
59         if (connection->avrcp_browsing_cid != browsing_cid) continue;
60         return connection;
61     }
62     return NULL;
63 }
64 
65 static avrcp_connection_t * get_avrcp_connection_for_browsing_l2cap_cid(uint16_t browsing_l2cap_cid, avrcp_context_t * context){
66     btstack_linked_list_iterator_t it;
67     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
68     while (btstack_linked_list_iterator_has_next(&it)){
69         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
70         if (connection->browsing_connection &&  connection->browsing_connection->l2cap_browsing_cid != browsing_l2cap_cid) continue;
71         return connection;
72     }
73     return NULL;
74 }
75 
76 static avrcp_browsing_connection_t * get_avrcp_browsing_connection_for_l2cap_cid(uint16_t l2cap_cid, avrcp_context_t * context){
77     btstack_linked_list_iterator_t it;
78     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
79     while (btstack_linked_list_iterator_has_next(&it)){
80         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
81         if (connection->browsing_connection && connection->browsing_connection->l2cap_browsing_cid != l2cap_cid) continue;
82         return connection->browsing_connection;
83     }
84     return NULL;
85 }
86 
87 static void avrcp_emit_browsing_connection_established(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr, uint8_t status){
88     if (!callback) return;
89     uint8_t event[12];
90     int pos = 0;
91     event[pos++] = HCI_EVENT_AVRCP_META;
92     event[pos++] = sizeof(event) - 2;
93     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_ESTABLISHED;
94     event[pos++] = status;
95     reverse_bd_addr(addr,&event[pos]);
96     pos += 6;
97     little_endian_store_16(event, pos, browsing_cid);
98     pos += 2;
99     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
100 }
101 
102 static void avrcp_emit_incoming_browsing_connection(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr){
103     if (!callback) return;
104     uint8_t event[11];
105     int pos = 0;
106     event[pos++] = HCI_EVENT_AVRCP_META;
107     event[pos++] = sizeof(event) - 2;
108     event[pos++] = AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION;
109     reverse_bd_addr(addr,&event[pos]);
110     pos += 6;
111     little_endian_store_16(event, pos, browsing_cid);
112     pos += 2;
113     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
114 }
115 
116 static void avrcp_emit_browsing_connection_closed(btstack_packet_handler_t callback, uint16_t browsing_cid){
117     if (!callback) return;
118     uint8_t event[5];
119     int pos = 0;
120     event[pos++] = HCI_EVENT_AVRCP_META;
121     event[pos++] = sizeof(event) - 2;
122     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_RELEASED;
123     little_endian_store_16(event, pos, browsing_cid);
124     pos += 2;
125     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
126 }
127 
128 static avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection){
129     avrcp_browsing_connection_t * connection = btstack_memory_avrcp_browsing_connection_get();
130     memset(connection, 0, sizeof(avrcp_browsing_connection_t));
131     connection->state = AVCTP_CONNECTION_IDLE;
132     connection->transaction_label = 0xFF;
133     avrcp_connection->avrcp_browsing_cid = avrcp_get_next_cid();
134     avrcp_connection->browsing_connection = connection;
135     return connection;
136 }
137 
138 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){
139     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_bd_addr(remote_addr, context);
140 
141     if (!avrcp_connection){
142         log_error("avrcp: there is no previously established AVRCP controller connection.");
143         return ERROR_CODE_COMMAND_DISALLOWED;
144     }
145 
146     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
147     if (connection){
148         log_error(" avrcp_browsing_connect connection exists.");
149         return ERROR_CODE_SUCCESS;
150     }
151 
152     connection = avrcp_browsing_create_connection(avrcp_connection);
153     if (!connection){
154         log_error("avrcp: could not allocate connection struct.");
155         return BTSTACK_MEMORY_ALLOC_FAILED;
156     }
157 
158     if (browsing_cid){
159         *browsing_cid = avrcp_connection->avrcp_browsing_cid;
160     }
161 
162     connection->ertm_buffer = ertm_buffer;
163     connection->ertm_buffer_size = size;
164     avrcp_connection->browsing_connection = connection;
165     avrcp_connection->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
166     memcpy(&connection->ertm_config, ertm_config, sizeof(l2cap_ertm_config_t));
167 
168     return l2cap_create_ertm_channel(avrcp_browsing_controller_packet_handler, remote_addr, avrcp_connection->browsing_l2cap_psm,
169                     &connection->ertm_config, connection->ertm_buffer, connection->ertm_buffer_size, NULL);
170 
171 }
172 
173 static void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context){
174     UNUSED(channel);
175     UNUSED(size);
176     bd_addr_t event_addr;
177     uint16_t local_cid;
178     uint8_t  status;
179     avrcp_browsing_connection_t * browsing_connection = NULL;
180     avrcp_connection_t * avrcp_connection = NULL;
181 
182     if (packet_type != HCI_EVENT_PACKET) return;
183 
184     switch (hci_event_packet_get_type(packet)) {
185         case HCI_EVENT_DISCONNECTION_COMPLETE:
186             avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, 0);
187             break;
188         case L2CAP_EVENT_INCOMING_CONNECTION:
189             l2cap_event_incoming_connection_get_address(packet, event_addr);
190             local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
191             avrcp_connection = get_avrcp_connection_for_bd_addr(event_addr, context);
192             if (!avrcp_connection) {
193                 log_error("No previously created AVRCP controller connections");
194                 l2cap_decline_connection(local_cid);
195                 break;
196             }
197             browsing_connection = avrcp_browsing_create_connection(avrcp_connection);
198             browsing_connection->l2cap_browsing_cid = local_cid;
199             browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION;
200             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);
201             avrcp_emit_incoming_browsing_connection(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr);
202             break;
203 
204         case L2CAP_EVENT_CHANNEL_OPENED:
205             l2cap_event_channel_opened_get_address(packet, event_addr);
206             status = l2cap_event_channel_opened_get_status(packet);
207             local_cid = l2cap_event_channel_opened_get_local_cid(packet);
208 
209             avrcp_connection = get_avrcp_connection_for_bd_addr(event_addr, context);
210             if (!avrcp_connection){
211                 log_error("Failed to find AVRCP connection for bd_addr %s", bd_addr_to_str(event_addr));
212                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, local_cid, event_addr, L2CAP_LOCAL_CID_DOES_NOT_EXIST);
213                 l2cap_disconnect(local_cid, 0); // reason isn't used
214                 break;
215             }
216 
217             browsing_connection = avrcp_connection->browsing_connection;
218             if (status != ERROR_CODE_SUCCESS){
219                 log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status);
220                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, status);
221                 btstack_memory_avrcp_browsing_connection_free(browsing_connection);
222                 avrcp_connection->browsing_connection = NULL;
223                 break;
224             }
225             browsing_connection->l2cap_browsing_cid = local_cid;
226 
227             log_info("L2CAP_EVENT_CHANNEL_OPENED browsing cid 0x%02x, l2cap cid 0x%02x", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid);
228             browsing_connection->state = AVCTP_CONNECTION_OPENED;
229             avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, ERROR_CODE_SUCCESS);
230             break;
231 
232         case L2CAP_EVENT_CHANNEL_CLOSED:
233             // data: event (8), len(8), channel (16)
234             local_cid = l2cap_event_channel_closed_get_local_cid(packet);
235             avrcp_connection = get_avrcp_connection_for_browsing_l2cap_cid(local_cid, context);
236 
237             if (avrcp_connection && avrcp_connection->browsing_connection){
238                 avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid);
239                 // free connection
240                 btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
241                 avrcp_connection->browsing_connection = NULL;
242                 break;
243             }
244             break;
245         default:
246             break;
247     }
248 }
249 
250 static int avrcp_browsing_controller_send_get_folder_items_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
251     uint8_t command[100];
252     int pos = 0;
253 
254     // // if (connection->cmd_operands[3] == AVRCP_PDU_ID_GET_CAPABILITIES){
255     //     printf("cheet\n");
256     //     uint8_t buffer[] = {0xB0, 0x11, 0x0E, 0xFF, 0x00, 0x02, 0xFF, 0xFF};
257     //     memcpy(command, buffer, sizeof(buffer));
258     //     pos =  sizeof(buffer);
259     //     return l2cap_send(cid, command, pos);
260     // // }
261 
262     // transport header
263     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
264     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
265     // Profile IDentifier (PID)
266     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
267     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
268     command[pos++] = AVRCP_PDU_ID_GET_FOLDER_ITEMS;
269     printf_hexdump(command, pos);
270     printf("\n");
271 
272     uint32_t attribute_count = 0;
273     uint32_t attributes_to_copy = 0;
274 
275     switch (connection->attr_bitmap){
276         case AVRCP_MEDIA_ATTR_NONE:
277             attribute_count = AVRCP_MEDIA_ATTR_NONE; // 0xFFFFFFFF
278             break;
279         case AVRCP_MEDIA_ATTR_ALL:
280             attribute_count = AVRCP_MEDIA_ATTR_ALL;  // 0
281             break;
282         default:
283             attribute_count    = count_set_bits_uint32(connection->attr_bitmap & 0xff);
284             attributes_to_copy = attribute_count;
285             break;
286     }
287     big_endian_store_16(command, pos, 9 + 1 + attribute_count*4);
288     pos += 2;
289 
290     command[pos++] = connection->scope;
291     big_endian_store_32(command, pos, connection->start_item);
292     pos += 4;
293     big_endian_store_32(command, pos, connection->end_item);
294     pos += 4;
295     command[pos++] = attribute_count;
296 
297     int bit_position = 1;
298     while (attributes_to_copy){
299         if (connection->attr_bitmap & (1 << bit_position)){
300             big_endian_store_32(command, pos, bit_position);
301             pos += 4;
302             attributes_to_copy--;
303         }
304         bit_position++;
305     }
306     return l2cap_send(cid, command, pos);
307 }
308 
309 
310 static int avrcp_browsing_controller_send_get_item_attributes_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
311     uint8_t command[100];
312     int pos = 0;
313     // transport header
314     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
315     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
316     // Profile IDentifier (PID)
317     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
318     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
319     command[pos++] = AVRCP_PDU_ID_GET_ITEM_ATTRIBUTES;
320 
321     uint32_t attribute_count;
322     uint32_t attributes_to_copy = 0;
323 
324     switch (connection->attr_bitmap){
325         case AVRCP_MEDIA_ATTR_NONE:
326         case AVRCP_MEDIA_ATTR_ALL:
327             attribute_count = 0;
328             break;
329         default:
330             attribute_count = count_set_bits_uint32(connection->attr_bitmap & 0xff);
331             attributes_to_copy = attribute_count;
332             break;
333     }
334 
335     big_endian_store_16(command, pos, 12 + attribute_count*4);
336     pos += 2;
337 
338     command[pos++] = connection->scope;
339     memcpy(command+pos, connection->folder_uid, 8);
340     pos += 8;
341     big_endian_store_16(command, pos, connection->uid_counter);
342     pos += 2;
343     command[pos++] = attribute_count;
344 
345     int bit_position = 1;
346     while (attributes_to_copy){
347         if (connection->attr_bitmap & (1 << bit_position)){
348             big_endian_store_32(command, pos, bit_position);
349             pos += 4;
350             attributes_to_copy--;
351         }
352         bit_position++;
353     }
354 
355     return l2cap_send(cid, command, pos);
356 }
357 
358 
359 static int avrcp_browsing_controller_send_change_path_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
360     uint8_t command[100];
361     int pos = 0;
362     // transport header
363     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
364     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
365     // Profile IDentifier (PID)
366     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
367     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
368     command[pos++] = AVRCP_PDU_ID_CHANGE_PATH;
369 
370     big_endian_store_16(command, pos, 11);
371     pos += 2;
372     pos += 2;
373     command[pos++] = connection->direction;
374     memcpy(command+pos, connection->folder_uid, 8);
375     pos += 8;
376     return l2cap_send(cid, command, pos);
377 }
378 
379 static int avrcp_browsing_controller_send_search_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
380     uint8_t command[100];
381     int pos = 0;
382     // transport header
383     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
384     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
385     // Profile IDentifier (PID)
386     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
387     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
388     command[pos++] = AVRCP_PDU_ID_SEARCH;
389 
390     big_endian_store_16(command, pos, 4 + connection->search_str_len);
391     pos += 2;
392 
393     big_endian_store_16(command, pos, 0x006A);
394     pos += 2;
395     big_endian_store_16(command, pos, connection->search_str_len);
396     pos += 2;
397 
398     memcpy(command+pos,connection->search_str, connection->search_str_len);
399     pos += connection->search_str_len;
400     return l2cap_send(cid, command, pos);
401 }
402 
403 static int avrcp_browsing_controller_send_set_browsed_player_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
404     uint8_t command[100];
405     int pos = 0;
406     // transport header
407     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
408     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
409     // Profile IDentifier (PID)
410     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
411     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
412     command[pos++] = AVRCP_PDU_ID_SET_BROWSED_PLAYER;
413 
414     big_endian_store_16(command, pos, 2);
415     pos += 2;
416     big_endian_store_16(command, pos, connection->browsed_player_id);
417     pos += 2;
418     return l2cap_send(cid, command, pos);
419 }
420 
421 static int avrcp_browsing_controller_send_get_total_nr_items_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
422     uint8_t command[7];
423     int pos = 0;
424     // transport header
425     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
426     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
427     // Profile IDentifier (PID)
428     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
429     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
430     command[pos++] = AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
431 
432     big_endian_store_16(command, pos, 1);
433     pos += 2;
434     command[pos++] = connection->get_total_nr_items_scope;
435     return l2cap_send(cid, command, pos);
436 }
437 
438 static void avrcp_browsing_controller_handle_can_send_now(avrcp_browsing_connection_t * connection){
439     switch (connection->state){
440         case AVCTP_CONNECTION_OPENED:
441             if (connection->set_browsed_player_id){
442                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
443                 connection->set_browsed_player_id = 0;
444                 avrcp_browsing_controller_send_set_browsed_player_cmd(connection->l2cap_browsing_cid, connection);
445                 break;
446             }
447 
448             if (connection->get_total_nr_items){
449                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
450                 connection->get_total_nr_items = 0;
451                 avrcp_browsing_controller_send_get_total_nr_items_cmd(connection->l2cap_browsing_cid, connection);
452                 break;
453             }
454 
455             if (connection->get_folder_items){
456                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
457                 connection->get_folder_items = 0;
458                 avrcp_browsing_controller_send_get_folder_items_cmd(connection->l2cap_browsing_cid, connection);
459                 break;
460             }
461 
462             if (connection->get_item_attributes){
463                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
464                 connection->get_item_attributes = 0;
465                 avrcp_browsing_controller_send_get_item_attributes_cmd(connection->l2cap_browsing_cid, connection);
466                 break;
467             }
468 
469             if (connection->change_path){
470                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
471                 connection->change_path = 0;
472                 avrcp_browsing_controller_send_change_path_cmd(connection->l2cap_browsing_cid, connection);
473                 break;
474             }
475 
476             if (connection->search){
477                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
478                 connection->search = 0;
479                 avrcp_browsing_controller_send_search_cmd(connection->l2cap_browsing_cid, connection);
480                 break;
481             }
482             break;
483         default:
484             return;
485     }
486 }
487 
488 
489 static void avrcp_browsing_controller_emit_done_with_uid_counter(btstack_packet_handler_t callback, uint16_t browsing_cid, uint16_t uid_counter, uint8_t browsing_status, uint8_t bluetooth_status){
490     if (!callback) return;
491     uint8_t event[9];
492     int pos = 0;
493     event[pos++] = HCI_EVENT_AVRCP_META;
494     event[pos++] = sizeof(event) - 2;
495     event[pos++] = AVRCP_SUBEVENT_BROWSING_DONE;
496     little_endian_store_16(event, pos, browsing_cid);
497     pos += 2;
498     little_endian_store_16(event, pos, uid_counter);
499     pos += 2;
500     event[pos++] = browsing_status;
501     event[pos++] = bluetooth_status;
502     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
503 }
504 
505 static void avrcp_parser_reset(avrcp_browsing_connection_t * connection){
506     connection->parser_attribute_header_pos = 0;
507     connection->parsed_attribute_value_offset = 0;
508     connection->parsed_num_attributes = 0;
509     connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
510 }
511 
512 
513 static void avrcp_browsing_parser_process_byte(uint8_t byte, avrcp_browsing_connection_t * connection){
514     uint8_t prepended_header_size = 1;
515     switch(connection->parser_state){
516         case AVRCP_PARSER_GET_ATTRIBUTE_HEADER:{
517             connection->parser_attribute_header[connection->parser_attribute_header_pos++] = byte;
518             if (connection->parser_attribute_header_pos < AVRCP_BROWSING_ITEM_HEADER_LEN) break;
519 
520             uint16_t attribute_total_value_len = big_endian_read_16(connection->parser_attribute_header, 1);
521             connection->parsed_attribute_value[connection->parsed_attribute_value_offset++] = connection->parser_attribute_header[0];   // prepend with item type
522             connection->parsed_attribute_value_len = btstack_min(attribute_total_value_len, AVRCP_MAX_ATTRIBUTTE_SIZE - prepended_header_size);                 // reduce AVRCP_MAX_ATTRIBUTTE_SIZE for the size ot item type
523             connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_VALUE;
524             // printf("AVRCP_PARSER_GET_ATTRIBUTE_HEADER value len %d, to parse %d, offset %d\n", attribute_total_value_len, connection->parsed_attribute_value_len, connection->parsed_attribute_value_offset);
525             break;
526         }
527         case AVRCP_PARSER_GET_ATTRIBUTE_VALUE:{
528             connection->parsed_attribute_value[connection->parsed_attribute_value_offset++] = byte;
529             if (connection->parsed_attribute_value_offset < connection->parsed_attribute_value_len + prepended_header_size){
530                 break;
531             }
532             if (connection->parsed_attribute_value_offset < big_endian_read_16(connection->parser_attribute_header, 1)){
533                 connection->parser_state = AVRCP_PARSER_IGNORE_REST_OF_ATTRIBUTE_VALUE;
534                 break;
535             }
536             connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
537             (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, connection->l2cap_browsing_cid, &connection->parsed_attribute_value[0], connection->parsed_attribute_value_offset);
538             connection->parsed_num_attributes++;
539             connection->parsed_attribute_value_offset = 0;
540             connection->parser_attribute_header_pos = 0;
541 
542             if (connection->parsed_num_attributes == connection->num_items){
543                 avrcp_parser_reset(connection);
544                 break;
545             }
546             break;
547         }
548         case AVRCP_PARSER_IGNORE_REST_OF_ATTRIBUTE_VALUE:
549             connection->parsed_attribute_value_offset++;
550             if (connection->parsed_attribute_value_offset < big_endian_read_16(connection->parser_attribute_header, 1) + prepended_header_size){
551                 break;
552             }
553             connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
554             (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, connection->l2cap_browsing_cid, &connection->parsed_attribute_value[0], connection->parsed_attribute_value_offset);
555             connection->parsed_num_attributes++;
556             connection->parsed_attribute_value_offset = 0;
557             connection->parser_attribute_header_pos = 0;
558 
559             if (connection->parsed_num_attributes == connection->num_items){
560                 avrcp_parser_reset(connection);
561                 break;
562             }
563             break;
564         default:
565             break;
566     }
567 }
568 
569 static void avrcp_browsing_parse_and_emit_element_attrs(uint8_t * packet, uint16_t num_bytes_to_read, avrcp_browsing_connection_t * connection){
570     int i;
571     for (i=0;i<num_bytes_to_read;i++){
572         avrcp_browsing_parser_process_byte(packet[i], connection);
573     }
574 }
575 
576 static void avrcp_browsing_controller_emit_failed(btstack_packet_handler_t callback, uint16_t browsing_cid, uint8_t browsing_status, uint8_t bluetooth_status){
577     avrcp_browsing_controller_emit_done_with_uid_counter(callback, browsing_cid, 0, browsing_status, bluetooth_status);
578 }
579 
580 
581 static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
582     avrcp_browsing_connection_t * browsing_connection;
583 
584     switch (packet_type) {
585         case L2CAP_DATA_PACKET:{
586             browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_controller_context);
587             if (!browsing_connection) break;
588             // printf("received \n");
589             // printf_hexdump(packet,size);
590             int pos = 0;
591             uint8_t transport_header = packet[pos++];
592             // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
593             browsing_connection->transaction_label = transport_header >> 4;
594             avrcp_packet_type_t avctp_packet_type = (transport_header & 0x0F) >> 2;
595             // printf("L2CAP_DATA_PACKET, packet type %d\n", avctp_packet_type);
596             switch (avctp_packet_type){
597                 case AVRCP_SINGLE_PACKET:
598                 case AVRCP_START_PACKET:
599                     // uint8_t frame_type = (transport_header & 0x03) >> 1;
600                     // uint8_t ipid = transport_header & 0x01;
601                     pos += 2;
602                     browsing_connection->num_packets = 1;
603                     if (avctp_packet_type == AVRCP_START_PACKET){
604                         browsing_connection->num_packets = packet[pos++];
605                     }
606                     if (pos + 4 > size){
607                         browsing_connection->state = AVCTP_CONNECTION_OPENED;
608                         avrcp_browsing_controller_emit_failed(avrcp_controller_context.browsing_avrcp_callback, channel, AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND, ERROR_CODE_SUCCESS);
609                         return;
610                     }
611                     browsing_connection->pdu_id = packet[pos++];
612                     // uint16_t length = big_endian_read_16(packet, pos);
613                     pos += 2;
614                     browsing_connection->browsing_status = packet[pos++];
615                     if (browsing_connection->browsing_status != AVRCP_BROWSING_ERROR_CODE_SUCCESS){
616                         browsing_connection->state = AVCTP_CONNECTION_OPENED;
617                         avrcp_browsing_controller_emit_failed(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_connection->browsing_status, ERROR_CODE_SUCCESS);
618                         return;
619                     }
620                     break;
621                 default:
622                     break;
623             }
624 
625             uint32_t i;
626             switch(browsing_connection->pdu_id){
627                 case AVRCP_PDU_ID_CHANGE_PATH:
628                     // printf("AVRCP_PDU_ID_CHANGE_PATH \n");
629                     break;
630                 case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER:
631                     // printf("AVRCP_PDU_ID_SET_ADDRESSED_PLAYER \n");
632                     break;
633                 case AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS:{
634                     // uint32_t num_items = big_endian_read_32(packet, pos);
635                     // pos += 4;
636                     // printf("TODO: send event, uid_counter %d, num_items %d\n", browsing_connection->uid_counter, num_items);
637                     break;
638                 }
639                 case AVRCP_PDU_ID_SET_BROWSED_PLAYER:{
640                     // printf("AVRCP_PDU_ID_SET_BROWSED_PLAYER \n");
641                     browsing_connection->uid_counter =  big_endian_read_16(packet, pos);
642                     pos += 2;
643                     // uint32_t num_items = big_endian_read_32(packet, pos);
644                     pos += 4;
645                     // uint16_t charset = big_endian_read_16(packet, pos);
646                     pos += 2;
647                     uint8_t folder_depth = packet[pos++];
648 
649                     for (i = 0; i < folder_depth; i++){
650                         uint16_t folder_name_length = big_endian_read_16(packet, pos);
651                         pos += 2;
652                         // reuse packet and add data type as a header
653                         packet[pos-1] = AVRCP_BROWSING_MEDIA_ROOT_FOLDER;
654                         (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos-1, folder_name_length+1);
655                         pos += folder_name_length;
656                     }
657                     break;
658                 }
659                 case AVRCP_PDU_ID_GET_FOLDER_ITEMS:{
660                     // printf("AVRCP_PDU_ID_GET_FOLDER_ITEMS \n");
661                     switch (avctp_packet_type){
662                         case AVRCP_SINGLE_PACKET:
663                         case AVRCP_START_PACKET:
664                             avrcp_parser_reset(browsing_connection);
665                             browsing_connection->uid_counter =  big_endian_read_16(packet, pos);
666                             pos += 2;
667                             browsing_connection->num_items = big_endian_read_16(packet, pos); //num_items
668                             pos += 2;
669                             avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection);
670                             break;
671 
672                         case AVRCP_CONTINUE_PACKET:
673                             avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection);
674                             break;
675 
676                         case AVRCP_END_PACKET:
677                             avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection);
678                             avrcp_parser_reset(browsing_connection);
679                             break;
680                     }
681                     break;
682                 }
683                 case AVRCP_PDU_ID_SEARCH:{
684                     browsing_connection->uid_counter =  big_endian_read_16(packet, pos);
685                     pos += 2;
686                     // uint32_t num_items = big_endian_read_32(packet, pos);
687                     // printf("TODO: send as event, search found %d items\n", num_items);
688                     break;
689                 }
690                 case AVRCP_PDU_ID_GET_ITEM_ATTRIBUTES:
691                     packet[pos-1] = AVRCP_BROWSING_MEDIA_ELEMENT_ITEM_ATTRIBUTE;
692                     (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos-1, size - pos + 1);
693                     break;
694                 default:
695                     log_info(" not parsed pdu ID 0x%02x", browsing_connection->pdu_id);
696                     break;
697             }
698 
699             switch (avctp_packet_type){
700                 case AVRCP_SINGLE_PACKET:
701                 case AVRCP_END_PACKET:
702                     // printf("reset browsing connection state to OPENED\n");
703                     browsing_connection->state = AVCTP_CONNECTION_OPENED;
704                     avrcp_browsing_controller_emit_done_with_uid_counter(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_connection->uid_counter, browsing_connection->browsing_status, ERROR_CODE_SUCCESS);
705                     break;
706                 default:
707                     break;
708             }
709             // printf(" paket done\n");
710             break;
711         }
712         case HCI_EVENT_PACKET:
713             switch (hci_event_packet_get_type(packet)){
714                 case L2CAP_EVENT_CAN_SEND_NOW:
715                     browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_controller_context);
716                     if (!browsing_connection) break;
717                     avrcp_browsing_controller_handle_can_send_now(browsing_connection);
718                     break;
719                 default:
720                     avrcp_browser_packet_handler(packet_type, channel, packet, size, &avrcp_controller_context);
721                     break;
722             }
723             break;
724 
725         default:
726             break;
727     }
728 }
729 
730 void avrcp_browsing_controller_init(void){
731     avrcp_controller_context.browsing_packet_handler = avrcp_browsing_controller_packet_handler;
732     l2cap_register_service(&avrcp_browsing_controller_packet_handler, PSM_AVCTP_BROWSING, 0xffff, LEVEL_2);
733 }
734 
735 void avrcp_browsing_controller_register_packet_handler(btstack_packet_handler_t callback){
736     if (callback == NULL){
737         log_error("avrcp_browsing_controller_register_packet_handler called with NULL callback");
738         return;
739     }
740     avrcp_controller_context.browsing_avrcp_callback = callback;
741 }
742 
743 uint8_t avrcp_browsing_controller_connect(bd_addr_t bd_addr, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config, uint16_t * avrcp_browsing_cid){
744     return avrcp_browsing_connect(bd_addr, &avrcp_controller_context, ertm_buffer, size, ertm_config, avrcp_browsing_cid);
745 }
746 
747 uint8_t avrcp_browsing_controller_disconnect(uint16_t avrcp_browsing_cid){
748     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
749     if (!avrcp_connection){
750         log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
751         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
752     }
753     if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
754 
755     l2cap_disconnect(avrcp_connection->browsing_connection->l2cap_browsing_cid, 0);
756     return ERROR_CODE_SUCCESS;
757 }
758 
759 uint8_t avrcp_browsing_controller_configure_incoming_connection(uint16_t avrcp_browsing_cid, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config){
760     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
761     if (!avrcp_connection){
762         log_error("avrcp_browsing_controller_decline_incoming_connection: could not find a connection.");
763         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
764     }
765     if (!avrcp_connection->browsing_connection){
766         log_error("avrcp_browsing_controller_decline_incoming_connection: no browsing connection.");
767         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
768     }
769 
770     if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_W4_ERTM_CONFIGURATION){
771         log_error("avrcp_browsing_controller_decline_incoming_connection: browsing connection in a wrong state.");
772         return ERROR_CODE_COMMAND_DISALLOWED;
773     }
774 
775     avrcp_connection->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
776     avrcp_connection->browsing_connection->ertm_buffer = ertm_buffer;
777     avrcp_connection->browsing_connection->ertm_buffer_size = size;
778     memcpy(&avrcp_connection->browsing_connection->ertm_config, ertm_config, sizeof(l2cap_ertm_config_t));
779     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);
780     return ERROR_CODE_SUCCESS;
781 }
782 
783 uint8_t avrcp_browsing_controller_decline_incoming_connection(uint16_t avrcp_browsing_cid){
784     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
785     if (!avrcp_connection){
786         log_error("avrcp_browsing_controller_decline_incoming_connection: could not find a connection.");
787         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
788     }
789     if (!avrcp_connection->browsing_connection) return ERROR_CODE_SUCCESS;
790     if (avrcp_connection->browsing_connection->state > AVCTP_CONNECTION_W4_ERTM_CONFIGURATION) return ERROR_CODE_COMMAND_DISALLOWED;
791 
792     l2cap_decline_connection(avrcp_connection->browsing_connection->l2cap_browsing_cid);
793     // free connection
794     btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
795     avrcp_connection->browsing_connection = NULL;
796     return ERROR_CODE_SUCCESS;
797 }
798 
799 uint8_t avrcp_browsing_controller_get_item_attributes_for_scope(uint16_t avrcp_browsing_cid, uint8_t * uid, uint16_t uid_counter, uint32_t attr_bitmap, avrcp_browsing_scope_t scope){
800     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
801     if (!avrcp_connection){
802         log_error("avrcp_browsing_controller_get_item_attributes: could not find a connection.");
803         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
804     }
805     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
806     if (connection->state != AVCTP_CONNECTION_OPENED){
807         log_error("avrcp_browsing_controller_get_item_attributes: connection in wrong state %d, expected %d.", connection->state, AVCTP_CONNECTION_OPENED);
808         return ERROR_CODE_COMMAND_DISALLOWED;
809     }
810 
811     connection->get_item_attributes = 1;
812     connection->scope = scope;
813     memcpy(connection->folder_uid, uid, 8);
814     connection->uid_counter = uid_counter;
815     connection->attr_bitmap = attr_bitmap;
816 
817     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
818     return ERROR_CODE_SUCCESS;
819 }
820 
821 /**
822  * @brief Retrieve a listing of the contents of a folder.
823  * @param scope    0-player list, 1-virtual file system, 2-search, 3-now playing
824  * @param start_item
825  * @param end_item
826  * @param attribute_count
827  * @param attribute_list
828  **/
829 static uint8_t avrcp_browsing_controller_get_folder_items(uint16_t avrcp_browsing_cid, avrcp_browsing_scope_t scope, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
830     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
831     if (!avrcp_connection){
832         log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
833         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
834     }
835     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
836     if (connection->state != AVCTP_CONNECTION_OPENED) {
837         log_error("avrcp_browsing_controller_get_folder_items: connection in wrong state %d, expected %d.", connection->state, AVCTP_CONNECTION_OPENED);
838         return ERROR_CODE_COMMAND_DISALLOWED;
839     }
840 
841     connection->get_folder_items = 1;
842     connection->scope = scope;
843     connection->start_item = start_item;
844     connection->end_item = end_item;
845     connection->attr_bitmap = attr_bitmap;
846 
847     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
848     return ERROR_CODE_SUCCESS;
849 }
850 
851 uint8_t avrcp_browsing_controller_get_media_players(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
852     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_LIST, start_item, end_item, attr_bitmap);
853 }
854 
855 uint8_t avrcp_browsing_controller_browse_file_system(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
856     // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 1, 0, 0xFFFFFFFF, attr_bitmap);
857     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_VIRTUAL_FILESYSTEM, start_item, end_item, attr_bitmap);
858 }
859 
860 uint8_t avrcp_browsing_controller_browse_media(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
861     // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 2, 0, 0xFFFFFFFF, 0, NULL);
862     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_SEARCH, start_item, end_item, attr_bitmap);
863 }
864 
865 uint8_t avrcp_browsing_controller_browse_now_playing_list(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
866     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_NOW_PLAYING, start_item, end_item, attr_bitmap);
867 }
868 
869 
870 uint8_t avrcp_browsing_controller_set_browsed_player(uint16_t avrcp_browsing_cid, uint16_t browsed_player_id){
871     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
872     if (!avrcp_connection){
873         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
874         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
875     }
876 
877     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
878     if (connection->state != AVCTP_CONNECTION_OPENED){
879         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
880         return ERROR_CODE_COMMAND_DISALLOWED;
881     }
882 
883     connection->set_browsed_player_id = 1;
884     connection->browsed_player_id = browsed_player_id;
885     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
886     return ERROR_CODE_SUCCESS;
887 }
888 
889 /**
890  * @brief Retrieve a listing of the contents of a folder.
891  * @param direction     0-folder up, 1-folder down
892  * @param folder_uid    8 bytes long
893  **/
894 uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8_t direction, uint8_t * folder_uid){
895     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
896     if (!avrcp_connection){
897         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
898         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
899     }
900 
901     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
902 
903     if (!connection || connection->state != AVCTP_CONNECTION_OPENED){
904         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
905         return ERROR_CODE_COMMAND_DISALLOWED;
906     }
907 
908     if (!connection->browsed_player_id){
909         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
910         return ERROR_CODE_COMMAND_DISALLOWED;
911     }
912     connection->change_path = 1;
913     connection->direction = direction;
914     memset(connection->folder_uid, 0, 8);
915     if (folder_uid){
916         memcpy(connection->folder_uid, folder_uid, 8);
917     }
918 
919     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
920     return ERROR_CODE_SUCCESS;
921 }
922 
923 uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid){
924     return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 0, NULL);
925 }
926 
927 uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid){
928     return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 1, folder_uid);
929 }
930 
931 uint8_t avrcp_browsing_controller_search(uint16_t avrcp_browsing_cid, uint16_t search_str_len, char * search_str){
932     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
933     if (!avrcp_connection){
934         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
935         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
936     }
937 
938     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
939 
940     if (!connection || connection->state != AVCTP_CONNECTION_OPENED){
941         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
942         return ERROR_CODE_COMMAND_DISALLOWED;
943     }
944 
945     if (!connection->browsed_player_id){
946         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
947         return ERROR_CODE_COMMAND_DISALLOWED;
948     }
949     if (!search_str || search_str_len == 0){
950         return AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND;
951     }
952 
953     connection->search = 1;
954 
955     connection->search_str_len = btstack_min(search_str_len, sizeof(connection->search_str)-1);
956     memset(connection->search_str, 0, sizeof(connection->search_str));
957     memcpy(connection->search_str, search_str, connection->search_str_len);
958     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
959     return ERROR_CODE_SUCCESS;
960 }
961 
962 uint8_t avrcp_browsing_controller_get_total_nr_items_for_scope(uint16_t avrcp_browsing_cid, avrcp_browsing_scope_t scope){
963     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
964     if (!avrcp_connection){
965         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
966         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
967     }
968 
969     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
970 
971     if (!connection || connection->state != AVCTP_CONNECTION_OPENED){
972         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
973         return ERROR_CODE_COMMAND_DISALLOWED;
974     }
975 
976     if (!connection->browsed_player_id){
977         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
978         return ERROR_CODE_COMMAND_DISALLOWED;
979     }
980     connection->get_total_nr_items = 1;
981     connection->get_total_nr_items_scope = scope;
982     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
983     return ERROR_CODE_SUCCESS;
984 }
985