xref: /btstack/src/classic/avrcp_browsing_controller.c (revision 4783d25609a5032739e1b6e67d2236f2d80f2100)
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_browsing.h"
47 #include "classic/avrcp_browsing_controller.h"
48 
49 
50 static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
51 
52 static int avrcp_browsing_controller_send_get_folder_items_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
53     uint8_t command[100];
54     int pos = 0;
55     // transport header
56     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
57     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
58     // Profile IDentifier (PID)
59     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
60     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
61     command[pos++] = AVRCP_PDU_ID_GET_FOLDER_ITEMS;
62 
63     uint32_t attribute_count = 0;
64     uint32_t attributes_to_copy = 0;
65 
66     switch (connection->attr_bitmap){
67         case AVRCP_MEDIA_ATTR_NONE:
68             attribute_count = AVRCP_MEDIA_ATTR_NONE; // 0xFFFFFFFF
69             break;
70         case AVRCP_MEDIA_ATTR_ALL:
71             attribute_count = AVRCP_MEDIA_ATTR_ALL;  // 0
72             break;
73         default:
74             attribute_count    = count_set_bits_uint32(connection->attr_bitmap & 0xff);
75             attributes_to_copy = attribute_count;
76             break;
77     }
78     big_endian_store_16(command, pos, 9 + 1 + (attribute_count*4));
79     pos += 2;
80 
81     command[pos++] = connection->scope;
82     big_endian_store_32(command, pos, connection->start_item);
83     pos += 4;
84     big_endian_store_32(command, pos, connection->end_item);
85     pos += 4;
86     command[pos++] = attribute_count;
87 
88     int bit_position = 1;
89     while (attributes_to_copy){
90         if (connection->attr_bitmap & (1 << bit_position)){
91             big_endian_store_32(command, pos, bit_position);
92             pos += 4;
93             attributes_to_copy--;
94         }
95         bit_position++;
96     }
97     return l2cap_send(cid, command, pos);
98 }
99 
100 
101 static int avrcp_browsing_controller_send_get_item_attributes_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
102     uint8_t command[100];
103     int pos = 0;
104     // transport header
105     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
106     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
107     // Profile IDentifier (PID)
108     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
109     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
110     command[pos++] = AVRCP_PDU_ID_GET_ITEM_ATTRIBUTES;
111 
112     uint32_t attribute_count;
113     uint32_t attributes_to_copy = 0;
114 
115     switch (connection->attr_bitmap){
116         case AVRCP_MEDIA_ATTR_NONE:
117         case AVRCP_MEDIA_ATTR_ALL:
118             attribute_count = 0;
119             break;
120         default:
121             attribute_count = count_set_bits_uint32(connection->attr_bitmap & 0xff);
122             attributes_to_copy = attribute_count;
123             break;
124     }
125 
126     big_endian_store_16(command, pos, 12 + (attribute_count*4));
127     pos += 2;
128 
129     command[pos++] = connection->scope;
130     (void)memcpy(command + pos, connection->folder_uid, 8);
131     pos += 8;
132     big_endian_store_16(command, pos, connection->uid_counter);
133     pos += 2;
134     command[pos++] = attribute_count;
135 
136     int bit_position = 1;
137     while (attributes_to_copy){
138         if (connection->attr_bitmap & (1 << bit_position)){
139             big_endian_store_32(command, pos, bit_position);
140             pos += 4;
141             attributes_to_copy--;
142         }
143         bit_position++;
144     }
145 
146     return l2cap_send(cid, command, pos);
147 }
148 
149 
150 static int avrcp_browsing_controller_send_change_path_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
151     uint8_t command[100];
152     int pos = 0;
153     // transport header
154     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
155     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
156     // Profile IDentifier (PID)
157     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
158     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
159     command[pos++] = AVRCP_PDU_ID_CHANGE_PATH;
160 
161     big_endian_store_16(command, pos, 11);
162     pos += 2;
163     pos += 2;
164     command[pos++] = connection->direction;
165     (void)memcpy(command + pos, connection->folder_uid, 8);
166     pos += 8;
167     return l2cap_send(cid, command, pos);
168 }
169 
170 static int avrcp_browsing_controller_send_search_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
171     uint8_t command[100];
172     int pos = 0;
173     // transport header
174     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
175     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
176     // Profile IDentifier (PID)
177     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
178     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
179     command[pos++] = AVRCP_PDU_ID_SEARCH;
180 
181     big_endian_store_16(command, pos, 4 + connection->search_str_len);
182     pos += 2;
183 
184     big_endian_store_16(command, pos, 0x006A);
185     pos += 2;
186     big_endian_store_16(command, pos, connection->search_str_len);
187     pos += 2;
188 
189     (void)memcpy(command + pos, connection->search_str,
190                  connection->search_str_len);
191     pos += connection->search_str_len;
192     return l2cap_send(cid, command, pos);
193 }
194 
195 static int avrcp_browsing_controller_send_set_browsed_player_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
196     uint8_t command[100];
197     int pos = 0;
198     // transport header
199     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
200     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
201     // Profile IDentifier (PID)
202     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
203     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
204     command[pos++] = AVRCP_PDU_ID_SET_BROWSED_PLAYER;
205 
206     big_endian_store_16(command, pos, 2);
207     pos += 2;
208     big_endian_store_16(command, pos, connection->browsed_player_id);
209     pos += 2;
210     return l2cap_send(cid, command, pos);
211 }
212 
213 static int avrcp_browsing_controller_send_get_total_nr_items_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
214     uint8_t command[7];
215     int pos = 0;
216     // transport header
217     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
218     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
219     // Profile IDentifier (PID)
220     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
221     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
222     command[pos++] = AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
223 
224     big_endian_store_16(command, pos, 1);
225     pos += 2;
226     command[pos++] = connection->get_total_nr_items_scope;
227     return l2cap_send(cid, command, pos);
228 }
229 
230 static void avrcp_browsing_controller_handle_can_send_now(avrcp_browsing_connection_t * connection){
231     switch (connection->state){
232         case AVCTP_CONNECTION_OPENED:
233             if (connection->set_browsed_player_id){
234                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
235                 connection->set_browsed_player_id = 0;
236                 avrcp_browsing_controller_send_set_browsed_player_cmd(connection->l2cap_browsing_cid, connection);
237                 break;
238             }
239 
240             if (connection->get_total_nr_items){
241                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
242                 connection->get_total_nr_items = 0;
243                 avrcp_browsing_controller_send_get_total_nr_items_cmd(connection->l2cap_browsing_cid, connection);
244                 break;
245             }
246 
247             if (connection->get_folder_items){
248                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
249                 connection->get_folder_items = 0;
250                 avrcp_browsing_controller_send_get_folder_items_cmd(connection->l2cap_browsing_cid, connection);
251                 break;
252             }
253 
254             if (connection->get_item_attributes){
255                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
256                 connection->get_item_attributes = 0;
257                 avrcp_browsing_controller_send_get_item_attributes_cmd(connection->l2cap_browsing_cid, connection);
258                 break;
259             }
260 
261             if (connection->change_path){
262                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
263                 connection->change_path = 0;
264                 avrcp_browsing_controller_send_change_path_cmd(connection->l2cap_browsing_cid, connection);
265                 break;
266             }
267 
268             if (connection->search){
269                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
270                 connection->search = 0;
271                 avrcp_browsing_controller_send_search_cmd(connection->l2cap_browsing_cid, connection);
272                 break;
273             }
274             break;
275         default:
276             return;
277     }
278 }
279 
280 
281 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){
282     btstack_assert(callback != NULL);
283 
284     uint8_t event[9];
285     int pos = 0;
286     event[pos++] = HCI_EVENT_AVRCP_META;
287     event[pos++] = sizeof(event) - 2;
288     event[pos++] = AVRCP_SUBEVENT_BROWSING_DONE;
289     little_endian_store_16(event, pos, browsing_cid);
290     pos += 2;
291     little_endian_store_16(event, pos, uid_counter);
292     pos += 2;
293     event[pos++] = browsing_status;
294     event[pos++] = bluetooth_status;
295     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
296 }
297 
298 static void avrcp_parser_reset(avrcp_browsing_connection_t * connection){
299     connection->parser_attribute_header_pos = 0;
300     connection->parsed_attribute_value_offset = 0;
301     connection->parsed_num_attributes = 0;
302     connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
303 }
304 
305 
306 static void avrcp_browsing_parser_process_byte(uint8_t byte, avrcp_browsing_connection_t * connection){
307     uint8_t prepended_header_size = 1;
308     uint16_t attribute_total_value_len;
309 
310     switch(connection->parser_state){
311         case AVRCP_PARSER_GET_ATTRIBUTE_HEADER:
312             connection->parser_attribute_header[connection->parser_attribute_header_pos++] = byte;
313             if (connection->parser_attribute_header_pos < AVRCP_BROWSING_ITEM_HEADER_LEN) break;
314 
315             attribute_total_value_len = big_endian_read_16(connection->parser_attribute_header, 1);
316             connection->parsed_attribute_value[connection->parsed_attribute_value_offset++] = connection->parser_attribute_header[0];   // prepend with item type
317             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
318             connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_VALUE;
319             break;
320 
321         case AVRCP_PARSER_GET_ATTRIBUTE_VALUE:
322             connection->parsed_attribute_value[connection->parsed_attribute_value_offset++] = byte;
323             if (connection->parsed_attribute_value_offset < (connection->parsed_attribute_value_len + prepended_header_size)){
324                 break;
325             }
326             if (connection->parsed_attribute_value_offset < big_endian_read_16(connection->parser_attribute_header, 1)){
327                 connection->parser_state = AVRCP_PARSER_IGNORE_REST_OF_ATTRIBUTE_VALUE;
328                 break;
329             }
330             connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
331             (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, connection->l2cap_browsing_cid, &connection->parsed_attribute_value[0], connection->parsed_attribute_value_offset);
332             connection->parsed_num_attributes++;
333             connection->parsed_attribute_value_offset = 0;
334             connection->parser_attribute_header_pos = 0;
335 
336             if (connection->parsed_num_attributes == connection->num_items){
337                 avrcp_parser_reset(connection);
338                 break;
339             }
340             break;
341 
342         case AVRCP_PARSER_IGNORE_REST_OF_ATTRIBUTE_VALUE:
343             connection->parsed_attribute_value_offset++;
344             if (connection->parsed_attribute_value_offset < (big_endian_read_16(connection->parser_attribute_header, 1) + prepended_header_size)){
345                 break;
346             }
347             connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
348             (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, connection->l2cap_browsing_cid, &connection->parsed_attribute_value[0], connection->parsed_attribute_value_offset);
349             connection->parsed_num_attributes++;
350             connection->parsed_attribute_value_offset = 0;
351             connection->parser_attribute_header_pos = 0;
352 
353             if (connection->parsed_num_attributes == connection->num_items){
354                 avrcp_parser_reset(connection);
355                 break;
356             }
357             break;
358         default:
359             break;
360     }
361 }
362 
363 static void avrcp_browsing_parse_and_emit_element_attrs(uint8_t * packet, uint16_t num_bytes_to_read, avrcp_browsing_connection_t * connection){
364     int i;
365     for (i=0;i<num_bytes_to_read;i++){
366         avrcp_browsing_parser_process_byte(packet[i], connection);
367     }
368 }
369 
370 static void avrcp_browsing_controller_emit_failed(btstack_packet_handler_t callback, uint16_t browsing_cid, uint8_t browsing_status, uint8_t bluetooth_status){
371     avrcp_browsing_controller_emit_done_with_uid_counter(callback, browsing_cid, 0, browsing_status, bluetooth_status);
372 }
373 
374 
375 static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
376     avrcp_browsing_connection_t * browsing_connection;
377     uint8_t transport_header;
378     int pos;
379     switch (packet_type) {
380         case L2CAP_DATA_PACKET:
381             browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid_for_role(AVRCP_CONTROLLER, channel);
382             if (!browsing_connection) break;
383             pos = 0;
384             transport_header = packet[pos++];
385             // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
386             browsing_connection->transaction_label = transport_header >> 4;
387             avrcp_packet_type_t avctp_packet_type = (transport_header & 0x0F) >> 2;
388             switch (avctp_packet_type){
389                 case AVRCP_SINGLE_PACKET:
390                 case AVRCP_START_PACKET:
391                     pos += 2;
392                     browsing_connection->num_packets = 1;
393                     if (avctp_packet_type == AVRCP_START_PACKET){
394                         browsing_connection->num_packets = packet[pos++];
395                     }
396                     if ((pos + 4) > size){
397                         browsing_connection->state = AVCTP_CONNECTION_OPENED;
398                         avrcp_browsing_controller_emit_failed(avrcp_controller_context.browsing_avrcp_callback, channel, AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND, ERROR_CODE_SUCCESS);
399                         return;
400                     }
401                     browsing_connection->pdu_id = packet[pos++];
402                     pos += 2;
403                     browsing_connection->browsing_status = packet[pos++];
404                     if (browsing_connection->browsing_status != AVRCP_BROWSING_ERROR_CODE_SUCCESS){
405                         browsing_connection->state = AVCTP_CONNECTION_OPENED;
406                         avrcp_browsing_controller_emit_failed(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_connection->browsing_status, ERROR_CODE_SUCCESS);
407                         return;
408                     }
409                     break;
410                 default:
411                     break;
412             }
413 
414             uint32_t i;
415             uint8_t folder_depth;
416 
417             switch(browsing_connection->pdu_id){
418                 case AVRCP_PDU_ID_CHANGE_PATH:
419                     break;
420                 case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER:
421                     break;
422                 case AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS:
423                     break;
424                 case AVRCP_PDU_ID_SET_BROWSED_PLAYER:
425                     browsing_connection->uid_counter =  big_endian_read_16(packet, pos);
426                     pos += 2;
427                     // num_items
428                     pos += 4;
429                     // charset
430                     pos += 2;
431                     folder_depth = packet[pos++];
432 
433                     for (i = 0; i < folder_depth; i++){
434                         uint16_t folder_name_length = big_endian_read_16(packet, pos);
435                         pos += 2;
436                         // reuse packet and add data type as a header
437                         packet[pos-1] = AVRCP_BROWSING_MEDIA_ROOT_FOLDER;
438                         (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos-1, folder_name_length+1);
439                         pos += folder_name_length;
440                     }
441                     break;
442 
443                 case AVRCP_PDU_ID_GET_FOLDER_ITEMS:{
444                     switch (avctp_packet_type){
445                         case AVRCP_SINGLE_PACKET:
446                         case AVRCP_START_PACKET:
447                             avrcp_parser_reset(browsing_connection);
448                             browsing_connection->uid_counter =  big_endian_read_16(packet, pos);
449                             pos += 2;
450                             browsing_connection->num_items = big_endian_read_16(packet, pos); //num_items
451                             pos += 2;
452                             avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection);
453                             break;
454 
455                         case AVRCP_CONTINUE_PACKET:
456                             avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection);
457                             break;
458 
459                         case AVRCP_END_PACKET:
460                             avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection);
461                             avrcp_parser_reset(browsing_connection);
462                             break;
463                         default:
464                             break;
465                     }
466                     break;
467                 }
468                 case AVRCP_PDU_ID_SEARCH:
469                     browsing_connection->uid_counter =  big_endian_read_16(packet, pos);
470                     pos += 2;
471                     break;
472                 case AVRCP_PDU_ID_GET_ITEM_ATTRIBUTES:
473                     packet[pos-1] = AVRCP_BROWSING_MEDIA_ELEMENT_ITEM_ATTRIBUTE;
474                     (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos-1, size - pos + 1);
475                     break;
476                 default:
477                     log_info(" not parsed pdu ID 0x%02x", browsing_connection->pdu_id);
478                     break;
479             }
480 
481             switch (avctp_packet_type){
482                 case AVRCP_SINGLE_PACKET:
483                 case AVRCP_END_PACKET:
484                     browsing_connection->state = AVCTP_CONNECTION_OPENED;
485                     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);
486                     break;
487                 default:
488                     break;
489             }
490             break;
491 
492         case HCI_EVENT_PACKET:
493             switch (hci_event_packet_get_type(packet)){
494                 case L2CAP_EVENT_CAN_SEND_NOW:
495                     browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid_for_role(AVRCP_CONTROLLER,channel);
496                     avrcp_browsing_controller_handle_can_send_now(browsing_connection);
497                     break;
498                 default:
499                     break;
500             }
501             break;
502 
503         default:
504             break;
505     }
506 }
507 
508 void avrcp_browsing_controller_init(void){
509     avrcp_controller_context.browsing_packet_handler = avrcp_browsing_controller_packet_handler;
510     avrcp_browsing_register_controller_packet_handler(avrcp_browsing_controller_packet_handler);
511 }
512 
513 void avrcp_browsing_controller_register_packet_handler(btstack_packet_handler_t callback){
514     btstack_assert(callback != NULL);
515     avrcp_controller_context.browsing_avrcp_callback = callback;
516 }
517 
518 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){
519     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
520     if (!avrcp_connection){
521         log_error("avrcp_browsing_controller_get_item_attributes: could not find a connection.");
522         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
523     }
524     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
525     if (connection->state != AVCTP_CONNECTION_OPENED){
526         log_error("avrcp_browsing_controller_get_item_attributes: connection in wrong state %d, expected %d.", connection->state, AVCTP_CONNECTION_OPENED);
527         return ERROR_CODE_COMMAND_DISALLOWED;
528     }
529 
530     connection->get_item_attributes = 1;
531     connection->scope = scope;
532     (void)memcpy(connection->folder_uid, uid, 8);
533     connection->uid_counter = uid_counter;
534     connection->attr_bitmap = attr_bitmap;
535 
536     avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
537     return ERROR_CODE_SUCCESS;
538 }
539 
540 /**
541  * @brief Retrieve a listing of the contents of a folder.
542  * @param scope    0-player list, 1-virtual file system, 2-search, 3-now playing
543  * @param start_item
544  * @param end_item
545  * @param attribute_count
546  * @param attribute_list
547  **/
548 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){
549     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
550     if (!avrcp_connection){
551         log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
552         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
553     }
554     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
555     if (connection->state != AVCTP_CONNECTION_OPENED) {
556         log_error("avrcp_browsing_controller_get_folder_items: connection in wrong state %d, expected %d.", connection->state, AVCTP_CONNECTION_OPENED);
557         return ERROR_CODE_COMMAND_DISALLOWED;
558     }
559 
560     connection->get_folder_items = 1;
561     connection->scope = scope;
562     connection->start_item = start_item;
563     connection->end_item = end_item;
564     connection->attr_bitmap = attr_bitmap;
565 
566     avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
567     return ERROR_CODE_SUCCESS;
568 }
569 
570 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){
571     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_LIST, start_item, end_item, attr_bitmap);
572 }
573 
574 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){
575     // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 1, 0, 0xFFFFFFFF, attr_bitmap);
576     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_VIRTUAL_FILESYSTEM, start_item, end_item, attr_bitmap);
577 }
578 
579 uint8_t avrcp_browsing_controller_browse_media(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
580     // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 2, 0, 0xFFFFFFFF, 0, NULL);
581     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_SEARCH, start_item, end_item, attr_bitmap);
582 }
583 
584 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){
585     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_NOW_PLAYING, start_item, end_item, attr_bitmap);
586 }
587 
588 
589 uint8_t avrcp_browsing_controller_set_browsed_player(uint16_t avrcp_browsing_cid, uint16_t browsed_player_id){
590     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
591     if (!avrcp_connection){
592         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
593         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
594     }
595 
596     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
597     if (connection->state != AVCTP_CONNECTION_OPENED){
598         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
599         return ERROR_CODE_COMMAND_DISALLOWED;
600     }
601 
602     connection->set_browsed_player_id = 1;
603     connection->browsed_player_id = browsed_player_id;
604     avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
605     return ERROR_CODE_SUCCESS;
606 }
607 
608 /**
609  * @brief Retrieve a listing of the contents of a folder.
610  * @param direction     0-folder up, 1-folder down
611  * @param folder_uid    8 bytes long
612  **/
613 uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8_t direction, uint8_t * folder_uid){
614     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
615     if (!avrcp_connection){
616         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
617         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
618     }
619 
620     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
621 
622     if ((connection == NULL) || (connection->state != AVCTP_CONNECTION_OPENED)){
623         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
624         return ERROR_CODE_COMMAND_DISALLOWED;
625     }
626 
627     if (!connection->browsed_player_id){
628         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
629         return ERROR_CODE_COMMAND_DISALLOWED;
630     }
631     connection->change_path = 1;
632     connection->direction = direction;
633     memset(connection->folder_uid, 0, 8);
634     if (folder_uid){
635         (void)memcpy(connection->folder_uid, folder_uid, 8);
636     }
637 
638     avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
639     return ERROR_CODE_SUCCESS;
640 }
641 
642 uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid){
643     return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 0, NULL);
644 }
645 
646 uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid){
647     return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 1, folder_uid);
648 }
649 
650 uint8_t avrcp_browsing_controller_search(uint16_t avrcp_browsing_cid, uint16_t search_str_len, char * search_str){
651     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
652     if (!avrcp_connection){
653         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
654         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
655     }
656 
657     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
658 
659     if ((connection == NULL) || (connection->state != AVCTP_CONNECTION_OPENED)){
660         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
661         return ERROR_CODE_COMMAND_DISALLOWED;
662     }
663 
664     if (!connection->browsed_player_id){
665         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
666         return ERROR_CODE_COMMAND_DISALLOWED;
667     }
668     if (!search_str || (search_str_len == 0)){
669         return AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND;
670     }
671 
672     connection->search = 1;
673 
674     connection->search_str_len = btstack_min(search_str_len, sizeof(connection->search_str)-1);
675     memset(connection->search_str, 0, sizeof(connection->search_str));
676     (void)memcpy(connection->search_str, search_str,
677                  connection->search_str_len);
678     avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
679     return ERROR_CODE_SUCCESS;
680 }
681 
682 uint8_t avrcp_browsing_controller_get_total_nr_items_for_scope(uint16_t avrcp_browsing_cid, avrcp_browsing_scope_t scope){
683     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
684     if (!avrcp_connection){
685         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
686         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
687     }
688 
689     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
690 
691     if ((connection == NULL) || (connection->state != AVCTP_CONNECTION_OPENED)){
692         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
693         return ERROR_CODE_COMMAND_DISALLOWED;
694     }
695 
696     if (!connection->browsed_player_id){
697         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
698         return ERROR_CODE_COMMAND_DISALLOWED;
699     }
700     connection->get_total_nr_items = 1;
701     connection->get_total_nr_items_scope = scope;
702     avrcp_browsing_request_can_send_now(connection, connection->l2cap_browsing_cid);
703     return ERROR_CODE_SUCCESS;
704 }
705