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