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