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