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