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