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