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_target.c" 39 40 #include <stdint.h> 41 #include <string.h> 42 #include <inttypes.h> 43 44 #include "btstack.h" 45 #include "classic/avrcp.h" 46 47 #define AVRCP_ATTR_HEADER_LEN 8 48 49 static const uint8_t AVRCP_NOTIFICATION_TRACK_SELECTED[] = {0,0,0,0,0,0,0,0}; 50 static const uint8_t AVRCP_NOTIFICATION_TRACK_NOT_SELECTED[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; 51 52 avrcp_context_t avrcp_target_context; 53 54 static int avrcp_target_supports_browsing(uint16_t target_supported_features){ 55 return target_supported_features & AVRCP_FEATURE_MASK_BROWSING; 56 } 57 58 void avrcp_target_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name){ 59 avrcp_create_sdp_record(0, service, service_record_handle, avrcp_target_supports_browsing(supported_features), supported_features, service_name, service_provider_name); 60 } 61 62 static void avrcp_target_emit_operation(btstack_packet_handler_t callback, uint16_t avrcp_cid, avrcp_operation_id_t operation_id, uint8_t operands_length, uint8_t operand){ 63 btstack_assert(callback != NULL); 64 65 uint8_t event[8]; 66 int pos = 0; 67 event[pos++] = HCI_EVENT_AVRCP_META; 68 event[pos++] = sizeof(event) - 2; 69 event[pos++] = AVRCP_SUBEVENT_OPERATION; 70 little_endian_store_16(event, pos, avrcp_cid); 71 pos += 2; 72 event[pos++] = operation_id; 73 event[pos++] = operands_length; 74 event[pos++] = operand; 75 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 76 } 77 78 static void avrcp_target_emit_volume_changed(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t absolute_volume){ 79 btstack_assert(callback != NULL); 80 81 uint8_t event[7]; 82 int offset = 0; 83 event[offset++] = HCI_EVENT_AVRCP_META; 84 event[offset++] = sizeof(event) - 2; 85 event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED; 86 little_endian_store_16(event, offset, avrcp_cid); 87 offset += 2; 88 event[offset++] = AVRCP_CTYPE_NOTIFY; 89 event[offset++] = absolute_volume; 90 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 91 } 92 93 static void avrcp_target_emit_respond_vendor_dependent_query(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t subevent_id){ 94 btstack_assert(callback != NULL); 95 96 uint8_t event[5]; 97 int pos = 0; 98 event[pos++] = HCI_EVENT_AVRCP_META; 99 event[pos++] = sizeof(event) - 2; 100 event[pos++] = subevent_id; 101 little_endian_store_16(event, pos, avrcp_cid); 102 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 103 } 104 105 // returns number of bytes stored 106 static uint16_t avrcp_target_pack_single_element_header(uint8_t * packet, uint16_t pos, avrcp_media_attribute_id_t attr_id, uint16_t attr_value_size){ 107 btstack_assert(attr_id >= 1); 108 btstack_assert(attr_id <= AVRCP_MEDIA_ATTR_COUNT); 109 110 big_endian_store_32(packet, pos, attr_id); 111 big_endian_store_16(packet, pos+4, RFC2978_CHARSET_MIB_UTF8); 112 big_endian_store_16(packet, pos+6, attr_value_size); 113 return 8; 114 } 115 116 // returns number of bytes stored 117 static uint16_t avrcp_target_pack_single_element_attribute_number(uint8_t * packet, uint16_t pos, avrcp_media_attribute_id_t attr_id, uint32_t value){ 118 uint16_t attr_value_length = sprintf((char *)(packet+pos+8), "%0" PRIu32, value); 119 (void) avrcp_target_pack_single_element_header(packet, pos, attr_id, attr_value_length); 120 return 8 + attr_value_length; 121 } 122 123 // returns number of bytes stored 124 static uint16_t avrcp_target_pack_single_element_attribute_string_fragment(uint8_t * packet, uint16_t pos, avrcp_media_attribute_id_t attr_id, uint8_t * attr_value, uint16_t attr_value_to_copy, uint16_t attr_value_size, bool header){ 125 if (attr_value_size == 0) return 0; 126 uint16_t bytes_stored = 0; 127 if (header){ 128 bytes_stored += avrcp_target_pack_single_element_header(packet, pos, attr_id, attr_value_size); 129 } 130 (void)memcpy(packet + pos + bytes_stored, attr_value, attr_value_to_copy); 131 bytes_stored += attr_value_to_copy; 132 return bytes_stored; 133 } 134 135 static int avrcp_target_abort_continue_response(uint16_t cid, avrcp_connection_t * connection){ 136 uint16_t pos = 0; 137 l2cap_reserve_packet_buffer(); 138 uint8_t * packet = l2cap_get_outgoing_buffer(); 139 140 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 141 connection->command_type = AVRCP_CTYPE_RESPONSE_ACCEPTED; 142 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 143 connection->subunit_id = AVRCP_SUBUNIT_ID; 144 145 packet[pos++] = (connection->transaction_id << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0; 146 // Profile IDentifier (PID) 147 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 148 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 149 150 // command_type 151 packet[pos++] = connection->command_type; 152 // subunit_type | subunit ID 153 packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id; 154 // opcode 155 packet[pos++] = (uint8_t)connection->command_opcode; 156 157 // company id is 3 bytes long 158 big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID); 159 pos += 3; 160 161 packet[pos++] = AVRCP_PDU_ID_REQUEST_ABORT_CONTINUING_RESPONSE; 162 163 // reserve byte for packet type 164 packet[pos++] = AVRCP_SINGLE_PACKET; 165 big_endian_store_16(packet, pos, 0); 166 pos += 2; 167 return l2cap_send_prepared(cid, pos); 168 } 169 170 static int avrcp_target_send_now_playing_info(uint16_t cid, avrcp_connection_t * connection){ 171 uint16_t pos = 0; 172 l2cap_reserve_packet_buffer(); 173 uint8_t * packet = l2cap_get_outgoing_buffer(); 174 uint16_t size = l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid); 175 176 packet[pos++] = (connection->transaction_id << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0; 177 // Profile IDentifier (PID) 178 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 179 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 180 181 // command_type 182 packet[pos++] = connection->command_type; 183 // subunit_type | subunit ID 184 packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id; 185 // opcode 186 packet[pos++] = (uint8_t)connection->command_opcode; 187 188 // company id is 3 bytes long 189 big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID); 190 pos += 3; 191 192 packet[pos++] = AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES; 193 194 // reserve byte for packet type 195 uint8_t pos_packet_type = pos; 196 pos++; 197 198 uint16_t playing_info_buffer_len_position = pos; 199 pos += 2; 200 if (connection->next_attr_id == AVRCP_MEDIA_ATTR_NONE){ 201 packet[pos_packet_type] = AVRCP_SINGLE_PACKET; 202 connection->packet_type = AVRCP_SINGLE_PACKET; 203 packet[pos++] = count_set_bits_uint32(connection->now_playing_info_attr_bitmap); 204 connection->next_attr_id = AVRCP_MEDIA_ATTR_ALL; 205 } 206 207 uint8_t fragmented = 0; 208 int num_free_bytes = size - pos - 2; 209 uint8_t MAX_NUMBER_ATTR_LEN = 10; 210 211 while (!fragmented && (num_free_bytes > 0) && (connection->next_attr_id <= AVRCP_MEDIA_ATTR_SONG_LENGTH_MS)){ 212 avrcp_media_attribute_id_t attr_id = connection->next_attr_id; 213 int attr_index = attr_id - 1; 214 215 if (connection->now_playing_info_attr_bitmap & (1 << attr_id)){ 216 int num_written_bytes = 0; 217 int num_bytes_to_write = 0; 218 switch (attr_id){ 219 case AVRCP_MEDIA_ATTR_ALL: 220 case AVRCP_MEDIA_ATTR_NONE: 221 break; 222 case AVRCP_MEDIA_ATTR_TRACK: 223 num_bytes_to_write = AVRCP_ATTR_HEADER_LEN + MAX_NUMBER_ATTR_LEN; 224 if (num_free_bytes >= num_bytes_to_write){ 225 num_written_bytes = avrcp_target_pack_single_element_attribute_number(packet, pos, attr_id, connection->track_nr); 226 break; 227 } 228 fragmented = 1; 229 connection->attribute_value_offset = 0; 230 break; 231 case AVRCP_MEDIA_ATTR_TOTAL_NUM_ITEMS: 232 num_bytes_to_write = AVRCP_ATTR_HEADER_LEN + MAX_NUMBER_ATTR_LEN; 233 if (num_free_bytes >= num_bytes_to_write){ 234 num_written_bytes = avrcp_target_pack_single_element_attribute_number(packet, pos, attr_id, connection->total_tracks); 235 break; 236 } 237 fragmented = 1; 238 connection->attribute_value_offset = 0; 239 break; 240 case AVRCP_MEDIA_ATTR_SONG_LENGTH_MS: 241 num_bytes_to_write = AVRCP_ATTR_HEADER_LEN + MAX_NUMBER_ATTR_LEN; 242 if (num_free_bytes >= num_bytes_to_write){ 243 num_written_bytes = avrcp_target_pack_single_element_attribute_number(packet, pos, attr_id, connection->song_length_ms); 244 break; 245 } 246 fragmented = 1; 247 connection->attribute_value_offset = 0; 248 break; 249 default:{ 250 bool header = connection->attribute_value_offset == 0; 251 uint8_t * attr_value = (uint8_t *) (connection->now_playing_info[attr_index].value + connection->attribute_value_offset); 252 uint16_t attr_value_len = connection->now_playing_info[attr_index].len - connection->attribute_value_offset; 253 254 num_bytes_to_write = attr_value_len + (header * AVRCP_ATTR_HEADER_LEN); 255 if (num_bytes_to_write <= num_free_bytes){ 256 connection->attribute_value_offset = 0; 257 num_written_bytes = num_bytes_to_write; 258 avrcp_target_pack_single_element_attribute_string_fragment(packet, pos, attr_id, attr_value, attr_value_len, connection->now_playing_info[attr_index].len, header); 259 break; 260 } 261 fragmented = 1; 262 num_written_bytes = num_free_bytes; 263 attr_value_len = num_free_bytes - (header * AVRCP_ATTR_HEADER_LEN); 264 avrcp_target_pack_single_element_attribute_string_fragment(packet, pos, attr_id, attr_value, attr_value_len, connection->now_playing_info[attr_index].len, header); 265 connection->attribute_value_offset += attr_value_len; 266 break; 267 } 268 } 269 pos += num_written_bytes; 270 num_free_bytes -= num_written_bytes; 271 } 272 if (!fragmented){ 273 // C++ compatible version of connection->next_attr_id++ 274 connection->next_attr_id = (avrcp_media_attribute_id_t) (((int) connection->next_attr_id) + 1); 275 } 276 } 277 278 if (fragmented){ 279 switch (connection->packet_type){ 280 case AVRCP_SINGLE_PACKET: 281 connection->packet_type = AVRCP_START_PACKET; 282 break; 283 default: 284 connection->packet_type = AVRCP_CONTINUE_PACKET; 285 break; 286 } 287 } else { 288 if (connection->next_attr_id >= AVRCP_MEDIA_ATTR_SONG_LENGTH_MS){ // DONE 289 if (connection->packet_type != AVRCP_SINGLE_PACKET){ 290 connection->packet_type = AVRCP_END_PACKET; 291 } 292 } 293 } 294 packet[pos_packet_type] = connection->packet_type; 295 // store attr value length 296 big_endian_store_16(packet, playing_info_buffer_len_position, pos - playing_info_buffer_len_position - 2); 297 return l2cap_send_prepared(cid, size); 298 } 299 300 301 302 static int avrcp_target_send_response(uint16_t cid, avrcp_connection_t * connection){ 303 int pos = 0; 304 l2cap_reserve_packet_buffer(); 305 uint8_t * packet = l2cap_get_outgoing_buffer(); 306 307 // transport header 308 // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) 309 310 // TODO: check for fragmentation 311 connection->packet_type = AVRCP_SINGLE_PACKET; 312 313 packet[pos++] = (connection->transaction_id << 4) | (connection->packet_type << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0; 314 // Profile IDentifier (PID) 315 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 316 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 317 // command_type 318 packet[pos++] = connection->command_type; 319 // subunit_type | subunit ID 320 packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id; 321 // opcode 322 packet[pos++] = (uint8_t)connection->command_opcode; 323 324 (void)memcpy(packet + pos, connection->cmd_operands, 325 connection->cmd_operands_length); 326 pos += connection->cmd_operands_length; 327 328 return l2cap_send_prepared(cid, pos); 329 } 330 331 static void avrcp_target_response_setup(avrcp_connection_t * connection, avrcp_command_type_t command_type, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id, 332 avrcp_command_opcode_t opcode){ 333 connection->command_type = command_type; 334 connection->subunit_type = subunit_type; 335 connection->subunit_id = subunit_id; 336 connection->command_opcode = opcode; 337 } 338 339 static uint8_t avrcp_target_response_accept(avrcp_connection_t * connection, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id, avrcp_command_opcode_t opcode, avrcp_pdu_id_t pdu_id, uint8_t status){ 340 // AVRCP_CTYPE_RESPONSE_REJECTED 341 avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_ACCEPTED, subunit_type, subunit_id, opcode); 342 // company id is 3 bytes long 343 int pos = connection->cmd_operands_length; 344 connection->cmd_operands[pos++] = pdu_id; 345 connection->cmd_operands[pos++] = 0; 346 // param length 347 big_endian_store_16(connection->cmd_operands, pos, 1); 348 pos += 2; 349 connection->cmd_operands[pos++] = status; 350 connection->cmd_operands_length = pos; 351 connection->accept_response = 1; 352 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 353 return ERROR_CODE_SUCCESS; 354 } 355 356 static uint8_t avrcp_target_response_reject(avrcp_connection_t * connection, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id, avrcp_command_opcode_t opcode, avrcp_pdu_id_t pdu_id, avrcp_status_code_t status){ 357 // AVRCP_CTYPE_RESPONSE_REJECTED 358 avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_REJECTED, subunit_type, subunit_id, opcode); 359 // company id is 3 bytes long 360 int pos = connection->cmd_operands_length; 361 connection->cmd_operands[pos++] = pdu_id; 362 connection->cmd_operands[pos++] = 0; 363 // param length 364 big_endian_store_16(connection->cmd_operands, pos, 1); 365 pos += 2; 366 connection->cmd_operands[pos++] = status; 367 connection->cmd_operands_length = pos; 368 connection->state = AVCTP_W2_SEND_RESPONSE; 369 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 370 return ERROR_CODE_SUCCESS; 371 } 372 373 static uint8_t avrcp_target_response_not_implemented(avrcp_connection_t * connection, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id, avrcp_command_opcode_t opcode, avrcp_pdu_id_t pdu_id, uint8_t event_id){ 374 avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_NOT_IMPLEMENTED, subunit_type, subunit_id, opcode); 375 // company id is 3 bytes long 376 int pos = connection->cmd_operands_length; 377 connection->cmd_operands[pos++] = pdu_id; 378 connection->cmd_operands[pos++] = 0; 379 // param length 380 big_endian_store_16(connection->cmd_operands, pos, 1); 381 pos += 2; 382 connection->cmd_operands[pos++] = event_id; 383 connection->cmd_operands_length = pos; 384 385 connection->state = AVCTP_W2_SEND_RESPONSE; 386 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 387 return ERROR_CODE_SUCCESS; 388 } 389 390 static uint8_t avrcp_target_response_vendor_dependent_interim(avrcp_connection_t * connection, avrcp_pdu_id_t pdu_id, uint8_t event_id, const uint8_t * value, uint16_t value_len){ 391 392 // company id is 3 bytes long 393 int pos = connection->cmd_operands_length; 394 connection->cmd_operands[pos++] = pdu_id; 395 connection->cmd_operands[pos++] = 0; 396 // param length 397 big_endian_store_16(connection->cmd_operands, pos, 1 + value_len); 398 pos += 2; 399 connection->cmd_operands[pos++] = event_id; 400 if (value && (value_len > 0)){ 401 (void)memcpy(connection->cmd_operands + pos, value, value_len); 402 pos += value_len; 403 } 404 connection->cmd_operands_length = pos; 405 connection->state = AVCTP_W2_SEND_RESPONSE; 406 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 407 return ERROR_CODE_SUCCESS; 408 } 409 410 static uint8_t avrcp_target_response_addressed_player_changed_interim(avrcp_connection_t * connection, avrcp_subunit_type_t subunit_type, avrcp_subunit_id_t subunit_id, avrcp_command_opcode_t opcode, avrcp_pdu_id_t pdu_id){ 411 avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode); 412 413 // company id is 3 bytes long 414 int pos = connection->cmd_operands_length; 415 connection->cmd_operands[pos++] = pdu_id; 416 connection->cmd_operands[pos++] = 0; 417 // param length 418 big_endian_store_16(connection->cmd_operands, pos, 5); 419 pos += 2; 420 connection->cmd_operands[pos++] = AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED; 421 big_endian_read_16( &connection->cmd_operands[pos], connection->addressed_player_id); 422 pos += 2; 423 big_endian_read_16( &connection->cmd_operands[pos], connection->uid_counter); 424 pos += 2; 425 426 connection->cmd_operands_length = pos; 427 connection->state = AVCTP_W2_SEND_RESPONSE; 428 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 429 return ERROR_CODE_SUCCESS; 430 } 431 432 static uint8_t avrcp_target_pass_through_response(uint16_t avrcp_cid, avrcp_command_type_t cmd_type, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){ 433 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 434 if (!connection){ 435 log_error("Could not find a connection."); 436 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 437 } 438 avrcp_target_response_setup(connection, cmd_type, AVRCP_SUBUNIT_TYPE_PANEL, AVRCP_SUBUNIT_ID, AVRCP_CMD_OPCODE_PASS_THROUGH); 439 440 int pos = 0; 441 connection->cmd_operands[pos++] = opid; 442 connection->cmd_operands[pos++] = operands_length; 443 if (operands_length == 1){ 444 connection->cmd_operands[pos++] = operand; 445 } 446 connection->cmd_operands_length = pos; 447 448 connection->state = AVCTP_W2_SEND_RESPONSE; 449 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 450 return ERROR_CODE_SUCCESS; 451 } 452 453 uint8_t avrcp_target_operation_rejected(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){ 454 return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_REJECTED, opid, operands_length, operand); 455 } 456 457 uint8_t avrcp_target_operation_accepted(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){ 458 return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_ACCEPTED, opid, operands_length, operand); 459 } 460 461 uint8_t avrcp_target_operation_not_implemented(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){ 462 return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_ACCEPTED, opid, operands_length, operand); 463 } 464 465 void avrcp_target_set_unit_info(uint16_t avrcp_cid, avrcp_subunit_type_t unit_type, uint32_t company_id){ 466 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 467 if (!connection){ 468 log_error("avrcp_target_set_unit_info: could not find a connection."); 469 return; 470 } 471 connection->unit_type = unit_type; 472 connection->company_id = company_id; 473 } 474 475 void avrcp_target_set_subunit_info(uint16_t avrcp_cid, avrcp_subunit_type_t subunit_type, const uint8_t * subunit_info_data, uint16_t subunit_info_data_size){ 476 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 477 if (!connection){ 478 log_error("avrcp_target_set_subunit_info: could not find a connection."); 479 return; 480 } 481 connection->subunit_info_type = subunit_type; 482 connection->subunit_info_data = subunit_info_data; 483 connection->subunit_info_data_size = subunit_info_data_size; 484 } 485 486 static uint8_t avrcp_target_unit_info(avrcp_connection_t * connection){ 487 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 488 489 uint8_t unit = 0; 490 connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE; 491 connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique 492 connection->subunit_id = AVRCP_SUBUNIT_ID_IGNORE; 493 connection->command_opcode = AVRCP_CMD_OPCODE_UNIT_INFO; 494 495 connection->cmd_operands_length = 5; 496 connection->cmd_operands[0] = 0x07; 497 connection->cmd_operands[1] = (connection->unit_type << 4) | unit; 498 // company id is 3 bytes long 499 big_endian_store_32(connection->cmd_operands, 2, connection->company_id); 500 501 connection->state = AVCTP_W2_SEND_RESPONSE; 502 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 503 return ERROR_CODE_SUCCESS; 504 } 505 506 507 static uint8_t avrcp_target_subunit_info(avrcp_connection_t * connection, uint8_t offset){ 508 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 509 if ((offset - 4) > connection->subunit_info_data_size) return AVRCP_STATUS_INVALID_PARAMETER; 510 511 connection->command_opcode = AVRCP_CMD_OPCODE_SUBUNIT_INFO; 512 connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE; 513 connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique 514 connection->subunit_id = AVRCP_SUBUNIT_ID_IGNORE; 515 516 uint8_t page = offset / 4; 517 uint8_t extension_code = 7; 518 connection->cmd_operands_length = 5; 519 connection->cmd_operands[0] = (page << 4) | extension_code; 520 521 (void)memcpy(connection->cmd_operands + 1, 522 connection->subunit_info_data + offset, 4); 523 524 connection->state = AVCTP_W2_SEND_RESPONSE; 525 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 526 return ERROR_CODE_SUCCESS; 527 } 528 529 static inline uint8_t avrcp_prepare_vendor_dependent_response(uint16_t avrcp_cid, avrcp_connection_t ** out_connection, avrcp_pdu_id_t pdu_id, uint16_t param_length){ 530 *out_connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 531 if (!*out_connection){ 532 log_error("avrcp tartget: could not find a connection."); 533 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 534 } 535 536 if ((*out_connection)->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 537 (*out_connection)->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 538 (*out_connection)->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE; 539 (*out_connection)->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 540 (*out_connection)->subunit_id = AVRCP_SUBUNIT_ID; 541 542 (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = pdu_id; 543 // reserved 544 (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = 0; 545 // param length 546 big_endian_store_16((*out_connection)->cmd_operands, (*out_connection)->cmd_operands_length, param_length); 547 (*out_connection)->cmd_operands_length += 2; 548 return ERROR_CODE_SUCCESS; 549 } 550 551 static uint8_t avrcp_target_capability(uint16_t avrcp_cid, avrcp_capability_id_t capability_id, uint8_t num_capabilities, const uint8_t *capabilities, uint8_t capabilities_size){ 552 avrcp_connection_t * connection = NULL; 553 uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_CAPABILITIES, 2 + capabilities_size); 554 if (status != ERROR_CODE_SUCCESS) return status; 555 556 connection->cmd_operands[connection->cmd_operands_length++] = capability_id; 557 connection->cmd_operands[connection->cmd_operands_length++] = num_capabilities; 558 (void)memcpy(connection->cmd_operands + connection->cmd_operands_length, 559 capabilities, capabilities_size); 560 connection->cmd_operands_length += capabilities_size; 561 562 connection->state = AVCTP_W2_SEND_RESPONSE; 563 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 564 return ERROR_CODE_SUCCESS; 565 } 566 567 uint8_t avrcp_target_supported_events(uint16_t avrcp_cid, uint8_t num_event_ids, const uint8_t *event_ids, uint8_t event_ids_size){ 568 return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_EVENT, num_event_ids, event_ids, event_ids_size); 569 } 570 571 uint8_t avrcp_target_supported_companies(uint16_t avrcp_cid, uint8_t num_company_ids, const uint8_t *company_ids, uint8_t company_ids_size){ 572 return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_COMPANY, num_company_ids, company_ids, company_ids_size); 573 } 574 575 uint8_t avrcp_target_play_status(uint16_t avrcp_cid, uint32_t song_length_ms, uint32_t song_position_ms, avrcp_playback_status_t play_status){ 576 avrcp_connection_t * connection = NULL; 577 uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_PLAY_STATUS, 11); 578 if (status != ERROR_CODE_SUCCESS) return status; 579 580 big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_length_ms); 581 connection->cmd_operands_length += 4; 582 big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_position_ms); 583 connection->cmd_operands_length += 4; 584 connection->cmd_operands[connection->cmd_operands_length++] = play_status; 585 586 connection->state = AVCTP_W2_SEND_RESPONSE; 587 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 588 return ERROR_CODE_SUCCESS; 589 } 590 591 static uint8_t avrcp_target_now_playing_info(avrcp_connection_t * connection){ 592 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 593 connection->now_playing_info_response = 1; 594 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 595 connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE; 596 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 597 connection->subunit_id = AVRCP_SUBUNIT_ID; 598 599 connection->state = AVCTP_W2_SEND_RESPONSE; 600 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 601 return ERROR_CODE_SUCCESS; 602 } 603 604 static uint8_t avrcp_target_store_media_attr(avrcp_connection_t * connection, avrcp_media_attribute_id_t attr_id, const char * value){ 605 int index = attr_id - 1; 606 if (!value) return AVRCP_STATUS_INVALID_PARAMETER; 607 connection->now_playing_info[index].value = (uint8_t*)value; 608 connection->now_playing_info[index].len = strlen(value); 609 return ERROR_CODE_SUCCESS; 610 } 611 612 uint8_t avrcp_target_set_playback_status(uint16_t avrcp_cid, avrcp_playback_status_t playback_status){ 613 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 614 if (!connection){ 615 log_error("avrcp_unit_info: could not find a connection."); 616 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 617 } 618 if (connection->playback_status == playback_status) return ERROR_CODE_SUCCESS; 619 620 connection->playback_status = playback_status; 621 connection->playback_status_changed = 1; 622 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 623 return ERROR_CODE_SUCCESS; 624 } 625 626 void avrcp_target_set_now_playing_info(uint16_t avrcp_cid, const avrcp_track_t * current_track, uint16_t total_tracks){ 627 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 628 if (!connection){ 629 log_error("avrcp_unit_info: could not find a connection. cid 0x%02x\n", avrcp_cid); 630 return; 631 } 632 if (!current_track){ 633 connection->track_selected = 0; 634 connection->playback_status = AVRCP_PLAYBACK_STATUS_ERROR; 635 return; 636 } 637 (void)memcpy(connection->track_id, current_track->track_id, 8); 638 connection->song_length_ms = current_track->song_length_ms; 639 connection->track_nr = current_track->track_nr; 640 connection->total_tracks = total_tracks; 641 avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_TITLE, current_track->title); 642 avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_ARTIST, current_track->artist); 643 avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_ALBUM, current_track->album); 644 avrcp_target_store_media_attr(connection, AVRCP_MEDIA_ATTR_GENRE, current_track->genre); 645 connection->track_selected = 1; 646 647 if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED)) { 648 connection->track_changed = 1; 649 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 650 } 651 return; 652 } 653 654 uint8_t avrcp_target_track_changed(uint16_t avrcp_cid, uint8_t * track_id){ 655 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 656 if (!connection){ 657 log_error("avrcp_target_track_changed: could not find connection."); 658 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 659 } 660 if (!track_id) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 661 662 if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED)) { 663 connection->track_changed = 1; 664 (void)memcpy(connection->track_id, track_id, 8); 665 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 666 } 667 return ERROR_CODE_SUCCESS; 668 } 669 670 uint8_t avrcp_target_playing_content_changed(uint16_t avrcp_cid){ 671 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 672 if (!connection){ 673 log_error("avrcp_target_playing_content_changed: could not find a connection."); 674 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 675 } 676 if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED)) { 677 connection->playing_content_changed = 1; 678 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 679 } 680 return ERROR_CODE_SUCCESS; 681 } 682 683 uint8_t avrcp_target_addressed_player_changed(uint16_t avrcp_cid, uint16_t player_id, uint16_t uid_counter){ 684 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 685 if (!connection){ 686 log_error("avrcp_unit_info: could not find a connection."); 687 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 688 } 689 if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED)) { 690 connection->uid_counter = uid_counter; 691 connection->addressed_player_id = player_id; 692 } 693 return ERROR_CODE_SUCCESS; 694 } 695 696 uint8_t avrcp_target_battery_status_changed(uint16_t avrcp_cid, avrcp_battery_status_t battery_status){ 697 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 698 if (!connection){ 699 log_error("avrcp_unit_info: could not find a connection."); 700 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 701 } 702 if (connection->battery_status == battery_status) return ERROR_CODE_SUCCESS; 703 if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED)) { 704 connection->battery_status = battery_status; 705 connection->battery_status_changed = 1; 706 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 707 } 708 return ERROR_CODE_SUCCESS; 709 } 710 711 uint8_t avrcp_target_volume_changed(uint16_t avrcp_cid, uint8_t volume_percentage){ 712 avrcp_connection_t * connection = avrcp_get_connection_for_avrcp_cid_for_role(AVRCP_TARGET, avrcp_cid); 713 if (!connection){ 714 log_error("avrcp_unit_info: could not find a connection."); 715 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 716 } 717 connection->volume_percentage = volume_percentage; 718 if (connection->notifications_enabled & (1 << AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED )) { 719 connection->notify_volume_percentage_changed = 1; 720 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 721 } 722 return ERROR_CODE_SUCCESS; 723 } 724 725 static void avrcp_target_set_transaction_label_for_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t notification, uint8_t transaction_label){ 726 if (notification > AVRCP_NOTIFICATION_EVENT_MAX_VALUE) return; 727 connection->notifications_transaction_label[notification] = transaction_label; 728 } 729 730 static uint8_t avrcp_target_get_transaction_label_for_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t notification){ 731 if (notification > AVRCP_NOTIFICATION_EVENT_MAX_VALUE) return 0; 732 return connection->notifications_transaction_label[notification]; 733 } 734 735 static uint8_t avrcp_is_receive_pass_through_cmd(uint8_t operation_id){ 736 return operation_id & 0x80; 737 } 738 739 static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connection_t * connection, uint8_t *packet, uint16_t size){ 740 741 if (size < 6u) return; 742 743 uint16_t pid = 0; 744 uint8_t transport_header = packet[0]; 745 connection->transaction_id = transport_header >> 4; 746 747 avrcp_packet_type_t packet_type = (avrcp_packet_type_t) ((transport_header & 0x0F) >> 2); 748 switch (packet_type){ 749 case AVRCP_SINGLE_PACKET: 750 pid = big_endian_read_16(packet, 1); 751 break; 752 case AVRCP_START_PACKET: 753 pid = big_endian_read_16(packet, 2); 754 break; 755 default: 756 break; 757 } 758 759 switch (packet_type){ 760 case AVRCP_SINGLE_PACKET: 761 case AVRCP_START_PACKET: 762 if (pid != BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL){ 763 log_info("Invalid pid 0x%02x, expected 0x%02x", connection->invalid_pid, BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL); 764 connection->reject_transport_header = 1; 765 connection->invalid_pid = pid; 766 connection->transport_header = (connection->transaction_id << 4) | (AVRCP_SINGLE_PACKET << 2 ) | (AVRCP_RESPONSE_FRAME << 1) | 1; 767 connection->state = AVCTP_W2_SEND_RESPONSE; 768 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 769 return; 770 } 771 break; 772 default: 773 break; 774 } 775 776 if (packet_type != AVRCP_SINGLE_PACKET) return; 777 778 avrcp_subunit_type_t subunit_type = (avrcp_subunit_type_t) (packet[4] >> 3); 779 avrcp_subunit_id_t subunit_id = (avrcp_subunit_id_t) (packet[4] & 0x07); 780 781 avrcp_command_opcode_t opcode = (avrcp_command_opcode_t) avrcp_cmd_opcode(packet,size); 782 783 int pos = 4; 784 uint16_t length; 785 avrcp_pdu_id_t pdu_id; 786 connection->cmd_operands_length = 0; 787 788 switch (opcode){ 789 case AVRCP_CMD_OPCODE_UNIT_INFO: 790 avrcp_target_unit_info(connection); 791 break; 792 case AVRCP_CMD_OPCODE_SUBUNIT_INFO:{ 793 if ((size - pos) < 3) return; 794 uint8_t offset = 4 * (packet[pos+2]>>4); 795 avrcp_target_subunit_info(connection, offset); 796 break; 797 } 798 case AVRCP_CMD_OPCODE_PASS_THROUGH:{ 799 if (size < 9) return; 800 log_info("AVRCP_OPERATION_ID 0x%02x, operands length %d, operand %d", packet[6], packet[7], packet[8]); 801 avrcp_operation_id_t operation_id = (avrcp_operation_id_t) packet[6]; 802 803 if (avrcp_is_receive_pass_through_cmd(operation_id)){ 804 operation_id = (avrcp_operation_id_t) (packet[6] & 0x7F); 805 avrcp_target_operation_accepted(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]); 806 break; 807 } 808 809 switch (operation_id){ 810 case AVRCP_OPERATION_ID_PLAY: 811 case AVRCP_OPERATION_ID_PAUSE: 812 case AVRCP_OPERATION_ID_STOP: 813 case AVRCP_OPERATION_ID_VOLUME_UP: 814 case AVRCP_OPERATION_ID_VOLUME_DOWN: 815 case AVRCP_OPERATION_ID_REWIND: 816 case AVRCP_OPERATION_ID_FAST_FORWARD: 817 case AVRCP_OPERATION_ID_FORWARD: 818 case AVRCP_OPERATION_ID_BACKWARD: 819 case AVRCP_OPERATION_ID_SKIP: 820 case AVRCP_OPERATION_ID_MUTE: 821 case AVRCP_OPERATION_ID_CHANNEL_UP: 822 case AVRCP_OPERATION_ID_CHANNEL_DOWN: 823 case AVRCP_OPERATION_ID_SELECT: 824 case AVRCP_OPERATION_ID_UP: 825 case AVRCP_OPERATION_ID_DOWN: 826 case AVRCP_OPERATION_ID_LEFT: 827 case AVRCP_OPERATION_ID_RIGHT: 828 case AVRCP_OPERATION_ID_ROOT_MENU: 829 avrcp_target_operation_accepted(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]); 830 avrcp_target_emit_operation(avrcp_target_context.avrcp_callback, connection->avrcp_cid, operation_id, packet[7], packet[8]); 831 break; 832 case AVRCP_OPERATION_ID_UNDEFINED: 833 avrcp_target_operation_not_implemented(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]); 834 return; 835 default: 836 avrcp_target_operation_not_implemented(connection->avrcp_cid, (avrcp_operation_id_t) packet[6], packet[7], packet[8]); 837 return; 838 } 839 break; 840 } 841 842 case AVRCP_CMD_OPCODE_VENDOR_DEPENDENT: 843 844 if (size < 13) return; 845 846 // pos = 6 - company id 847 (void)memcpy(connection->cmd_operands, &packet[pos], 3); 848 connection->cmd_operands_length = 3; 849 pos += 3; 850 // pos = 9 851 pdu_id = (avrcp_pdu_id_t) packet[pos++]; 852 // 1 - reserved 853 pos++; 854 // 2-3 param length, 855 length = big_endian_read_16(packet, pos); 856 pos += 2; 857 // pos = 13 858 switch (pdu_id){ 859 case AVRCP_PDU_ID_SET_ADDRESSED_PLAYER:{ 860 if ((pos + 2) > size) return; 861 bool ok = length == 4; 862 if (avrcp_target_context.set_addressed_player_callback != NULL){ 863 uint16_t player_id = big_endian_read_16(packet, pos); 864 ok = avrcp_target_context.set_addressed_player_callback(player_id); 865 } 866 if (ok){ 867 avrcp_target_response_accept(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_SUCCESS); 868 } else { 869 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PLAYER_ID); 870 } 871 break; 872 } 873 case AVRCP_PDU_ID_GET_CAPABILITIES:{ 874 avrcp_capability_id_t capability_id = (avrcp_capability_id_t) packet[pos]; 875 switch (capability_id){ 876 case AVRCP_CAPABILITY_ID_EVENT: 877 avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_EVENT_IDS_QUERY); 878 break; 879 case AVRCP_CAPABILITY_ID_COMPANY: 880 avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_COMPANY_IDS_QUERY); 881 break; 882 default: 883 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER); 884 break; 885 } 886 break; 887 } 888 case AVRCP_PDU_ID_GET_PLAY_STATUS: 889 avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_PLAY_STATUS_QUERY); 890 break; 891 case AVRCP_PDU_ID_REQUEST_ABORT_CONTINUING_RESPONSE: 892 if ((pos + 1) > size) return; 893 connection->cmd_operands[0] = packet[pos]; 894 connection->abort_continue_response = 1; 895 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 896 break; 897 case AVRCP_PDU_ID_REQUEST_CONTINUING_RESPONSE: 898 if ((pos + 1) > size) return; 899 if (packet[pos] != AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES){ 900 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND); 901 return; 902 } 903 connection->now_playing_info_response = 1; 904 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 905 break; 906 case AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES:{ 907 if ((pos + 9) > size) return; 908 uint8_t play_identifier[8]; 909 memset(play_identifier, 0, 8); 910 if (memcmp(&packet[pos], play_identifier, 8) != 0) { 911 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER); 912 return; 913 } 914 pos += 8; 915 uint8_t attribute_count = packet[pos++]; 916 connection->next_attr_id = AVRCP_MEDIA_ATTR_NONE; 917 if (!attribute_count){ 918 connection->now_playing_info_attr_bitmap = 0xFE; 919 } else { 920 int i; 921 connection->now_playing_info_attr_bitmap = 0; 922 if ((pos + attribute_count * 2) > size) return; 923 for (i=0; i < attribute_count; i++){ 924 uint16_t attr_id = big_endian_read_16(packet, pos); 925 pos += 2; 926 connection->now_playing_info_attr_bitmap |= (1 << attr_id); 927 } 928 } 929 log_info("now_playing_info_attr_bitmap 0x%02x", connection->now_playing_info_attr_bitmap); 930 avrcp_target_now_playing_info(connection); 931 break; 932 } 933 case AVRCP_PDU_ID_REGISTER_NOTIFICATION:{ 934 if ((pos + 1) > size) return; 935 avrcp_notification_event_id_t event_id = (avrcp_notification_event_id_t) packet[pos]; 936 uint16_t event_mask = (1 << event_id); 937 avrcp_target_set_transaction_label_for_notification(connection, event_id, connection->transaction_id); 938 939 switch (event_id){ 940 case AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED: 941 connection->notifications_enabled |= event_mask; 942 avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode); 943 if (connection->track_selected){ 944 avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, AVRCP_NOTIFICATION_TRACK_SELECTED, 8); 945 } else { 946 avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, AVRCP_NOTIFICATION_TRACK_NOT_SELECTED, 8); 947 } 948 break; 949 case AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED: 950 connection->notifications_enabled |= event_mask; 951 avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode); 952 avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, (const uint8_t *)&connection->playback_status, 1); 953 break; 954 case AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED: 955 connection->notifications_enabled |= event_mask; 956 avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode); 957 avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, NULL, 0); 958 break; 959 case AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED: 960 connection->notify_volume_percentage_changed = 0; 961 connection->notifications_enabled |= event_mask; 962 avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode); 963 avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, (const uint8_t *)&connection->volume_percentage, 1); 964 break; 965 case AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED: 966 connection->notifications_enabled |= event_mask; 967 avrcp_target_response_setup(connection, AVRCP_CTYPE_RESPONSE_INTERIM, subunit_type, subunit_id, opcode); 968 avrcp_target_response_vendor_dependent_interim(connection, pdu_id, event_id, (const uint8_t *)&connection->battery_status, 1); 969 break; 970 case AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED: 971 case AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED: 972 case AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED: 973 avrcp_target_response_not_implemented(connection, subunit_type, subunit_id, opcode, pdu_id, event_id); 974 return; 975 case AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED: 976 connection->notifications_enabled |= event_mask; 977 avrcp_target_response_addressed_player_changed_interim(connection, subunit_type, subunit_id, opcode, pdu_id); 978 return; 979 default: 980 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER); 981 return; 982 } 983 break; 984 } 985 case AVRCP_PDU_ID_SET_ABSOLUTE_VOLUME: { 986 if (length != 1){ 987 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND); 988 break; 989 } 990 991 if ((pos + 1) > size) return; 992 uint8_t absolute_volume = packet[pos]; 993 if (absolute_volume < 0x80){ 994 connection->volume_percentage = absolute_volume; 995 } 996 avrcp_target_response_accept(connection, subunit_type, subunit_id, opcode, pdu_id, connection->volume_percentage); 997 avrcp_target_emit_volume_changed(avrcp_target_context.avrcp_callback, connection->avrcp_cid, connection->volume_percentage); 998 break; 999 } 1000 default: 1001 log_info("AVRCP target: unhandled pdu id 0x%02x", pdu_id); 1002 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND); 1003 break; 1004 } 1005 break; 1006 default: 1007 log_info("AVRCP target: opcode 0x%02x not implemented", avrcp_cmd_opcode(packet,size)); 1008 break; 1009 } 1010 } 1011 1012 static int avrcp_target_send_notification(uint16_t cid, avrcp_connection_t * connection, avrcp_notification_event_id_t notification_id, uint8_t * value, uint16_t value_len){ 1013 if (!connection){ 1014 log_error("avrcp tartget: could not find a connection."); 1015 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 1016 } 1017 1018 btstack_assert((value_len == 0) || (value != NULL)); 1019 1020 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 1021 connection->command_type = AVRCP_CTYPE_RESPONSE_CHANGED_STABLE; 1022 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 1023 connection->subunit_id = AVRCP_SUBUNIT_ID; 1024 connection->transaction_id = avrcp_target_get_transaction_label_for_notification(connection, notification_id); 1025 1026 uint16_t pos = 0; 1027 l2cap_reserve_packet_buffer(); 1028 uint8_t * packet = l2cap_get_outgoing_buffer(); 1029 1030 // value <= 8 ==> pdu <= 22 < L2CAP Default MTU 1031 btstack_assert((14 + value_len) <= l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid)); 1032 1033 connection->packet_type = AVRCP_SINGLE_PACKET; 1034 packet[pos++] = (connection->transaction_id << 4) | (connection->packet_type << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0; 1035 // Profile IDentifier (PID) 1036 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 1037 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 1038 1039 // command_type 1040 packet[pos++] = connection->command_type; 1041 // subunit_type | subunit ID 1042 packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id; 1043 // opcode 1044 packet[pos++] = (uint8_t)connection->command_opcode; 1045 1046 // company id is 3 bytes long 1047 big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID); 1048 pos += 3; 1049 1050 packet[pos++] = AVRCP_PDU_ID_REGISTER_NOTIFICATION; 1051 packet[pos++] = 0; 1052 1053 big_endian_store_16(packet, pos, value_len); 1054 pos += 2; 1055 packet[pos++] = notification_id; 1056 if (value_len > 0){ 1057 (void)memcpy(packet + pos, value, value_len); 1058 pos += value_len; 1059 } 1060 1061 return l2cap_send_prepared(cid, pos); 1062 } 1063 1064 static void avrcp_target_reset_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t notification_id){ 1065 if (!connection){ 1066 log_error("avrcp tartget: could not find a connection."); 1067 return; 1068 } 1069 connection->notifications_enabled &= ~(1 << notification_id); 1070 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 1071 avrcp_target_set_transaction_label_for_notification(connection, notification_id, 0); 1072 } 1073 1074 static void avrcp_target_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 1075 avrcp_connection_t * connection; 1076 switch (packet_type) { 1077 case L2CAP_DATA_PACKET: 1078 connection = avrcp_get_connection_for_l2cap_signaling_cid_for_role(AVRCP_TARGET, channel); 1079 avrcp_handle_l2cap_data_packet_for_signaling_connection(connection, packet, size); 1080 break; 1081 case HCI_EVENT_PACKET: 1082 switch (hci_event_packet_get_type(packet)){ 1083 case L2CAP_EVENT_CAN_SEND_NOW:{ 1084 connection = avrcp_get_connection_for_l2cap_signaling_cid_for_role(AVRCP_TARGET, channel); 1085 1086 if (connection->accept_response){ 1087 connection->accept_response = 0; 1088 avrcp_target_send_response(connection->l2cap_signaling_cid, connection); 1089 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 1090 return; 1091 } 1092 1093 if (connection->abort_continue_response){ 1094 connection->abort_continue_response = 0; 1095 connection->now_playing_info_response = 0; 1096 avrcp_target_abort_continue_response(connection->l2cap_signaling_cid, connection); 1097 return; 1098 } 1099 1100 if (connection->now_playing_info_response){ 1101 connection->now_playing_info_response = 0; 1102 avrcp_target_send_now_playing_info(connection->l2cap_signaling_cid, connection); 1103 return; 1104 } 1105 1106 if (connection->track_changed){ 1107 connection->track_changed = 0; 1108 avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED, connection->track_id, 8); 1109 avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED); 1110 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 1111 return; 1112 } 1113 1114 if (connection->playback_status_changed){ 1115 connection->playback_status_changed = 0; 1116 uint8_t playback_status = (uint8_t) connection->playback_status; 1117 avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED, &playback_status, 1); 1118 avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED); 1119 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 1120 return; 1121 } 1122 1123 if (connection->playing_content_changed){ 1124 connection->playing_content_changed = 0; 1125 avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED, NULL, 0); 1126 avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED); 1127 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 1128 return; 1129 } 1130 1131 if (connection->battery_status_changed){ 1132 connection->battery_status_changed = 0; 1133 avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED, (uint8_t *)&connection->battery_status, 1); 1134 avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED); 1135 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 1136 return; 1137 } 1138 1139 if (connection->notify_volume_percentage_changed){ 1140 connection->notify_volume_percentage_changed = 0; 1141 avrcp_target_send_notification(connection->l2cap_signaling_cid, connection, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED, &connection->volume_percentage, 1); 1142 avrcp_target_reset_notification(connection, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED); 1143 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 1144 return; 1145 } 1146 1147 if (connection->reject_transport_header){ 1148 connection->state = AVCTP_CONNECTION_OPENED; 1149 connection->reject_transport_header = 0; 1150 l2cap_reserve_packet_buffer(); 1151 uint8_t * out_buffer = l2cap_get_outgoing_buffer(); 1152 out_buffer[0] = connection->transport_header; 1153 big_endian_store_16(out_buffer, 1, connection->invalid_pid); 1154 l2cap_send_prepared(connection->l2cap_signaling_cid, 3); 1155 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 1156 return; 1157 } 1158 1159 switch (connection->state){ 1160 case AVCTP_W2_SEND_RESPONSE: 1161 connection->state = AVCTP_CONNECTION_OPENED; 1162 avrcp_target_send_response(connection->l2cap_signaling_cid, connection); 1163 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 1164 return; 1165 default: 1166 break; 1167 } 1168 1169 break; 1170 } 1171 default: 1172 break; 1173 } 1174 default: 1175 break; 1176 } 1177 } 1178 1179 void avrcp_target_init(void){ 1180 avrcp_target_context.role = AVRCP_TARGET; 1181 avrcp_target_context.packet_handler = avrcp_target_packet_handler; 1182 avrcp_register_target_packet_handler(&avrcp_target_packet_handler); 1183 } 1184 1185 void avrcp_target_deinit(void){ 1186 memset(&avrcp_target_context, 0, sizeof(avrcp_context_t)); 1187 } 1188 1189 void avrcp_target_register_packet_handler(btstack_packet_handler_t callback){ 1190 btstack_assert(callback != NULL); 1191 avrcp_target_context.avrcp_callback = callback; 1192 } 1193 1194 void avrcp_target_register_set_addressed_player_handler(bool (*callback)(uint16_t player_id)){ 1195 btstack_assert(callback != NULL); 1196 avrcp_target_context.set_addressed_player_callback = callback; 1197 } 1198 1199 1200