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