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