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 static void avrcp_emit_browsing_connection_established(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr, uint8_t status){ 55 btstack_assert(callback != NULL); 56 57 uint8_t event[12]; 58 int pos = 0; 59 event[pos++] = HCI_EVENT_AVRCP_META; 60 event[pos++] = sizeof(event) - 2; 61 event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_ESTABLISHED; 62 event[pos++] = status; 63 reverse_bd_addr(addr,&event[pos]); 64 pos += 6; 65 little_endian_store_16(event, pos, browsing_cid); 66 pos += 2; 67 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 68 } 69 70 static void avrcp_emit_incoming_browsing_connection(btstack_packet_handler_t callback, uint16_t browsing_cid, bd_addr_t addr){ 71 btstack_assert(callback != NULL); 72 73 uint8_t event[11]; 74 int pos = 0; 75 event[pos++] = HCI_EVENT_AVRCP_META; 76 event[pos++] = sizeof(event) - 2; 77 event[pos++] = AVRCP_SUBEVENT_INCOMING_BROWSING_CONNECTION; 78 reverse_bd_addr(addr,&event[pos]); 79 pos += 6; 80 little_endian_store_16(event, pos, browsing_cid); 81 pos += 2; 82 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 83 } 84 85 static void avrcp_emit_browsing_connection_closed(btstack_packet_handler_t callback, uint16_t browsing_cid){ 86 btstack_assert(callback != NULL); 87 88 uint8_t event[5]; 89 int pos = 0; 90 event[pos++] = HCI_EVENT_AVRCP_META; 91 event[pos++] = sizeof(event) - 2; 92 event[pos++] = AVRCP_SUBEVENT_BROWSING_CONNECTION_RELEASED; 93 little_endian_store_16(event, pos, browsing_cid); 94 pos += 2; 95 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 96 } 97 98 static void avrcp_browser_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size, avrcp_context_t * context){ 99 UNUSED(channel); 100 UNUSED(size); 101 bd_addr_t event_addr; 102 uint16_t local_cid; 103 uint8_t status; 104 avrcp_browsing_connection_t * browsing_connection = NULL; 105 avrcp_connection_t * avrcp_connection = NULL; 106 107 if (packet_type != HCI_EVENT_PACKET) return; 108 109 switch (hci_event_packet_get_type(packet)) { 110 case HCI_EVENT_DISCONNECTION_COMPLETE: 111 avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, 0); 112 break; 113 case L2CAP_EVENT_INCOMING_CONNECTION: 114 l2cap_event_incoming_connection_get_address(packet, event_addr); 115 local_cid = l2cap_event_incoming_connection_get_local_cid(packet); 116 avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, event_addr); 117 if (!avrcp_connection) { 118 log_error("No previously created AVRCP controller connections"); 119 l2cap_decline_connection(local_cid); 120 break; 121 } 122 browsing_connection = avrcp_browsing_create_connection(avrcp_connection); 123 browsing_connection->l2cap_browsing_cid = local_cid; 124 browsing_connection->state = AVCTP_CONNECTION_W4_ERTM_CONFIGURATION; 125 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); 126 avrcp_emit_incoming_browsing_connection(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr); 127 break; 128 129 case L2CAP_EVENT_CHANNEL_OPENED: 130 l2cap_event_channel_opened_get_address(packet, event_addr); 131 status = l2cap_event_channel_opened_get_status(packet); 132 local_cid = l2cap_event_channel_opened_get_local_cid(packet); 133 134 avrcp_connection = get_avrcp_connection_for_bd_addr_for_role(AVRCP_CONTROLLER, event_addr); 135 if (!avrcp_connection){ 136 log_error("Failed to find AVRCP connection for bd_addr %s", bd_addr_to_str(event_addr)); 137 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, local_cid, event_addr, L2CAP_LOCAL_CID_DOES_NOT_EXIST); 138 l2cap_disconnect(local_cid, 0); // reason isn't used 139 break; 140 } 141 142 browsing_connection = avrcp_connection->browsing_connection; 143 if (status != ERROR_CODE_SUCCESS){ 144 log_info("L2CAP connection to connection %s failed. status code 0x%02x", bd_addr_to_str(event_addr), status); 145 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, status); 146 btstack_memory_avrcp_browsing_connection_free(browsing_connection); 147 avrcp_connection->browsing_connection = NULL; 148 break; 149 } 150 browsing_connection->l2cap_browsing_cid = local_cid; 151 152 log_info("L2CAP_EVENT_CHANNEL_OPENED browsing cid 0x%02x, l2cap cid 0x%02x", avrcp_connection->avrcp_browsing_cid, browsing_connection->l2cap_browsing_cid); 153 browsing_connection->state = AVCTP_CONNECTION_OPENED; 154 avrcp_emit_browsing_connection_established(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid, event_addr, ERROR_CODE_SUCCESS); 155 break; 156 157 case L2CAP_EVENT_CHANNEL_CLOSED: 158 local_cid = l2cap_event_channel_closed_get_local_cid(packet); 159 avrcp_connection = get_avrcp_connection_for_browsing_l2cap_cid_for_role(context->role, local_cid); 160 161 if (avrcp_connection && avrcp_connection->browsing_connection){ 162 avrcp_emit_browsing_connection_closed(context->browsing_avrcp_callback, avrcp_connection->avrcp_browsing_cid); 163 // free connection 164 btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection); 165 avrcp_connection->browsing_connection = NULL; 166 break; 167 } 168 break; 169 default: 170 break; 171 } 172 } 173 174 static int avrcp_browsing_controller_send_get_folder_items_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){ 175 uint8_t command[100]; 176 int pos = 0; 177 // transport header 178 // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) 179 command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0; 180 // Profile IDentifier (PID) 181 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 182 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 183 command[pos++] = AVRCP_PDU_ID_GET_FOLDER_ITEMS; 184 185 uint32_t attribute_count = 0; 186 uint32_t attributes_to_copy = 0; 187 188 switch (connection->attr_bitmap){ 189 case AVRCP_MEDIA_ATTR_NONE: 190 attribute_count = AVRCP_MEDIA_ATTR_NONE; // 0xFFFFFFFF 191 break; 192 case AVRCP_MEDIA_ATTR_ALL: 193 attribute_count = AVRCP_MEDIA_ATTR_ALL; // 0 194 break; 195 default: 196 attribute_count = count_set_bits_uint32(connection->attr_bitmap & 0xff); 197 attributes_to_copy = attribute_count; 198 break; 199 } 200 big_endian_store_16(command, pos, 9 + 1 + (attribute_count*4)); 201 pos += 2; 202 203 command[pos++] = connection->scope; 204 big_endian_store_32(command, pos, connection->start_item); 205 pos += 4; 206 big_endian_store_32(command, pos, connection->end_item); 207 pos += 4; 208 command[pos++] = attribute_count; 209 210 int bit_position = 1; 211 while (attributes_to_copy){ 212 if (connection->attr_bitmap & (1 << bit_position)){ 213 big_endian_store_32(command, pos, bit_position); 214 pos += 4; 215 attributes_to_copy--; 216 } 217 bit_position++; 218 } 219 return l2cap_send(cid, command, pos); 220 } 221 222 223 static int avrcp_browsing_controller_send_get_item_attributes_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){ 224 uint8_t command[100]; 225 int pos = 0; 226 // transport header 227 // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) 228 command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0; 229 // Profile IDentifier (PID) 230 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 231 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 232 command[pos++] = AVRCP_PDU_ID_GET_ITEM_ATTRIBUTES; 233 234 uint32_t attribute_count; 235 uint32_t attributes_to_copy = 0; 236 237 switch (connection->attr_bitmap){ 238 case AVRCP_MEDIA_ATTR_NONE: 239 case AVRCP_MEDIA_ATTR_ALL: 240 attribute_count = 0; 241 break; 242 default: 243 attribute_count = count_set_bits_uint32(connection->attr_bitmap & 0xff); 244 attributes_to_copy = attribute_count; 245 break; 246 } 247 248 big_endian_store_16(command, pos, 12 + (attribute_count*4)); 249 pos += 2; 250 251 command[pos++] = connection->scope; 252 (void)memcpy(command + pos, connection->folder_uid, 8); 253 pos += 8; 254 big_endian_store_16(command, pos, connection->uid_counter); 255 pos += 2; 256 command[pos++] = attribute_count; 257 258 int bit_position = 1; 259 while (attributes_to_copy){ 260 if (connection->attr_bitmap & (1 << bit_position)){ 261 big_endian_store_32(command, pos, bit_position); 262 pos += 4; 263 attributes_to_copy--; 264 } 265 bit_position++; 266 } 267 268 return l2cap_send(cid, command, pos); 269 } 270 271 272 static int avrcp_browsing_controller_send_change_path_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){ 273 uint8_t command[100]; 274 int pos = 0; 275 // transport header 276 // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) 277 command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0; 278 // Profile IDentifier (PID) 279 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 280 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 281 command[pos++] = AVRCP_PDU_ID_CHANGE_PATH; 282 283 big_endian_store_16(command, pos, 11); 284 pos += 2; 285 pos += 2; 286 command[pos++] = connection->direction; 287 (void)memcpy(command + pos, connection->folder_uid, 8); 288 pos += 8; 289 return l2cap_send(cid, command, pos); 290 } 291 292 static int avrcp_browsing_controller_send_search_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){ 293 uint8_t command[100]; 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_SEARCH; 302 303 big_endian_store_16(command, pos, 4 + connection->search_str_len); 304 pos += 2; 305 306 big_endian_store_16(command, pos, 0x006A); 307 pos += 2; 308 big_endian_store_16(command, pos, connection->search_str_len); 309 pos += 2; 310 311 (void)memcpy(command + pos, connection->search_str, 312 connection->search_str_len); 313 pos += connection->search_str_len; 314 return l2cap_send(cid, command, pos); 315 } 316 317 static int avrcp_browsing_controller_send_set_browsed_player_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){ 318 uint8_t command[100]; 319 int pos = 0; 320 // transport header 321 // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) 322 command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0; 323 // Profile IDentifier (PID) 324 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 325 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 326 command[pos++] = AVRCP_PDU_ID_SET_BROWSED_PLAYER; 327 328 big_endian_store_16(command, pos, 2); 329 pos += 2; 330 big_endian_store_16(command, pos, connection->browsed_player_id); 331 pos += 2; 332 return l2cap_send(cid, command, pos); 333 } 334 335 static int avrcp_browsing_controller_send_get_total_nr_items_cmd(uint16_t cid, avrcp_browsing_connection_t * connection){ 336 uint8_t command[7]; 337 int pos = 0; 338 // transport header 339 // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) 340 command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0; 341 // Profile IDentifier (PID) 342 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 343 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 344 command[pos++] = AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS; 345 346 big_endian_store_16(command, pos, 1); 347 pos += 2; 348 command[pos++] = connection->get_total_nr_items_scope; 349 return l2cap_send(cid, command, pos); 350 } 351 352 static void avrcp_browsing_controller_handle_can_send_now(avrcp_browsing_connection_t * connection){ 353 switch (connection->state){ 354 case AVCTP_CONNECTION_OPENED: 355 if (connection->set_browsed_player_id){ 356 connection->state = AVCTP_W2_RECEIVE_RESPONSE; 357 connection->set_browsed_player_id = 0; 358 avrcp_browsing_controller_send_set_browsed_player_cmd(connection->l2cap_browsing_cid, connection); 359 break; 360 } 361 362 if (connection->get_total_nr_items){ 363 connection->state = AVCTP_W2_RECEIVE_RESPONSE; 364 connection->get_total_nr_items = 0; 365 avrcp_browsing_controller_send_get_total_nr_items_cmd(connection->l2cap_browsing_cid, connection); 366 break; 367 } 368 369 if (connection->get_folder_items){ 370 connection->state = AVCTP_W2_RECEIVE_RESPONSE; 371 connection->get_folder_items = 0; 372 avrcp_browsing_controller_send_get_folder_items_cmd(connection->l2cap_browsing_cid, connection); 373 break; 374 } 375 376 if (connection->get_item_attributes){ 377 connection->state = AVCTP_W2_RECEIVE_RESPONSE; 378 connection->get_item_attributes = 0; 379 avrcp_browsing_controller_send_get_item_attributes_cmd(connection->l2cap_browsing_cid, connection); 380 break; 381 } 382 383 if (connection->change_path){ 384 connection->state = AVCTP_W2_RECEIVE_RESPONSE; 385 connection->change_path = 0; 386 avrcp_browsing_controller_send_change_path_cmd(connection->l2cap_browsing_cid, connection); 387 break; 388 } 389 390 if (connection->search){ 391 connection->state = AVCTP_W2_RECEIVE_RESPONSE; 392 connection->search = 0; 393 avrcp_browsing_controller_send_search_cmd(connection->l2cap_browsing_cid, connection); 394 break; 395 } 396 break; 397 default: 398 return; 399 } 400 } 401 402 403 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){ 404 btstack_assert(callback != NULL); 405 406 uint8_t event[9]; 407 int pos = 0; 408 event[pos++] = HCI_EVENT_AVRCP_META; 409 event[pos++] = sizeof(event) - 2; 410 event[pos++] = AVRCP_SUBEVENT_BROWSING_DONE; 411 little_endian_store_16(event, pos, browsing_cid); 412 pos += 2; 413 little_endian_store_16(event, pos, uid_counter); 414 pos += 2; 415 event[pos++] = browsing_status; 416 event[pos++] = bluetooth_status; 417 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 418 } 419 420 static void avrcp_parser_reset(avrcp_browsing_connection_t * connection){ 421 connection->parser_attribute_header_pos = 0; 422 connection->parsed_attribute_value_offset = 0; 423 connection->parsed_num_attributes = 0; 424 connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER; 425 } 426 427 428 static void avrcp_browsing_parser_process_byte(uint8_t byte, avrcp_browsing_connection_t * connection){ 429 uint8_t prepended_header_size = 1; 430 uint16_t attribute_total_value_len; 431 432 switch(connection->parser_state){ 433 case AVRCP_PARSER_GET_ATTRIBUTE_HEADER: 434 connection->parser_attribute_header[connection->parser_attribute_header_pos++] = byte; 435 if (connection->parser_attribute_header_pos < AVRCP_BROWSING_ITEM_HEADER_LEN) break; 436 437 attribute_total_value_len = big_endian_read_16(connection->parser_attribute_header, 1); 438 connection->parsed_attribute_value[connection->parsed_attribute_value_offset++] = connection->parser_attribute_header[0]; // prepend with item type 439 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 440 connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_VALUE; 441 break; 442 443 case AVRCP_PARSER_GET_ATTRIBUTE_VALUE: 444 connection->parsed_attribute_value[connection->parsed_attribute_value_offset++] = byte; 445 if (connection->parsed_attribute_value_offset < (connection->parsed_attribute_value_len + prepended_header_size)){ 446 break; 447 } 448 if (connection->parsed_attribute_value_offset < big_endian_read_16(connection->parser_attribute_header, 1)){ 449 connection->parser_state = AVRCP_PARSER_IGNORE_REST_OF_ATTRIBUTE_VALUE; 450 break; 451 } 452 connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER; 453 (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, connection->l2cap_browsing_cid, &connection->parsed_attribute_value[0], connection->parsed_attribute_value_offset); 454 connection->parsed_num_attributes++; 455 connection->parsed_attribute_value_offset = 0; 456 connection->parser_attribute_header_pos = 0; 457 458 if (connection->parsed_num_attributes == connection->num_items){ 459 avrcp_parser_reset(connection); 460 break; 461 } 462 break; 463 464 case AVRCP_PARSER_IGNORE_REST_OF_ATTRIBUTE_VALUE: 465 connection->parsed_attribute_value_offset++; 466 if (connection->parsed_attribute_value_offset < (big_endian_read_16(connection->parser_attribute_header, 1) + prepended_header_size)){ 467 break; 468 } 469 connection->parser_state = AVRCP_PARSER_GET_ATTRIBUTE_HEADER; 470 (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, connection->l2cap_browsing_cid, &connection->parsed_attribute_value[0], connection->parsed_attribute_value_offset); 471 connection->parsed_num_attributes++; 472 connection->parsed_attribute_value_offset = 0; 473 connection->parser_attribute_header_pos = 0; 474 475 if (connection->parsed_num_attributes == connection->num_items){ 476 avrcp_parser_reset(connection); 477 break; 478 } 479 break; 480 default: 481 break; 482 } 483 } 484 485 static void avrcp_browsing_parse_and_emit_element_attrs(uint8_t * packet, uint16_t num_bytes_to_read, avrcp_browsing_connection_t * connection){ 486 int i; 487 for (i=0;i<num_bytes_to_read;i++){ 488 avrcp_browsing_parser_process_byte(packet[i], connection); 489 } 490 } 491 492 static void avrcp_browsing_controller_emit_failed(btstack_packet_handler_t callback, uint16_t browsing_cid, uint8_t browsing_status, uint8_t bluetooth_status){ 493 avrcp_browsing_controller_emit_done_with_uid_counter(callback, browsing_cid, 0, browsing_status, bluetooth_status); 494 } 495 496 497 static void avrcp_browsing_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 498 avrcp_browsing_connection_t * browsing_connection; 499 uint8_t transport_header; 500 int pos; 501 502 switch (packet_type) { 503 case L2CAP_DATA_PACKET: 504 browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid_for_role(AVRCP_CONTROLLER, channel); 505 if (!browsing_connection) break; 506 pos = 0; 507 transport_header = packet[pos++]; 508 // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) 509 browsing_connection->transaction_label = transport_header >> 4; 510 avrcp_packet_type_t avctp_packet_type = (transport_header & 0x0F) >> 2; 511 switch (avctp_packet_type){ 512 case AVRCP_SINGLE_PACKET: 513 case AVRCP_START_PACKET: 514 pos += 2; 515 browsing_connection->num_packets = 1; 516 if (avctp_packet_type == AVRCP_START_PACKET){ 517 browsing_connection->num_packets = packet[pos++]; 518 } 519 if ((pos + 4) > size){ 520 browsing_connection->state = AVCTP_CONNECTION_OPENED; 521 avrcp_browsing_controller_emit_failed(avrcp_controller_context.browsing_avrcp_callback, channel, AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND, ERROR_CODE_SUCCESS); 522 return; 523 } 524 browsing_connection->pdu_id = packet[pos++]; 525 pos += 2; 526 browsing_connection->browsing_status = packet[pos++]; 527 if (browsing_connection->browsing_status != AVRCP_BROWSING_ERROR_CODE_SUCCESS){ 528 browsing_connection->state = AVCTP_CONNECTION_OPENED; 529 avrcp_browsing_controller_emit_failed(avrcp_controller_context.browsing_avrcp_callback, channel, browsing_connection->browsing_status, ERROR_CODE_SUCCESS); 530 return; 531 } 532 break; 533 default: 534 break; 535 } 536 537 uint32_t i; 538 uint8_t folder_depth; 539 540 switch(browsing_connection->pdu_id){ 541 case AVRCP_PDU_ID_CHANGE_PATH: 542 break; 543 case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER: 544 break; 545 case AVRCP_PDU_ID_GET_TOTAL_NUMBER_OF_ITEMS: 546 break; 547 case AVRCP_PDU_ID_SET_BROWSED_PLAYER: 548 browsing_connection->uid_counter = big_endian_read_16(packet, pos); 549 pos += 2; 550 // num_items 551 pos += 4; 552 // charset 553 pos += 2; 554 folder_depth = packet[pos++]; 555 556 for (i = 0; i < folder_depth; i++){ 557 uint16_t folder_name_length = big_endian_read_16(packet, pos); 558 pos += 2; 559 // reuse packet and add data type as a header 560 packet[pos-1] = AVRCP_BROWSING_MEDIA_ROOT_FOLDER; 561 (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos-1, folder_name_length+1); 562 pos += folder_name_length; 563 } 564 break; 565 566 case AVRCP_PDU_ID_GET_FOLDER_ITEMS:{ 567 switch (avctp_packet_type){ 568 case AVRCP_SINGLE_PACKET: 569 case AVRCP_START_PACKET: 570 avrcp_parser_reset(browsing_connection); 571 browsing_connection->uid_counter = big_endian_read_16(packet, pos); 572 pos += 2; 573 browsing_connection->num_items = big_endian_read_16(packet, pos); //num_items 574 pos += 2; 575 avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection); 576 break; 577 578 case AVRCP_CONTINUE_PACKET: 579 avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection); 580 break; 581 582 case AVRCP_END_PACKET: 583 avrcp_browsing_parse_and_emit_element_attrs(packet+pos, size-pos, browsing_connection); 584 avrcp_parser_reset(browsing_connection); 585 break; 586 default: 587 break; 588 } 589 break; 590 } 591 case AVRCP_PDU_ID_SEARCH: 592 browsing_connection->uid_counter = big_endian_read_16(packet, pos); 593 pos += 2; 594 break; 595 case AVRCP_PDU_ID_GET_ITEM_ATTRIBUTES: 596 packet[pos-1] = AVRCP_BROWSING_MEDIA_ELEMENT_ITEM_ATTRIBUTE; 597 (*avrcp_controller_context.browsing_avrcp_callback)(AVRCP_BROWSING_DATA_PACKET, channel, packet+pos-1, size - pos + 1); 598 break; 599 default: 600 log_info(" not parsed pdu ID 0x%02x", browsing_connection->pdu_id); 601 break; 602 } 603 604 switch (avctp_packet_type){ 605 case AVRCP_SINGLE_PACKET: 606 case AVRCP_END_PACKET: 607 browsing_connection->state = AVCTP_CONNECTION_OPENED; 608 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); 609 break; 610 default: 611 break; 612 } 613 break; 614 615 case HCI_EVENT_PACKET: 616 switch (hci_event_packet_get_type(packet)){ 617 case L2CAP_EVENT_CAN_SEND_NOW: 618 browsing_connection = get_avrcp_browsing_connection_for_l2cap_cid_for_role(AVRCP_CONTROLLER,channel); 619 if (!browsing_connection) break; 620 avrcp_browsing_controller_handle_can_send_now(browsing_connection); 621 break; 622 default: 623 avrcp_browser_packet_handler(packet_type, channel, packet, size, &avrcp_controller_context); 624 break; 625 } 626 break; 627 628 default: 629 break; 630 } 631 } 632 633 void avrcp_browsing_controller_init(void){ 634 avrcp_controller_context.browsing_packet_handler = avrcp_browsing_controller_packet_handler; 635 l2cap_register_service(&avrcp_browsing_controller_packet_handler, PSM_AVCTP_BROWSING, 0xffff, gap_get_security_level()); 636 } 637 638 void avrcp_browsing_controller_register_packet_handler(btstack_packet_handler_t callback){ 639 btstack_assert(callback != NULL); 640 avrcp_controller_context.browsing_avrcp_callback = callback; 641 } 642 643 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){ 644 return avrcp_browsing_connect(bd_addr, AVRCP_CONTROLLER, avrcp_browsing_controller_packet_handler, ertm_buffer, size, ertm_config, avrcp_browsing_cid); 645 } 646 647 uint8_t avrcp_browsing_controller_disconnect(uint16_t avrcp_browsing_cid){ 648 avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid); 649 if (!avrcp_connection){ 650 log_error("avrcp_browsing_controller_disconnect: could not find a connection."); 651 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 652 } 653 if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 654 655 l2cap_disconnect(avrcp_connection->browsing_connection->l2cap_browsing_cid, 0); 656 return ERROR_CODE_SUCCESS; 657 } 658 659 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){ 660 avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid); 661 if (!avrcp_connection){ 662 log_error("avrcp_browsing_controller_decline_incoming_connection: could not find a connection."); 663 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 664 } 665 if (!avrcp_connection->browsing_connection){ 666 log_error("avrcp_browsing_controller_decline_incoming_connection: no browsing connection."); 667 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 668 } 669 670 if (avrcp_connection->browsing_connection->state != AVCTP_CONNECTION_W4_ERTM_CONFIGURATION){ 671 log_error("avrcp_browsing_controller_decline_incoming_connection: browsing connection in a wrong state."); 672 return ERROR_CODE_COMMAND_DISALLOWED; 673 } 674 675 avrcp_connection->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED; 676 avrcp_connection->browsing_connection->ertm_buffer = ertm_buffer; 677 avrcp_connection->browsing_connection->ertm_buffer_size = size; 678 (void)memcpy(&avrcp_connection->browsing_connection->ertm_config, 679 ertm_config, sizeof(l2cap_ertm_config_t)); 680 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); 681 return ERROR_CODE_SUCCESS; 682 } 683 684 uint8_t avrcp_browsing_controller_decline_incoming_connection(uint16_t avrcp_browsing_cid){ 685 avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid); 686 if (!avrcp_connection){ 687 log_error("avrcp_browsing_controller_decline_incoming_connection: could not find a connection."); 688 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 689 } 690 if (!avrcp_connection->browsing_connection) return ERROR_CODE_SUCCESS; 691 if (avrcp_connection->browsing_connection->state > AVCTP_CONNECTION_W4_ERTM_CONFIGURATION) return ERROR_CODE_COMMAND_DISALLOWED; 692 693 l2cap_decline_connection(avrcp_connection->browsing_connection->l2cap_browsing_cid); 694 // free connection 695 btstack_memory_avrcp_browsing_connection_free(avrcp_connection->browsing_connection); 696 avrcp_connection->browsing_connection = NULL; 697 return ERROR_CODE_SUCCESS; 698 } 699 700 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){ 701 avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid); 702 if (!avrcp_connection){ 703 log_error("avrcp_browsing_controller_get_item_attributes: could not find a connection."); 704 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 705 } 706 avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection; 707 if (connection->state != AVCTP_CONNECTION_OPENED){ 708 log_error("avrcp_browsing_controller_get_item_attributes: connection in wrong state %d, expected %d.", connection->state, AVCTP_CONNECTION_OPENED); 709 return ERROR_CODE_COMMAND_DISALLOWED; 710 } 711 712 connection->get_item_attributes = 1; 713 connection->scope = scope; 714 (void)memcpy(connection->folder_uid, uid, 8); 715 connection->uid_counter = uid_counter; 716 connection->attr_bitmap = attr_bitmap; 717 718 avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); 719 return ERROR_CODE_SUCCESS; 720 } 721 722 /** 723 * @brief Retrieve a listing of the contents of a folder. 724 * @param scope 0-player list, 1-virtual file system, 2-search, 3-now playing 725 * @param start_item 726 * @param end_item 727 * @param attribute_count 728 * @param attribute_list 729 **/ 730 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){ 731 avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid); 732 if (!avrcp_connection){ 733 log_error("avrcp_browsing_controller_disconnect: could not find a connection."); 734 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 735 } 736 avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection; 737 if (connection->state != AVCTP_CONNECTION_OPENED) { 738 log_error("avrcp_browsing_controller_get_folder_items: connection in wrong state %d, expected %d.", connection->state, AVCTP_CONNECTION_OPENED); 739 return ERROR_CODE_COMMAND_DISALLOWED; 740 } 741 742 connection->get_folder_items = 1; 743 connection->scope = scope; 744 connection->start_item = start_item; 745 connection->end_item = end_item; 746 connection->attr_bitmap = attr_bitmap; 747 748 avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); 749 return ERROR_CODE_SUCCESS; 750 } 751 752 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){ 753 return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_LIST, start_item, end_item, attr_bitmap); 754 } 755 756 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){ 757 // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 1, 0, 0xFFFFFFFF, attr_bitmap); 758 return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_MEDIA_PLAYER_VIRTUAL_FILESYSTEM, start_item, end_item, attr_bitmap); 759 } 760 761 uint8_t avrcp_browsing_controller_browse_media(uint16_t avrcp_browsing_cid, uint32_t start_item, uint32_t end_item, uint32_t attr_bitmap){ 762 // return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, 2, 0, 0xFFFFFFFF, 0, NULL); 763 return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_SEARCH, start_item, end_item, attr_bitmap); 764 } 765 766 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){ 767 return avrcp_browsing_controller_get_folder_items(avrcp_browsing_cid, AVRCP_BROWSING_NOW_PLAYING, start_item, end_item, attr_bitmap); 768 } 769 770 771 uint8_t avrcp_browsing_controller_set_browsed_player(uint16_t avrcp_browsing_cid, uint16_t browsed_player_id){ 772 avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid); 773 if (!avrcp_connection){ 774 log_error("avrcp_browsing_controller_change_path: could not find a connection."); 775 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 776 } 777 778 avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection; 779 if (connection->state != AVCTP_CONNECTION_OPENED){ 780 log_error("avrcp_browsing_controller_change_path: connection in wrong state."); 781 return ERROR_CODE_COMMAND_DISALLOWED; 782 } 783 784 connection->set_browsed_player_id = 1; 785 connection->browsed_player_id = browsed_player_id; 786 avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); 787 return ERROR_CODE_SUCCESS; 788 } 789 790 /** 791 * @brief Retrieve a listing of the contents of a folder. 792 * @param direction 0-folder up, 1-folder down 793 * @param folder_uid 8 bytes long 794 **/ 795 uint8_t avrcp_browsing_controller_change_path(uint16_t avrcp_browsing_cid, uint8_t direction, uint8_t * folder_uid){ 796 avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid); 797 if (!avrcp_connection){ 798 log_error("avrcp_browsing_controller_change_path: could not find a connection."); 799 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 800 } 801 802 avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection; 803 804 if ((connection == NULL) || (connection->state != AVCTP_CONNECTION_OPENED)){ 805 log_error("avrcp_browsing_controller_change_path: connection in wrong state."); 806 return ERROR_CODE_COMMAND_DISALLOWED; 807 } 808 809 if (!connection->browsed_player_id){ 810 log_error("avrcp_browsing_controller_change_path: no browsed player set."); 811 return ERROR_CODE_COMMAND_DISALLOWED; 812 } 813 connection->change_path = 1; 814 connection->direction = direction; 815 memset(connection->folder_uid, 0, 8); 816 if (folder_uid){ 817 (void)memcpy(connection->folder_uid, folder_uid, 8); 818 } 819 820 avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); 821 return ERROR_CODE_SUCCESS; 822 } 823 824 uint8_t avrcp_browsing_controller_go_up_one_level(uint16_t avrcp_browsing_cid){ 825 return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 0, NULL); 826 } 827 828 uint8_t avrcp_browsing_controller_go_down_one_level(uint16_t avrcp_browsing_cid, uint8_t * folder_uid){ 829 return avrcp_browsing_controller_change_path(avrcp_browsing_cid, 1, folder_uid); 830 } 831 832 uint8_t avrcp_browsing_controller_search(uint16_t avrcp_browsing_cid, uint16_t search_str_len, char * search_str){ 833 avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid); 834 if (!avrcp_connection){ 835 log_error("avrcp_browsing_controller_change_path: could not find a connection."); 836 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 837 } 838 839 avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection; 840 841 if ((connection == NULL) || (connection->state != AVCTP_CONNECTION_OPENED)){ 842 log_error("avrcp_browsing_controller_change_path: connection in wrong state."); 843 return ERROR_CODE_COMMAND_DISALLOWED; 844 } 845 846 if (!connection->browsed_player_id){ 847 log_error("avrcp_browsing_controller_change_path: no browsed player set."); 848 return ERROR_CODE_COMMAND_DISALLOWED; 849 } 850 if (!search_str || (search_str_len == 0)){ 851 return AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND; 852 } 853 854 connection->search = 1; 855 856 connection->search_str_len = btstack_min(search_str_len, sizeof(connection->search_str)-1); 857 memset(connection->search_str, 0, sizeof(connection->search_str)); 858 (void)memcpy(connection->search_str, search_str, 859 connection->search_str_len); 860 avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); 861 return ERROR_CODE_SUCCESS; 862 } 863 864 uint8_t avrcp_browsing_controller_get_total_nr_items_for_scope(uint16_t avrcp_browsing_cid, avrcp_browsing_scope_t scope){ 865 avrcp_connection_t * avrcp_connection = get_avrcp_connection_for_browsing_cid_for_role(AVRCP_CONTROLLER, avrcp_browsing_cid); 866 if (!avrcp_connection){ 867 log_error("avrcp_browsing_controller_change_path: could not find a connection."); 868 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 869 } 870 871 avrcp_browsing_connection_t * connection = avrcp_connection->browsing_connection; 872 873 if ((connection == NULL) || (connection->state != AVCTP_CONNECTION_OPENED)){ 874 log_error("avrcp_browsing_controller_change_path: connection in wrong state."); 875 return ERROR_CODE_COMMAND_DISALLOWED; 876 } 877 878 if (!connection->browsed_player_id){ 879 log_error("avrcp_browsing_controller_change_path: no browsed player set."); 880 return ERROR_CODE_COMMAND_DISALLOWED; 881 } 882 connection->get_total_nr_items = 1; 883 connection->get_total_nr_items_scope = scope; 884 avrcp_request_can_send_now(avrcp_connection, connection->l2cap_browsing_cid); 885 return ERROR_CODE_SUCCESS; 886 } 887