xref: /btstack/src/classic/avrcp_browsing_controller.c (revision 64697164ef72f7897f172a22b7b13afea33d105c)
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 
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 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 avrcp_connection_t * get_avrcp_connection_for_browsing_cid(uint16_t browsing_cid, avrcp_context_t * context){
55     btstack_linked_list_iterator_t it;
56     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
57     while (btstack_linked_list_iterator_has_next(&it)){
58         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
59         if (connection->avrcp_browsing_cid != browsing_cid) continue;
60         return connection;
61     }
62     return NULL;
63 }
64 
65 static avrcp_connection_t * get_avrcp_connection_for_browsing_l2cap_cid(uint16_t browsing_l2cap_cid, avrcp_context_t * context){
66     btstack_linked_list_iterator_t it;
67     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
68     while (btstack_linked_list_iterator_has_next(&it)){
69         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
70         if (connection->browsing_connection &&  connection->browsing_connection->l2cap_browsing_cid != browsing_l2cap_cid) continue;
71         return connection;
72     }
73     return NULL;
74 }
75 
76 static avrcp_browsing_connection_t * get_avrcp_browsing_connection_for_l2cap_cid(uint16_t l2cap_cid, avrcp_context_t * context){
77     btstack_linked_list_iterator_t it;
78     btstack_linked_list_iterator_init(&it, (btstack_linked_list_t *)  &context->connections);
79     while (btstack_linked_list_iterator_has_next(&it)){
80         avrcp_connection_t * connection = (avrcp_connection_t *)btstack_linked_list_iterator_next(&it);
81         if (connection->browsing_connection && connection->browsing_connection->l2cap_browsing_cid != l2cap_cid) continue;
82         return connection->browsing_connection;
83     }
84     return NULL;
85 }
86 
87 static void avrcp_emit_browsing_connection_established(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr, uint8_t status){
88     if (!callback) return;
89     uint8_t event[12];
90     int pos = 0;
91     event[pos++] = HCI_EVENT_AVRCP_META;
92     event[pos++] = sizeof(event) - 2;
93     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_ESTABLISHED;
94     event[pos++] = status;
95     reverse_bd_addr(addr,&event[pos]);
96     pos += 6;
97     little_endian_store_16(event, pos, browsing_cid);
98     pos += 2;
99     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
100 }
101 
102 static void avrcp_emit_incoming_browsing_connection(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr){
103     if (!callback) return;
104     uint8_t event[11];
105     int pos = 0;
106     event[pos++] = HCI_EVENT_AVRCP_META;
107     event[pos++] = sizeof(event) - 2;
108     event[pos++] = AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION;
109     reverse_bd_addr(addr,&event[pos]);
110     pos += 6;
111     little_endian_store_16(event, pos, browsing_cid);
112     pos += 2;
113     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
114 }
115 
116 static void avrcp_emit_browsing_connection_closed(btstack_packet_handler_t callback, uint16_t browsing_cid){
117     if (!callback) return;
118     uint8_t event[5];
119     int pos = 0;
120     event[pos++] = HCI_EVENT_AVRCP_META;
121     event[pos++] = sizeof(event) - 2;
122     event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_RELEASED;
123     little_endian_store_16(event, pos, browsing_cid);
124     pos += 2;
125     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
126 }
127 
128 static avrcp_browsing_connection_t * avrcp_browsing_create_connection(avrcp_connection_t * avrcp_connection){
129     avrcp_browsing_connection_t * connection = btstack_memory_avrcp_browsing_connection_get();
130     memset(connection, 0, sizeof(avrcp_browsing_connection_t));
131     connection->state = AVCTP_CONNECTION_IDLE;
132     connection->transaction_label = 0xFF;
133     avrcp_connection->avrcp_browsing_cid = avrcp_get_next_cid();
134     avrcp_connection->browsing_connection = connection;
135     return connection;
136 }
137 
138 static uint8_t avrcp_browsing_connect(bd_addr_t remote_addr, avrcp_context_t * context, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config, uint16_t * browsing_cid){
139     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_bd_addr(remote_addr, context);
140 
141     if (!avrcp_connection){
142         log_error("avrcp: there is no previously established AVRCP controller connection.");
143         return ERROR_CODE_COMMAND_DISALLOWED;
144     }
145 
146     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
147     if (connection){
148         log_error(" avrcp_browsing_connect connection exists.");
149         return ERROR_CODE_SUCCESS;
150     }
151 
152     connection = avrcp_browsing_create_connection(avrcp_connection);
153     if (!connection){
154         log_error("avrcp: could not allocate connection struct.");
155         return BTSTACK_MEMORY_ALLOC_FAILED;
156     }
157 
158     if (!browsing_cid) return L2CAP_LOCAL_CID_DOES_NOT_EXIST;
159 
160     *browsing_cid = avrcp_connection->avrcp_browsing_cid;
161     connection->ertm_buffer = ertm_buffer;
162     connection->ertm_buffer_size = size;
163     avrcp_connection->browsing_connection = connection;
164 
165     memcpy(&connection->ertm_config, ertm_config, sizeof(l2cap_ertm_config_t));
166 
167     return l2cap_create_ertm_channel(avrcp_browsing_controller_packet_handler, remote_addr, avrcp_connection->browsing_l2cap_psm,
168                     &connection->ertm_config, connection->ertm_buffer, connection->ertm_buffer_size, NULL);
169 
170 }
171 
172 void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context){
173     UNUSED(channel);
174     UNUSED(size);
175     bd_addr_t event_addr;
176     uint16_t local_cid;
177     uint8_t  status;
178     avrcp_browsing_connection_t * browsing_connection = NULL;
179     avrcp_connection_t * avrcp_connection = NULL;
180 
181     if (packet_type != HCI_EVENT_PACKET) return;
182 
183     switch (hci_event_packet_get_type(packet)) {
184         case HCI_EVENT_DISCONNECTION_COMPLETE:
185             avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, 0);
186             break;
187         case L2CAP_EVENT_INCOMING_CONNECTION:
188             l2cap_event_incoming_connection_get_address(packet, event_addr);
189             local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
190             avrcp_connection = get_avrcp_connection_for_bd_addr(event_addr, context);
191             if (!avrcp_connection) {
192                 log_error("No previously created AVRCP controller connections");
193                 l2cap_decline_connection(local_cid);
194                 break;
195             }
196             browsing_connection = avrcp_browsing_create_connection(avrcp_connection);
197             browsing_connection->l2cap_browsing_cid = local_cid;
198             browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION;
199             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);
200             avrcp_emit_incoming_browsing_connection(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr);
201             break;
202 
203         case L2CAP_EVENT_CHANNEL_OPENED:
204             l2cap_event_channel_opened_get_address(packet, event_addr);
205             status = l2cap_event_channel_opened_get_status(packet);
206             local_cid = l2cap_event_channel_opened_get_local_cid(packet);
207 
208             avrcp_connection = get_avrcp_connection_for_bd_addr(event_addr, context);
209             if (!avrcp_connection){
210                 log_error("Failed to find AVRCP connection for bd_addr %s", bd_addr_to_str(event_addr));
211                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, local_cid, event_addr, L2CAP_LOCAL_CID_DOES_NOT_EXIST);
212                 l2cap_disconnect(local_cid, 0); // reason isn't used
213                 break;
214             }
215 
216             browsing_connection = avrcp_connection->browsing_connection;
217             if (status != ERROR_CODE_SUCCESS){
218                 log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status);
219                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, status);
220                 btstack_memory_avrcp_browsing_connection_free(browsing_connection);
221                 avrcp_connection->browsing_connection = NULL;
222                 break;
223             }
224             if (browsing_connection->state != AVCTP_CONNECTION_W4_L2CAP_CONNECTED) break;
225 
226             browsing_connection->l2cap_browsing_cid = local_cid;
227 
228             log_info("L2CAP_EVENT_CHANNEL_OPENED browsing cid 0x%02x, l2cap cid 0x%02x", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid);
229             browsing_connection->state = AVCTP_CONNECTION_OPENED;
230             avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, ERROR_CODE_SUCCESS);
231             break;
232 
233         case L2CAP_EVENT_CHANNEL_CLOSED:
234             // data: event (8), len(8), channel (16)
235             local_cid = l2cap_event_channel_closed_get_local_cid(packet);
236             avrcp_connection = get_avrcp_connection_for_browsing_l2cap_cid(local_cid, context);
237 
238             if (avrcp_connection && avrcp_connection->browsing_connection){
239                 avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid);
240                 // free connection
241                 btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
242                 avrcp_connection->browsing_connection = NULL;
243                 break;
244             }
245             break;
246         default:
247             break;
248     }
249 }
250 
251 static int avrcp_browsing_controller_send_get_folder_items_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
252     uint8_t command[100];
253     int pos = 0;
254     // transport header
255     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
256     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
257     // Profile IDentifier (PID)
258     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
259     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
260     command[pos++] = AVRCP_PDU_ID_GET_FOLDER_ITEMS;
261 
262     uint32_t attribute_count = 0;
263     uint32_t attributes_to_copy = 0;
264 
265     switch (connection->attr_bitmap){
266         case AVRCP_MEDIA_ATTR_NONE:
267             attribute_count = AVRCP_MEDIA_ATTR_NONE; // 0xFFFFFFFF
268             break;
269         case AVRCP_MEDIA_ATTR_ALL:
270             attribute_count = AVRCP_MEDIA_ATTR_ALL;  // 0
271             break;
272         default:
273             attribute_count = count_set_bits_uint32(connection->attr_bitmap & 0xff);
274             attributes_to_copy = attribute_count;
275             break;
276     }
277 
278     big_endian_store_16(command, pos, 10 + attribute_count);
279     pos += 2;
280     command[pos++] = connection->scope;
281     big_endian_store_32(command, pos, connection->start_item);
282     pos += 4;
283     big_endian_store_32(command, pos, connection->end_item);
284     pos += 4;
285     command[pos++] = attribute_count;
286 
287     int bit_position = 1;
288     while (attributes_to_copy){
289         if (connection->attr_bitmap & (1 << bit_position)){
290             big_endian_store_32(command, pos, bit_position);
291             pos += 4;
292             attributes_to_copy--;
293         }
294         bit_position++;
295     }
296 
297     return l2cap_send(cid, command, pos);
298 }
299 
300 static int avrcp_browsing_controller_send_change_path_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
301     uint8_t command[100];
302     int pos = 0;
303     // transport header
304     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
305     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
306     // Profile IDentifier (PID)
307     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
308     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
309     command[pos++] = AVRCP_PDU_ID_CHANGE_PATH;
310 
311     big_endian_store_16(command, pos, 11);
312     pos += 2;
313     big_endian_store_16(command, pos, connection->browsed_player_uid_counter);
314     pos += 2;
315     command[pos++] = connection->direction;
316     memcpy(command+pos, connection->folder_uid, 8);
317     pos += 8;
318     return l2cap_send(cid, command, pos);
319 }
320 
321 static int avrcp_browsing_controller_send_set_browsed_player_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
322     uint8_t command[100];
323     int pos = 0;
324     // transport header
325     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
326     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
327     // Profile IDentifier (PID)
328     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
329     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
330     command[pos++] = AVRCP_PDU_ID_SET_BROWSED_PLAYER;
331 
332     big_endian_store_16(command, pos, 2);
333     pos += 2;
334     big_endian_store_16(command, pos, connection->browsed_player_id);
335     pos += 2;
336     return l2cap_send(cid, command, pos);
337 }
338 
339 static int avrcp_browsing_controller_send_set_addressed_player_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
340     uint8_t command[100];
341     int pos = 0;
342     // transport header
343     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
344     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
345     // Profile IDentifier (PID)
346     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
347     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
348     command[pos++] = AVRCP_PDU_ID_SET_ADDRESSED_PLAYER;
349 
350     big_endian_store_16(command, pos, 2);
351     pos += 2;
352     big_endian_store_16(command, pos, connection->addressed_player_id);
353     pos += 2;
354     return l2cap_send(cid, command, pos);
355 }
356 
357 static void avrcp_browsing_controller_handle_can_send_now(avrcp_browsing_connection_t * connection){
358     switch (connection->state){
359         case AVCTP_CONNECTION_OPENED:
360             if (connection->set_browsed_player_id){
361                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
362                 connection->set_browsed_player_id = 0;
363                 avrcp_browsing_controller_send_set_browsed_player_cmd(connection->l2cap_browsing_cid, connection);
364                 break;
365             }
366 
367             if (connection->set_addressed_player_id){
368                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
369                 connection->set_addressed_player_id = 0;
370                 avrcp_browsing_controller_send_set_addressed_player_cmd(connection->l2cap_browsing_cid, connection);
371                 break;
372             }
373 
374             if (connection->get_folder_item){
375                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
376                 connection->get_folder_item = 0;
377                 avrcp_browsing_controller_send_get_folder_items_cmd(connection->l2cap_browsing_cid, connection);
378                 break;
379             }
380             if (connection->change_path){
381                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
382                 connection->change_path = 0;
383                 avrcp_browsing_controller_send_change_path_cmd(connection->l2cap_browsing_cid, connection);
384                 break;
385             }
386 
387         default:
388             return;
389     }
390 }
391 
392 static void avrcp_browsing_controller_emit_done(btstack_packet_handler_t callback, uint16_t browsing_cid, uint8_t browsing_status, uint8_t bluetooth_status){
393     if (!callback) return;
394     uint8_t event[7];
395     int pos = 0;
396     event[pos++] = HCI_EVENT_AVRCP_META;
397     event[pos++] = sizeof(event) - 2;
398     event[pos++] = AVRCP_SUBEVENT_BROWSING_MEDIA_ITEM_DONE;
399     little_endian_store_16(event, pos, browsing_cid);
400     pos += 2;
401     event[pos++] = browsing_status;
402     event[pos++] = bluetooth_status;
403     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
404 }
405 
406 static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
407     avrcp_browsing_connection_t * browsing_connection;
408 
409     switch (packet_type) {
410         case L2CAP_DATA_PACKET:{
411             browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_controller_context);
412             if (!browsing_connection) break;
413             browsing_connection->state = AVCTP_CONNECTION_OPENED;
414 
415             // printf_hexdump(packet, size);
416             int pos = 0;
417             uint8_t transport_header = packet[pos++];
418             // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
419             // uint8_t transaction_label = transport_header >> 4;
420             avrcp_packet_type_t avctp_packet_type = (transport_header & 0x0F) >> 2;
421             // uint8_t frame_type = (transport_header & 0x03) >> 1;
422             // uint8_t ipid = transport_header & 0x01;
423             pos += 2;
424             browsing_connection->num_packets = 1;
425             switch (avctp_packet_type){
426                 case AVRCP_SINGLE_PACKET:
427                     break;
428                 case AVRCP_START_PACKET:
429                     browsing_connection->num_packets = packet[pos++];
430                     break;
431                 case AVRCP_CONTINUE_PACKET:
432                 case AVRCP_END_PACKET:
433                     // browsing_connection->num_packets = packet[pos++];
434                     break;
435             }
436 
437             if (pos + 4 > size){
438                 avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND, ERROR_CODE_SUCCESS);
439                 return;
440             }
441 
442             avrcp_pdu_id_t pdu_id = packet[pos++];
443             uint16_t length = big_endian_read_16(packet, pos);
444             pos += 2;
445             UNUSED(length);
446             // if (browsing_connection->num_packets > 1)
447             // if (browsing_connection->num_packets == 1 && (pos + length > size)){
448             //     printf("pos + length > size, %d, %d, %d \n", pos, length, size);
449             //     avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND, ERROR_CODE_SUCCESS);
450             //     return;
451             // }
452 
453             uint8_t browsing_status = packet[pos++];
454             if (browsing_status != AVRCP_BROWSING_ERROR_CODE_SUCCESS){
455                 printf("browsing_status %d\n", browsing_status);
456                 avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_status, ERROR_CODE_SUCCESS);
457                 return;
458             }
459 
460             uint32_t i;
461             switch(pdu_id){
462                 case AVRCP_PDU_ID_CHANGE_PATH:
463                     printf("AVRCP_PDU_ID_CHANGE_PATH \n");
464                     break;
465                 case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER:
466                     printf("AVRCP_PDU_ID_CHANGE_PATH \n");
467                     break;
468                 case AVRCP_PDU_ID_SET_BROWSED_PLAYER:{
469                     browsing_connection->browsed_player_uid_counter = big_endian_read_16(packet, pos);
470                     pos += 2;
471                     uint32_t num_items = big_endian_read_32(packet, pos);
472                     pos += 4;
473                     printf("AVRCP_PDU_ID_SET_BROWSED_PLAYER uuid counter 0x0%2x, num items %d\n", browsing_connection->browsed_player_uid_counter, num_items);
474 
475                     for (i = 0; i < num_items; i++){
476                         uint16_t browsable_item_length = 5 + big_endian_read_16(packet, pos+3);
477                         printf(" pos %d, len %d\n", pos, browsable_item_length);
478                         // reuse byte to put the new type AVRCP_BROWSING_MEDIA_ROOT_FOLDER
479                         packet[pos-1] = AVRCP_BROWSING_MEDIA_ROOT_FOLDER;
480                         (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos, browsable_item_length+1);
481                         pos += browsable_item_length;
482                     }
483                     break;
484                 }
485                 case AVRCP_PDU_ID_GET_FOLDER_ITEMS:{
486                     // uint16_t uid_counter = big_endian_read_16(packet, pos);
487                     pos += 2;
488                     uint16_t num_items = big_endian_read_16(packet, pos);
489                     pos += 2;
490                     for (i = 0; i < num_items; i++){
491                         uint16_t browsable_item_length = 3 + big_endian_read_16(packet, pos+1);
492                         (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos, browsable_item_length);
493                         pos += browsable_item_length;
494                     }
495                     break;
496                 }
497                 default:
498                     break;
499             }
500             switch (avctp_packet_type){
501                 case AVRCP_SINGLE_PACKET:
502                 case AVRCP_END_PACKET:
503                     avrcp_browsing_controller_emit_done(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_status, ERROR_CODE_SUCCESS);
504                     break;
505                 default:
506                     break;
507             }
508             break;
509         }
510         case HCI_EVENT_PACKET:
511             switch (hci_event_packet_get_type(packet)){
512                 case L2CAP_EVENT_CAN_SEND_NOW:
513                     browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid(channel, &avrcp_controller_context);
514                     if (!browsing_connection) break;
515                     avrcp_browsing_controller_handle_can_send_now(browsing_connection);
516                     break;
517             default:
518                 avrcp_browser_packet_handler(packet_type, channel, packet, size, &avrcp_controller_context);
519                 break;
520         }
521         default:
522             break;
523     }
524 }
525 
526 void avrcp_browsing_controller_init(void){
527     avrcp_controller_context.browsing_packet_handler = avrcp_browsing_controller_packet_handler;
528     l2cap_register_service(&avrcp_browsing_controller_packet_handler, PSM_AVCTP_BROWSING, 0xffff, LEVEL_0);
529 }
530 
531 void avrcp_browsing_controller_register_packet_handler(btstack_packet_handler_t callback){
532     if (callback == NULL){
533         log_error("avrcp_browsing_controller_register_packet_handler called with NULL callback");
534         return;
535     }
536     avrcp_controller_context.browsing_avrcp_callback = callback;
537 }
538 
539 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){
540     return avrcp_browsing_connect(bd_addr, &avrcp_controller_context, ertm_buffer, size, ertm_config, avrcp_browsing_cid);
541 }
542 
543 uint8_t avrcp_browsing_controller_disconnect(uint16_t avrcp_browsing_cid){
544     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
545     if (!avrcp_connection){
546         log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
547         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
548     }
549     if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
550 
551     l2cap_disconnect(avrcp_connection->browsing_connection->l2cap_browsing_cid, 0);
552     return ERROR_CODE_SUCCESS;
553 }
554 
555 uint8_t avrcp_avrcp_browsing_configure_incoming_connection(uint16_t avrcp_browsing_cid, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config){
556     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
557     if (!avrcp_connection){
558         log_error("avrcp_avrcp_browsing_decline_incoming_connection: could not find a connection.");
559         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
560     }
561     if (!avrcp_connection->browsing_connection){
562         log_error("avrcp_avrcp_browsing_decline_incoming_connection: no browsing connection.");
563         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
564     }
565 
566     if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_W4_ERTM_CONFIGURATION){
567         log_error("avrcp_avrcp_browsing_decline_incoming_connection: browsing connection in a wrong state.");
568         return ERROR_CODE_COMMAND_DISALLOWED;
569     }
570 
571     avrcp_connection->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
572     avrcp_connection->browsing_connection->ertm_buffer = ertm_buffer;
573     avrcp_connection->browsing_connection->ertm_buffer_size = size;
574     memcpy(&avrcp_connection->browsing_connection->ertm_config, ertm_config, sizeof(l2cap_ertm_config_t));
575     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);
576     return ERROR_CODE_SUCCESS;
577 }
578 
579 uint8_t avrcp_avrcp_browsing_decline_incoming_connection(uint16_t avrcp_browsing_cid){
580     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
581     if (!avrcp_connection){
582         log_error("avrcp_avrcp_browsing_decline_incoming_connection: could not find a connection.");
583         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
584     }
585     if (!avrcp_connection->browsing_connection) return ERROR_CODE_SUCCESS;
586     if (avrcp_connection->browsing_connection->state > AVCTP_CONNECTION_W4_ERTM_CONFIGURATION) return ERROR_CODE_COMMAND_DISALLOWED;
587 
588     l2cap_decline_connection(avrcp_connection->browsing_connection->l2cap_browsing_cid);
589     // free connection
590     btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
591     avrcp_connection->browsing_connection = NULL;
592     return ERROR_CODE_SUCCESS;
593 }
594 
595 /**
596  * @brief Retrieve a listing of the contents of a folder.
597  * @param scope    0-player list, 1-virtual file system, 2-search, 3-now playing
598  * @param start_item
599  * @param end_item
600  * @param attribute_count
601  * @param attribute_list
602  **/
603 static uint8_t avrcp_browsing_controller_get_folder_items(uint16_t avrcp_browsing_cid, uint8_t scope, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
604     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
605     if (!avrcp_connection){
606         log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
607         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
608     }
609     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
610     if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED;
611 
612     connection->get_folder_item = 1;
613     connection->scope = scope;
614     connection->start_item = start_item;
615     connection->end_item = end_item;
616     connection->attr_bitmap = attr_bitmap;
617 
618     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
619     return ERROR_CODE_SUCCESS;
620 }
621 
622 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){
623     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 0, start_item, end_item, attr_bitmap);
624 }
625 
626 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){
627     // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 1, 0, 0xFFFFFFFF, attr_bitmap);
628     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 1, start_item, end_item, attr_bitmap);
629 }
630 
631 uint8_t avrcp_browsing_controller_browse_media(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
632     // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 2, 0, 0xFFFFFFFF, 0, NULL);
633     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 2, start_item, end_item, attr_bitmap);
634 }
635 
636 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){
637     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 3, start_item, end_item, attr_bitmap);
638 }
639 
640 
641 uint8_t avrcp_browsing_controller_set_browsed_player(uint16_t avrcp_browsing_cid, uint16_t browsed_player_id){
642     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
643     if (!avrcp_connection){
644         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
645         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
646     }
647 
648     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
649     if (connection->state != AVCTP_CONNECTION_OPENED){
650         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
651         return ERROR_CODE_COMMAND_DISALLOWED;
652     }
653 
654     connection->set_browsed_player_id = 1;
655     connection->browsed_player_id = browsed_player_id;
656     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
657     return ERROR_CODE_SUCCESS;
658 }
659 
660 uint8_t avrcp_browsing_controller_set_addressed_player(uint16_t avrcp_browsing_cid, uint16_t addressed_player_id){
661     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
662     if (!avrcp_connection){
663         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
664         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
665     }
666 
667     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
668     if (!connection || 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     connection->set_addressed_player_id = 1;
674     connection->addressed_player_id = addressed_player_id;
675     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
676     return ERROR_CODE_SUCCESS;
677 }
678 
679 /**
680  * @brief Retrieve a listing of the contents of a folder.
681  * @param direction     0-folder up, 1-folder down
682  * @param folder_uid    8 bytes long
683  **/
684 uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8_t direction, uint8_t * folder_uid){
685     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid(avrcp_browsing_cid, &avrcp_controller_context);
686     if (!avrcp_connection){
687         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
688         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
689     }
690 
691     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
692 
693     if (!connection || connection->state != AVCTP_CONNECTION_OPENED || !folder_uid){
694         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
695         return ERROR_CODE_COMMAND_DISALLOWED;
696     }
697 
698     if (!connection->browsed_player_id){
699         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
700         return ERROR_CODE_COMMAND_DISALLOWED;
701     }
702 
703     connection->change_path = 1;
704     connection->direction = direction;
705 
706     memcpy(connection->folder_uid, folder_uid, 8);
707     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
708     return ERROR_CODE_SUCCESS;
709 }
710 
711 uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid){
712     return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 0, 0);
713 }
714 
715 uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid){
716     return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 1, folder_uid);
717 }
718