xref: /btstack/src/classic/avrcp_browsing_controller.c (revision 119bdcb221753faaae11978428024ce0a884d662)
1 /*
2  * Copyright (C) 2016 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "avrcp_browsing_controller.c"
39 
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <inttypes.h>
45 #include "btstack.h"
46 #include "classic/avrcp.h"
47 #include "classic/avrcp_browsing_controller.h"
48 
49 #define PSM_AVCTP_BROWSING              0x001b
50 
51 static void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context);
52 static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
53 
54 
55 static void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context){
56     UNUSED(channel);
57     UNUSED(size);
58     bd_addr_t event_addr;
59     uint16_t local_cid;
60     uint8_t  status;
61     avrcp_browsing_connection_t * browsing_connection = NULL;
62     avrcp_connection_t * avrcp_connection = NULL;
63 
64     if (packet_type != HCI_EVENT_PACKET) return;
65 
66     switch (hci_event_packet_get_type(packet)) {
67         case HCI_EVENT_DISCONNECTION_COMPLETE:
68             avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, 0);
69             break;
70         case L2CAP_EVENT_INCOMING_CONNECTION:
71             l2cap_event_incoming_connection_get_address(packet, event_addr);
72             local_cid = l2cap_event_incoming_connection_get_local_cid(packet);
73             avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, event_addr);
74             if (!avrcp_connection) {
75                 log_error("No previously created AVRCP controller connections");
76                 l2cap_decline_connection(local_cid);
77                 break;
78             }
79             browsing_connection = avrcp_browsing_create_connection(avrcp_connection);
80             browsing_connection->l2cap_browsing_cid = local_cid;
81             browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION;
82             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);
83             avrcp_emit_incoming_browsing_connection(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr);
84             break;
85 
86         case L2CAP_EVENT_CHANNEL_OPENED:
87             l2cap_event_channel_opened_get_address(packet, event_addr);
88             status = l2cap_event_channel_opened_get_status(packet);
89             local_cid = l2cap_event_channel_opened_get_local_cid(packet);
90 
91             avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, event_addr);
92             if (!avrcp_connection){
93                 log_error("Failed to find AVRCP connection for bd_addr %s", bd_addr_to_str(event_addr));
94                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, local_cid, event_addr, L2CAP_LOCAL_CID_DOES_NOT_EXIST);
95                 l2cap_disconnect(local_cid, 0); // reason isn't used
96                 break;
97             }
98 
99             browsing_connection = avrcp_connection->browsing_connection;
100             if (status != ERROR_CODE_SUCCESS){
101                 log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status);
102                 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, status);
103                 btstack_memory_avrcp_browsing_connection_free(browsing_connection);
104                 avrcp_connection->browsing_connection = NULL;
105                 break;
106             }
107             browsing_connection->l2cap_browsing_cid = local_cid;
108 
109             log_info("L2CAP_EVENT_CHANNEL_OPENED browsing cid 0x%02x, l2cap cid 0x%02x", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid);
110             browsing_connection->state = AVCTP_CONNECTION_OPENED;
111             avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, ERROR_CODE_SUCCESS);
112             break;
113 
114         case L2CAP_EVENT_CHANNEL_CLOSED:
115             local_cid = l2cap_event_channel_closed_get_local_cid(packet);
116             avrcp_connection = get_avrcp_connection_for_browsing_l2cap_cid_for_role(context->role, local_cid);
117 
118             if (avrcp_connection && avrcp_connection->browsing_connection){
119                 avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid);
120                 // free connection
121                 btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
122                 avrcp_connection->browsing_connection = NULL;
123                 break;
124             }
125             break;
126         default:
127             break;
128     }
129 }
130 
131 static int avrcp_browsing_controller_send_get_folder_items_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
132     uint8_t command[100];
133     int pos = 0;
134     // transport header
135     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
136     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
137     // Profile IDentifier (PID)
138     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
139     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
140     command[pos++] = AVRCP_PDU_ID_GET_FOLDER_ITEMS;
141 
142     uint32_t attribute_count = 0;
143     uint32_t attributes_to_copy = 0;
144 
145     switch (connection->attr_bitmap){
146         case AVRCP_MEDIA_ATTR_NONE:
147             attribute_count = AVRCP_MEDIA_ATTR_NONE; // 0xFFFFFFFF
148             break;
149         case AVRCP_MEDIA_ATTR_ALL:
150             attribute_count = AVRCP_MEDIA_ATTR_ALL;  // 0
151             break;
152         default:
153             attribute_count    = count_set_bits_uint32(connection->attr_bitmap & 0xff);
154             attributes_to_copy = attribute_count;
155             break;
156     }
157     big_endian_store_16(command, pos, 9 + 1 + (attribute_count*4));
158     pos += 2;
159 
160     command[pos++] = connection->scope;
161     big_endian_store_32(command, pos, connection->start_item);
162     pos += 4;
163     big_endian_store_32(command, pos, connection->end_item);
164     pos += 4;
165     command[pos++] = attribute_count;
166 
167     int bit_position = 1;
168     while (attributes_to_copy){
169         if (connection->attr_bitmap & (1 << bit_position)){
170             big_endian_store_32(command, pos, bit_position);
171             pos += 4;
172             attributes_to_copy--;
173         }
174         bit_position++;
175     }
176     return l2cap_send(cid, command, pos);
177 }
178 
179 
180 static int avrcp_browsing_controller_send_get_item_attributes_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
181     uint8_t command[100];
182     int pos = 0;
183     // transport header
184     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
185     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
186     // Profile IDentifier (PID)
187     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
188     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
189     command[pos++] = AVRCP_PDU_ID_GET_ITEM_ATTRIBUTES;
190 
191     uint32_t attribute_count;
192     uint32_t attributes_to_copy = 0;
193 
194     switch (connection->attr_bitmap){
195         case AVRCP_MEDIA_ATTR_NONE:
196         case AVRCP_MEDIA_ATTR_ALL:
197             attribute_count = 0;
198             break;
199         default:
200             attribute_count = count_set_bits_uint32(connection->attr_bitmap & 0xff);
201             attributes_to_copy = attribute_count;
202             break;
203     }
204 
205     big_endian_store_16(command, pos, 12 + (attribute_count*4));
206     pos += 2;
207 
208     command[pos++] = connection->scope;
209     (void)memcpy(command + pos, connection->folder_uid, 8);
210     pos += 8;
211     big_endian_store_16(command, pos, connection->uid_counter);
212     pos += 2;
213     command[pos++] = attribute_count;
214 
215     int bit_position = 1;
216     while (attributes_to_copy){
217         if (connection->attr_bitmap & (1 << bit_position)){
218             big_endian_store_32(command, pos, bit_position);
219             pos += 4;
220             attributes_to_copy--;
221         }
222         bit_position++;
223     }
224 
225     return l2cap_send(cid, command, pos);
226 }
227 
228 
229 static int avrcp_browsing_controller_send_change_path_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
230     uint8_t command[100];
231     int pos = 0;
232     // transport header
233     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
234     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
235     // Profile IDentifier (PID)
236     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
237     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
238     command[pos++] = AVRCP_PDU_ID_CHANGE_PATH;
239 
240     big_endian_store_16(command, pos, 11);
241     pos += 2;
242     pos += 2;
243     command[pos++] = connection->direction;
244     (void)memcpy(command + pos, connection->folder_uid, 8);
245     pos += 8;
246     return l2cap_send(cid, command, pos);
247 }
248 
249 static int avrcp_browsing_controller_send_search_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
250     uint8_t command[100];
251     int pos = 0;
252     // transport header
253     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
254     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
255     // Profile IDentifier (PID)
256     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
257     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
258     command[pos++] = AVRCP_PDU_ID_SEARCH;
259 
260     big_endian_store_16(command, pos, 4 + connection->search_str_len);
261     pos += 2;
262 
263     big_endian_store_16(command, pos, 0x006A);
264     pos += 2;
265     big_endian_store_16(command, pos, connection->search_str_len);
266     pos += 2;
267 
268     (void)memcpy(command + pos, connection->search_str,
269                  connection->search_str_len);
270     pos += connection->search_str_len;
271     return l2cap_send(cid, command, pos);
272 }
273 
274 static int avrcp_browsing_controller_send_set_browsed_player_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
275     uint8_t command[100];
276     int pos = 0;
277     // transport header
278     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
279     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
280     // Profile IDentifier (PID)
281     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
282     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
283     command[pos++] = AVRCP_PDU_ID_SET_BROWSED_PLAYER;
284 
285     big_endian_store_16(command, pos, 2);
286     pos += 2;
287     big_endian_store_16(command, pos, connection->browsed_player_id);
288     pos += 2;
289     return l2cap_send(cid, command, pos);
290 }
291 
292 static int avrcp_browsing_controller_send_get_total_nr_items_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){
293     uint8_t command[7];
294     int pos = 0;
295     // transport header
296     // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
297     command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0;
298     // Profile IDentifier (PID)
299     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8;
300     command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF;
301     command[pos++] = AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS;
302 
303     big_endian_store_16(command, pos, 1);
304     pos += 2;
305     command[pos++] = connection->get_total_nr_items_scope;
306     return l2cap_send(cid, command, pos);
307 }
308 
309 static void avrcp_browsing_controller_handle_can_send_now(avrcp_browsing_connection_t * connection){
310     switch (connection->state){
311         case AVCTP_CONNECTION_OPENED:
312             if (connection->set_browsed_player_id){
313                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
314                 connection->set_browsed_player_id = 0;
315                 avrcp_browsing_controller_send_set_browsed_player_cmd(connection->l2cap_browsing_cid, connection);
316                 break;
317             }
318 
319             if (connection->get_total_nr_items){
320                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
321                 connection->get_total_nr_items = 0;
322                 avrcp_browsing_controller_send_get_total_nr_items_cmd(connection->l2cap_browsing_cid, connection);
323                 break;
324             }
325 
326             if (connection->get_folder_items){
327                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
328                 connection->get_folder_items = 0;
329                 avrcp_browsing_controller_send_get_folder_items_cmd(connection->l2cap_browsing_cid, connection);
330                 break;
331             }
332 
333             if (connection->get_item_attributes){
334                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
335                 connection->get_item_attributes = 0;
336                 avrcp_browsing_controller_send_get_item_attributes_cmd(connection->l2cap_browsing_cid, connection);
337                 break;
338             }
339 
340             if (connection->change_path){
341                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
342                 connection->change_path = 0;
343                 avrcp_browsing_controller_send_change_path_cmd(connection->l2cap_browsing_cid, connection);
344                 break;
345             }
346 
347             if (connection->search){
348                 connection->state = AVCTP_W2_RECEIVE_RESPONSE;
349                 connection->search = 0;
350                 avrcp_browsing_controller_send_search_cmd(connection->l2cap_browsing_cid, connection);
351                 break;
352             }
353             break;
354         default:
355             return;
356     }
357 }
358 
359 
360 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){
361     btstack_assert(callback != NULL);
362 
363     uint8_t event[9];
364     int pos = 0;
365     event[pos++] = HCI_EVENT_AVRCP_META;
366     event[pos++] = sizeof(event) - 2;
367     event[pos++] = AVRCP_SUBEVENT_BROWSING_DONE;
368     little_endian_store_16(event, pos, browsing_cid);
369     pos += 2;
370     little_endian_store_16(event, pos, uid_counter);
371     pos += 2;
372     event[pos++] = browsing_status;
373     event[pos++] = bluetooth_status;
374     (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
375 }
376 
377 static void avrcp_parser_reset(avrcp_browsing_connection_t * connection){
378     connection->parser_attribute_header_pos = 0;
379     connection->parsed_attribute_value_offset = 0;
380     connection->parsed_num_attributes = 0;
381     connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
382 }
383 
384 
385 static void avrcp_browsing_parser_process_byte(uint8_t byte, avrcp_browsing_connection_t * connection){
386     uint8_t prepended_header_size = 1;
387     uint16_t attribute_total_value_len;
388 
389     switch(connection->parser_state){
390         case AVRCP_PARSER_GET_ATTRIBUTE_HEADER:
391             connection->parser_attribute_header[connection->parser_attribute_header_pos++] = byte;
392             if (connection->parser_attribute_header_pos < AVRCP_BROWSING_ITEM_HEADER_LEN) break;
393 
394             attribute_total_value_len = big_endian_read_16(connection->parser_attribute_header, 1);
395             connection->parsed_attribute_value[connection->parsed_attribute_value_offset++] = connection->parser_attribute_header[0];   // prepend with item type
396             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
397             connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_VALUE;
398             break;
399 
400         case AVRCP_PARSER_GET_ATTRIBUTE_VALUE:
401             connection->parsed_attribute_value[connection->parsed_attribute_value_offset++] = byte;
402             if (connection->parsed_attribute_value_offset < (connection->parsed_attribute_value_len + prepended_header_size)){
403                 break;
404             }
405             if (connection->parsed_attribute_value_offset < big_endian_read_16(connection->parser_attribute_header, 1)){
406                 connection->parser_state = AVRCP_PARSER_IGNORE_REST_OF_ATTRIBUTE_VALUE;
407                 break;
408             }
409             connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
410             (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, connection->l2cap_browsing_cid, &connection->parsed_attribute_value[0], connection->parsed_attribute_value_offset);
411             connection->parsed_num_attributes++;
412             connection->parsed_attribute_value_offset = 0;
413             connection->parser_attribute_header_pos = 0;
414 
415             if (connection->parsed_num_attributes == connection->num_items){
416                 avrcp_parser_reset(connection);
417                 break;
418             }
419             break;
420 
421         case AVRCP_PARSER_IGNORE_REST_OF_ATTRIBUTE_VALUE:
422             connection->parsed_attribute_value_offset++;
423             if (connection->parsed_attribute_value_offset < (big_endian_read_16(connection->parser_attribute_header, 1) + prepended_header_size)){
424                 break;
425             }
426             connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER;
427             (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, connection->l2cap_browsing_cid, &connection->parsed_attribute_value[0], connection->parsed_attribute_value_offset);
428             connection->parsed_num_attributes++;
429             connection->parsed_attribute_value_offset = 0;
430             connection->parser_attribute_header_pos = 0;
431 
432             if (connection->parsed_num_attributes == connection->num_items){
433                 avrcp_parser_reset(connection);
434                 break;
435             }
436             break;
437         default:
438             break;
439     }
440 }
441 
442 static void avrcp_browsing_parse_and_emit_element_attrs(uint8_t * packet, uint16_t num_bytes_to_read, avrcp_browsing_connection_t * connection){
443     int i;
444     for (i=0;i<num_bytes_to_read;i++){
445         avrcp_browsing_parser_process_byte(packet[i], connection);
446     }
447 }
448 
449 static void avrcp_browsing_controller_emit_failed(btstack_packet_handler_t callback, uint16_t browsing_cid, uint8_t browsing_status, uint8_t bluetooth_status){
450     avrcp_browsing_controller_emit_done_with_uid_counter(callback, browsing_cid, 0, browsing_status, bluetooth_status);
451 }
452 
453 
454 static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
455     avrcp_browsing_connection_t * browsing_connection;
456     uint8_t transport_header;
457     int pos;
458 
459     switch (packet_type) {
460         case L2CAP_DATA_PACKET:
461             browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid_for_role(AVRCP_CONTROLLER, channel);
462             if (!browsing_connection) break;
463             pos = 0;
464             transport_header = packet[pos++];
465             // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier)
466             browsing_connection->transaction_label = transport_header >> 4;
467             avrcp_packet_type_t avctp_packet_type = (transport_header & 0x0F) >> 2;
468             switch (avctp_packet_type){
469                 case AVRCP_SINGLE_PACKET:
470                 case AVRCP_START_PACKET:
471                     pos += 2;
472                     browsing_connection->num_packets = 1;
473                     if (avctp_packet_type == AVRCP_START_PACKET){
474                         browsing_connection->num_packets = packet[pos++];
475                     }
476                     if ((pos + 4) > size){
477                         browsing_connection->state = AVCTP_CONNECTION_OPENED;
478                         avrcp_browsing_controller_emit_failed(avrcp_controller_context.browsing_avrcp_callback, channel, AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND, ERROR_CODE_SUCCESS);
479                         return;
480                     }
481                     browsing_connection->pdu_id = packet[pos++];
482                     pos += 2;
483                     browsing_connection->browsing_status = packet[pos++];
484                     if (browsing_connection->browsing_status != AVRCP_BROWSING_ERROR_CODE_SUCCESS){
485                         browsing_connection->state = AVCTP_CONNECTION_OPENED;
486                         avrcp_browsing_controller_emit_failed(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_connection->browsing_status, ERROR_CODE_SUCCESS);
487                         return;
488                     }
489                     break;
490                 default:
491                     break;
492             }
493 
494             uint32_t i;
495             uint8_t folder_depth;
496 
497             switch(browsing_connection->pdu_id){
498                 case AVRCP_PDU_ID_CHANGE_PATH:
499                     break;
500                 case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER:
501                     break;
502                 case AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS:
503                     break;
504                 case AVRCP_PDU_ID_SET_BROWSED_PLAYER:
505                     browsing_connection->uid_counter =  big_endian_read_16(packet, pos);
506                     pos += 2;
507                     // num_items
508                     pos += 4;
509                     // charset
510                     pos += 2;
511                     folder_depth = packet[pos++];
512 
513                     for (i = 0; i < folder_depth; i++){
514                         uint16_t folder_name_length = big_endian_read_16(packet, pos);
515                         pos += 2;
516                         // reuse packet and add data type as a header
517                         packet[pos-1] = AVRCP_BROWSING_MEDIA_ROOT_FOLDER;
518                         (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos-1, folder_name_length+1);
519                         pos += folder_name_length;
520                     }
521                     break;
522 
523                 case AVRCP_PDU_ID_GET_FOLDER_ITEMS:{
524                     switch (avctp_packet_type){
525                         case AVRCP_SINGLE_PACKET:
526                         case AVRCP_START_PACKET:
527                             avrcp_parser_reset(browsing_connection);
528                             browsing_connection->uid_counter =  big_endian_read_16(packet, pos);
529                             pos += 2;
530                             browsing_connection->num_items = big_endian_read_16(packet, pos); //num_items
531                             pos += 2;
532                             avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection);
533                             break;
534 
535                         case AVRCP_CONTINUE_PACKET:
536                             avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection);
537                             break;
538 
539                         case AVRCP_END_PACKET:
540                             avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection);
541                             avrcp_parser_reset(browsing_connection);
542                             break;
543                         default:
544                             break;
545                     }
546                     break;
547                 }
548                 case AVRCP_PDU_ID_SEARCH:
549                     browsing_connection->uid_counter =  big_endian_read_16(packet, pos);
550                     pos += 2;
551                     break;
552                 case AVRCP_PDU_ID_GET_ITEM_ATTRIBUTES:
553                     packet[pos-1] = AVRCP_BROWSING_MEDIA_ELEMENT_ITEM_ATTRIBUTE;
554                     (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos-1, size - pos + 1);
555                     break;
556                 default:
557                     log_info(" not parsed pdu ID 0x%02x", browsing_connection->pdu_id);
558                     break;
559             }
560 
561             switch (avctp_packet_type){
562                 case AVRCP_SINGLE_PACKET:
563                 case AVRCP_END_PACKET:
564                     browsing_connection->state = AVCTP_CONNECTION_OPENED;
565                     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);
566                     break;
567                 default:
568                     break;
569             }
570             break;
571 
572         case HCI_EVENT_PACKET:
573             switch (hci_event_packet_get_type(packet)){
574                 case L2CAP_EVENT_CAN_SEND_NOW:
575                     browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid_for_role(AVRCP_CONTROLLER,channel);
576                     if (!browsing_connection) break;
577                     avrcp_browsing_controller_handle_can_send_now(browsing_connection);
578                     break;
579                 default:
580                     avrcp_browser_packet_handler(packet_type, channel, packet, size, &avrcp_controller_context);
581                     break;
582             }
583             break;
584 
585         default:
586             break;
587     }
588 }
589 
590 void avrcp_browsing_controller_init(void){
591     avrcp_controller_context.browsing_packet_handler = avrcp_browsing_controller_packet_handler;
592     l2cap_register_service(&avrcp_browsing_controller_packet_handler, PSM_AVCTP_BROWSING, 0xffff, gap_get_security_level());
593 }
594 
595 void avrcp_browsing_controller_register_packet_handler(btstack_packet_handler_t callback){
596     btstack_assert(callback != NULL);
597     avrcp_controller_context.browsing_avrcp_callback = callback;
598 }
599 
600 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){
601     return avrcp_browsing_connect(bd_addr, AVRCP_CONTROLLER, avrcp_browsing_controller_packet_handler, ertm_buffer, size, ertm_config, avrcp_browsing_cid);
602 }
603 
604 uint8_t avrcp_browsing_controller_disconnect(uint16_t avrcp_browsing_cid){
605     return avrcp_browsing_disconnect(avrcp_browsing_cid, AVRCP_CONTROLLER);
606 }
607 
608 uint8_t avrcp_browsing_controller_configure_incoming_connection(uint16_t avrcp_browsing_cid, uint8_t * ertm_buffer, uint32_t size, l2cap_ertm_config_t * ertm_config){
609     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
610     if (!avrcp_connection){
611         log_error("avrcp_browsing_controller_decline_incoming_connection: could not find a connection.");
612         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
613     }
614     if (!avrcp_connection->browsing_connection){
615         log_error("avrcp_browsing_controller_decline_incoming_connection: no browsing connection.");
616         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
617     }
618 
619     if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_W4_ERTM_CONFIGURATION){
620         log_error("avrcp_browsing_controller_decline_incoming_connection: browsing connection in a wrong state.");
621         return ERROR_CODE_COMMAND_DISALLOWED;
622     }
623 
624     avrcp_connection->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
625     avrcp_connection->browsing_connection->ertm_buffer = ertm_buffer;
626     avrcp_connection->browsing_connection->ertm_buffer_size = size;
627     (void)memcpy(&avrcp_connection->browsing_connection->ertm_config,
628                  ertm_config, sizeof(l2cap_ertm_config_t));
629     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);
630     return ERROR_CODE_SUCCESS;
631 }
632 
633 uint8_t avrcp_browsing_controller_decline_incoming_connection(uint16_t avrcp_browsing_cid){
634     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
635     if (!avrcp_connection){
636         log_error("avrcp_browsing_controller_decline_incoming_connection: could not find a connection.");
637         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
638     }
639     if (!avrcp_connection->browsing_connection) return ERROR_CODE_SUCCESS;
640     if (avrcp_connection->browsing_connection->state > AVCTP_CONNECTION_W4_ERTM_CONFIGURATION) return ERROR_CODE_COMMAND_DISALLOWED;
641 
642     l2cap_decline_connection(avrcp_connection->browsing_connection->l2cap_browsing_cid);
643     // free connection
644     btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection);
645     avrcp_connection->browsing_connection = NULL;
646     return ERROR_CODE_SUCCESS;
647 }
648 
649 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){
650     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
651     if (!avrcp_connection){
652         log_error("avrcp_browsing_controller_get_item_attributes: could not find a connection.");
653         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
654     }
655     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
656     if (connection->state != AVCTP_CONNECTION_OPENED){
657         log_error("avrcp_browsing_controller_get_item_attributes: connection in wrong state %d, expected %d.", connection->state, AVCTP_CONNECTION_OPENED);
658         return ERROR_CODE_COMMAND_DISALLOWED;
659     }
660 
661     connection->get_item_attributes = 1;
662     connection->scope = scope;
663     (void)memcpy(connection->folder_uid, uid, 8);
664     connection->uid_counter = uid_counter;
665     connection->attr_bitmap = attr_bitmap;
666 
667     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
668     return ERROR_CODE_SUCCESS;
669 }
670 
671 /**
672  * @brief Retrieve a listing of the contents of a folder.
673  * @param scope    0-player list, 1-virtual file system, 2-search, 3-now playing
674  * @param start_item
675  * @param end_item
676  * @param attribute_count
677  * @param attribute_list
678  **/
679 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){
680     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
681     if (!avrcp_connection){
682         log_error("avrcp_browsing_controller_disconnect: could not find a connection.");
683         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
684     }
685     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
686     if (connection->state != AVCTP_CONNECTION_OPENED) {
687         log_error("avrcp_browsing_controller_get_folder_items: connection in wrong state %d, expected %d.", connection->state, AVCTP_CONNECTION_OPENED);
688         return ERROR_CODE_COMMAND_DISALLOWED;
689     }
690 
691     connection->get_folder_items = 1;
692     connection->scope = scope;
693     connection->start_item = start_item;
694     connection->end_item = end_item;
695     connection->attr_bitmap = attr_bitmap;
696 
697     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
698     return ERROR_CODE_SUCCESS;
699 }
700 
701 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){
702     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_LIST, start_item, end_item, attr_bitmap);
703 }
704 
705 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){
706     // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 1, 0, 0xFFFFFFFF, attr_bitmap);
707     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_VIRTUAL_FILESYSTEM, start_item, end_item, attr_bitmap);
708 }
709 
710 uint8_t avrcp_browsing_controller_browse_media(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){
711     // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 2, 0, 0xFFFFFFFF, 0, NULL);
712     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_SEARCH, start_item, end_item, attr_bitmap);
713 }
714 
715 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){
716     return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_NOW_PLAYING, start_item, end_item, attr_bitmap);
717 }
718 
719 
720 uint8_t avrcp_browsing_controller_set_browsed_player(uint16_t avrcp_browsing_cid, uint16_t browsed_player_id){
721     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
722     if (!avrcp_connection){
723         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
724         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
725     }
726 
727     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
728     if (connection->state != AVCTP_CONNECTION_OPENED){
729         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
730         return ERROR_CODE_COMMAND_DISALLOWED;
731     }
732 
733     connection->set_browsed_player_id = 1;
734     connection->browsed_player_id = browsed_player_id;
735     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
736     return ERROR_CODE_SUCCESS;
737 }
738 
739 /**
740  * @brief Retrieve a listing of the contents of a folder.
741  * @param direction     0-folder up, 1-folder down
742  * @param folder_uid    8 bytes long
743  **/
744 uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8_t direction, uint8_t * folder_uid){
745     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
746     if (!avrcp_connection){
747         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
748         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
749     }
750 
751     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
752 
753     if ((connection == NULL) || (connection->state != AVCTP_CONNECTION_OPENED)){
754         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
755         return ERROR_CODE_COMMAND_DISALLOWED;
756     }
757 
758     if (!connection->browsed_player_id){
759         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
760         return ERROR_CODE_COMMAND_DISALLOWED;
761     }
762     connection->change_path = 1;
763     connection->direction = direction;
764     memset(connection->folder_uid, 0, 8);
765     if (folder_uid){
766         (void)memcpy(connection->folder_uid, folder_uid, 8);
767     }
768 
769     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
770     return ERROR_CODE_SUCCESS;
771 }
772 
773 uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid){
774     return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 0, NULL);
775 }
776 
777 uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid){
778     return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 1, folder_uid);
779 }
780 
781 uint8_t avrcp_browsing_controller_search(uint16_t avrcp_browsing_cid, uint16_t search_str_len, char * search_str){
782     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
783     if (!avrcp_connection){
784         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
785         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
786     }
787 
788     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
789 
790     if ((connection == NULL) || (connection->state != AVCTP_CONNECTION_OPENED)){
791         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
792         return ERROR_CODE_COMMAND_DISALLOWED;
793     }
794 
795     if (!connection->browsed_player_id){
796         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
797         return ERROR_CODE_COMMAND_DISALLOWED;
798     }
799     if (!search_str || (search_str_len == 0)){
800         return AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND;
801     }
802 
803     connection->search = 1;
804 
805     connection->search_str_len = btstack_min(search_str_len, sizeof(connection->search_str)-1);
806     memset(connection->search_str, 0, sizeof(connection->search_str));
807     (void)memcpy(connection->search_str, search_str,
808                  connection->search_str_len);
809     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
810     return ERROR_CODE_SUCCESS;
811 }
812 
813 uint8_t avrcp_browsing_controller_get_total_nr_items_for_scope(uint16_t avrcp_browsing_cid, avrcp_browsing_scope_t scope){
814     avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid);
815     if (!avrcp_connection){
816         log_error("avrcp_browsing_controller_change_path: could not find a connection.");
817         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
818     }
819 
820     avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection;
821 
822     if ((connection == NULL) || (connection->state != AVCTP_CONNECTION_OPENED)){
823         log_error("avrcp_browsing_controller_change_path: connection in wrong state.");
824         return ERROR_CODE_COMMAND_DISALLOWED;
825     }
826 
827     if (!connection->browsed_player_id){
828         log_error("avrcp_browsing_controller_change_path: no browsed player set.");
829         return ERROR_CODE_COMMAND_DISALLOWED;
830     }
831     connection->get_total_nr_items = 1;
832     connection->get_total_nr_items_scope = scope;
833     avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid);
834     return ERROR_CODE_SUCCESS;
835 }
836