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