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