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 static avrcp_context_t avrcp_target_context; 50 51 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){ 52 avrcp_create_sdp_record(0, service, service_record_handle, browsing, supported_features, service_name, service_provider_name); 53 } 54 55 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){ 56 if (!callback) return; 57 uint8_t event[8]; 58 int pos = 0; 59 event[pos++] = HCI_EVENT_AVRCP_META; 60 event[pos++] = sizeof(event) - 2; 61 event[pos++] = AVRCP_SUBEVENT_OPERATION; 62 little_endian_store_16(event, pos, avrcp_cid); 63 pos += 2; 64 event[pos++] = operation_id; 65 event[pos++] = operands_length; 66 event[pos++] = operand; 67 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 68 } 69 70 static void avrcp_target_emit_respond_query(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t subeventID){ 71 if (!callback) return; 72 uint8_t event[5]; 73 int pos = 0; 74 event[pos++] = HCI_EVENT_AVRCP_META; 75 event[pos++] = sizeof(event) - 2; 76 event[pos++] = subeventID; 77 little_endian_store_16(event, pos, avrcp_cid); 78 pos += 2; 79 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 80 } 81 82 static void avrcp_target_emit_respond_subunit_info_query(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t offset){ 83 if (!callback) return; 84 uint8_t event[6]; 85 int pos = 0; 86 event[pos++] = HCI_EVENT_AVRCP_META; 87 event[pos++] = sizeof(event) - 2; 88 event[pos++] = AVRCP_SUBEVENT_SUBUNIT_INFO_QUERY; 89 little_endian_store_16(event, pos, avrcp_cid); 90 pos += 2; 91 event[pos++] = offset; 92 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 93 } 94 95 static void avrcp_target_emit_respond_vendor_dependent_query(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t subevent_id){ 96 if (!callback) return; 97 uint8_t event[5]; 98 int pos = 0; 99 event[pos++] = HCI_EVENT_AVRCP_META; 100 event[pos++] = sizeof(event) - 2; 101 event[pos++] = subevent_id; 102 little_endian_store_16(event, pos, avrcp_cid); 103 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 104 } 105 106 static uint16_t avrcp_target_pack_single_element_attribute_number(uint8_t * packet, uint16_t size, uint16_t pos, avrcp_media_attribute_id_t attr_id, uint32_t value){ 107 UNUSED(size); 108 if ((attr_id < 1) || (attr_id > AVRCP_MEDIA_ATTR_COUNT)) return 0; 109 uint16_t attr_value_length = sprintf((char *)(packet+pos+8), "%0" PRIu32, value); 110 big_endian_store_32(packet, pos, attr_id); 111 pos += 4; 112 big_endian_store_16(packet, pos, UTF8); 113 pos += 2; 114 big_endian_store_16(packet, pos, attr_value_length); 115 pos += 2; 116 return 8 + attr_value_length; 117 } 118 119 static uint16_t avrcp_target_pack_single_element_attribute_string(uint8_t * packet, uint16_t size, 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_length){ 120 UNUSED(size); 121 if (attr_value_length == 0) return 0; 122 if ((attr_id < 1) || (attr_id > AVRCP_MEDIA_ATTR_COUNT)) return 0; 123 big_endian_store_32(packet, pos, attr_id); 124 pos += 4; 125 big_endian_store_16(packet, pos, mib_enumid); 126 pos += 2; 127 big_endian_store_16(packet, pos, attr_value_length); 128 pos += 2; 129 memcpy(packet+pos, attr_value, attr_value_length); 130 pos += attr_value_length; 131 return 8 + attr_value_length; 132 } 133 134 static int avrcp_target_send_now_playing_info(uint16_t cid, avrcp_connection_t * connection){ 135 uint16_t pos = 0; 136 l2cap_reserve_packet_buffer(); 137 uint8_t * packet = l2cap_get_outgoing_buffer(); 138 uint16_t size = l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid); 139 140 packet[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0; 141 // Profile IDentifier (PID) 142 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 143 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 144 145 // command_type 146 packet[pos++] = connection->command_type; 147 // subunit_type | subunit ID 148 packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id; 149 // opcode 150 packet[pos++] = (uint8_t)connection->command_opcode; 151 152 // company id is 3 bytes long 153 big_endian_store_24(packet, pos, BT_SIG_COMPANY_ID); 154 pos += 3; 155 156 packet[pos++] = AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES; 157 packet[pos++] = 0; 158 159 // num_attrs 160 int i; 161 162 uint16_t playing_info_buffer_len = 1; 163 uint16_t playing_info_buffer_len_position = pos; 164 165 uint8_t media_attr_count = 0; 166 uint16_t media_attr_count_position = pos + 2; 167 pos += 3; 168 169 for (i = 0; i < AVRCP_MEDIA_ATTR_COUNT; i++){ 170 int attr_id = i+1; 171 int attr_len; 172 switch (attr_id){ 173 case AVRCP_MEDIA_ATTR_TRACK: 174 attr_len = avrcp_target_pack_single_element_attribute_number(packet, size, pos, attr_id, connection->track_nr); 175 break; 176 case AVRCP_MEDIA_ATTR_TOTAL_TRACKS: 177 attr_len = avrcp_target_pack_single_element_attribute_number(packet, size, pos, attr_id, connection->total_tracks); 178 break; 179 case AVRCP_MEDIA_ATTR_SONG_LENGTH: 180 attr_len = avrcp_target_pack_single_element_attribute_number(packet, size, pos, attr_id, connection->song_length_ms); 181 break; 182 default: 183 attr_len = avrcp_target_pack_single_element_attribute_string(packet, size, pos, UTF8, attr_id, connection->now_playing_info[i].value, connection->now_playing_info[i].len); 184 break; 185 } 186 if (attr_len > 0) { 187 pos += attr_len; 188 playing_info_buffer_len += attr_len; 189 media_attr_count++; 190 } 191 } 192 big_endian_store_16(packet, playing_info_buffer_len_position, playing_info_buffer_len); 193 packet[media_attr_count_position] = media_attr_count; 194 195 // TODO fragmentation 196 if (playing_info_buffer_len + pos > l2cap_get_remote_mtu_for_local_cid(connection->l2cap_signaling_cid)) { 197 return ERROR_CODE_MEMORY_CAPACITY_EXCEEDED; 198 } 199 200 connection->wait_to_send = 0; 201 return l2cap_send_prepared(cid, pos); 202 } 203 204 static int avrcp_target_send_response(uint16_t cid, avrcp_connection_t * connection){ 205 int pos = 0; 206 l2cap_reserve_packet_buffer(); 207 uint8_t * packet = l2cap_get_outgoing_buffer(); 208 209 // transport header 210 // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) 211 packet[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_RESPONSE_FRAME << 1) | 0; 212 // Profile IDentifier (PID) 213 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 214 packet[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 215 216 // command_type 217 packet[pos++] = connection->command_type; 218 // subunit_type | subunit ID 219 packet[pos++] = (connection->subunit_type << 3) | connection->subunit_id; 220 // opcode 221 packet[pos++] = (uint8_t)connection->command_opcode; 222 // operands 223 memcpy(packet+pos, connection->cmd_operands, connection->cmd_operands_length); 224 // printf_hexdump(packet+pos, connection->cmd_operands_length); 225 226 pos += connection->cmd_operands_length; 227 connection->wait_to_send = 0; 228 return l2cap_send_prepared(cid, pos); 229 } 230 231 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){ 232 // AVRCP_CTYPE_RESPONSE_REJECTED 233 connection->command_type = AVRCP_CTYPE_RESPONSE_REJECTED; 234 connection->subunit_type = subunit_type; 235 connection->subunit_id = subunit_id; 236 connection->command_opcode = opcode; 237 238 // company id is 3 bytes long 239 int pos = connection->cmd_operands_length; 240 connection->cmd_operands[pos++] = pdu_id; 241 connection->cmd_operands[pos++] = 0; 242 // param length 243 big_endian_store_16(connection->cmd_operands, pos, 1); 244 pos += 2; 245 connection->cmd_operands[pos++] = status; 246 connection->cmd_operands_length = pos; 247 248 connection->state = AVCTP_W2_SEND_RESPONSE; 249 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 250 return ERROR_CODE_SUCCESS; 251 } 252 253 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){ 254 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 255 if (!connection){ 256 log_error("avrcp_target_operation_reject: could not find a connection."); 257 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 258 } 259 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 260 printf("avrcp_target_pass_through_response: operation 0x%02x, operands length %d\n", opid, operands_length); 261 262 connection->command_type = cmd_type; 263 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 264 connection->subunit_id = AVRCP_SUBUNIT_ID; 265 connection->command_opcode = AVRCP_CMD_OPCODE_PASS_THROUGH; 266 267 int pos = 0; 268 connection->cmd_operands[pos++] = opid; 269 connection->cmd_operands[pos++] = operands_length; 270 if (operands_length == 1){ 271 connection->cmd_operands[pos++] = operand; 272 } 273 connection->cmd_operands_length = pos; 274 275 connection->state = AVCTP_W2_SEND_RESPONSE; 276 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 277 return ERROR_CODE_SUCCESS; 278 } 279 280 uint8_t avrcp_target_operation_rejected(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){ 281 return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_REJECTED, opid, operands_length, operand); 282 } 283 284 uint8_t avrcp_target_operation_accepted(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){ 285 return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_ACCEPTED, opid, operands_length, operand); 286 } 287 288 uint8_t avrcp_target_operation_not_implemented(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint8_t operands_length, uint8_t operand){ 289 return avrcp_target_pass_through_response(avrcp_cid, AVRCP_CTYPE_RESPONSE_ACCEPTED, opid, operands_length, operand); 290 } 291 292 uint8_t avrcp_target_unit_info(uint16_t avrcp_cid, avrcp_subunit_type_t unit_type, uint32_t company_id){ 293 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 294 if (!connection){ 295 log_error("avrcp_unit_info: could not find a connection."); 296 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 297 } 298 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 299 300 uint8_t unit = 0; 301 connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE; 302 connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique 303 connection->subunit_id = AVRCP_SUBUNIT_ID_IGNORE; 304 connection->command_opcode = AVRCP_CMD_OPCODE_UNIT_INFO; 305 306 connection->cmd_operands_length = 5; 307 connection->cmd_operands[0] = 0x07; 308 connection->cmd_operands[1] = (unit_type << 4) | unit; 309 // company id is 3 bytes long 310 big_endian_store_32(connection->cmd_operands, 2, company_id); 311 312 connection->state = AVCTP_W2_SEND_RESPONSE; 313 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 314 return ERROR_CODE_SUCCESS; 315 } 316 317 uint8_t avrcp_target_subunit_info(uint16_t avrcp_cid, avrcp_subunit_type_t subunit_type, uint8_t offset, uint8_t * subunit_info_data){ 318 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 319 if (!connection){ 320 log_error("avrcp_unit_info: could not find a connection."); 321 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 322 } 323 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 324 325 connection->command_opcode = AVRCP_CMD_OPCODE_SUBUNIT_INFO; 326 connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE; 327 connection->subunit_type = subunit_type; //vendor unique 328 connection->subunit_id = AVRCP_SUBUNIT_ID_IGNORE; 329 330 uint8_t page = offset / 4; 331 uint8_t extension_code = 7; 332 connection->cmd_operands_length = 5; 333 connection->cmd_operands[0] = (page << 4) | extension_code; 334 memcpy(connection->cmd_operands+1, subunit_info_data + offset, 4); 335 336 connection->state = AVCTP_W2_SEND_RESPONSE; 337 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 338 return ERROR_CODE_SUCCESS; 339 } 340 341 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){ 342 *out_connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 343 if (!*out_connection){ 344 log_error("avrcp tartget: could not find a connection."); 345 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 346 } 347 348 if ((*out_connection)->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 349 (*out_connection)->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 350 (*out_connection)->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE; 351 (*out_connection)->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 352 (*out_connection)->subunit_id = AVRCP_SUBUNIT_ID; 353 354 (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = pdu_id; 355 // reserved 356 (*out_connection)->cmd_operands[(*out_connection)->cmd_operands_length++] = 0; 357 // param length 358 big_endian_store_16((*out_connection)->cmd_operands, (*out_connection)->cmd_operands_length, param_length); 359 (*out_connection)->cmd_operands_length += 2; 360 return ERROR_CODE_SUCCESS; 361 } 362 363 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){ 364 avrcp_connection_t * connection = NULL; 365 uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_CAPABILITIES, 2+size); 366 if (status != ERROR_CODE_SUCCESS) return status; 367 368 connection->cmd_operands[connection->cmd_operands_length++] = capability_id; 369 connection->cmd_operands[connection->cmd_operands_length++] = capabilities_num; 370 memcpy(connection->cmd_operands+connection->cmd_operands_length, capabilities, size); 371 connection->cmd_operands_length += size; 372 373 connection->state = AVCTP_W2_SEND_RESPONSE; 374 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 375 return ERROR_CODE_SUCCESS; 376 } 377 378 uint8_t avrcp_target_supported_events(uint16_t avrcp_cid, uint8_t capabilities_num, uint8_t * capabilities, uint8_t size){ 379 return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_EVENT, capabilities_num, capabilities, size); 380 } 381 382 uint8_t avrcp_target_supported_companies(uint16_t avrcp_cid, uint8_t capabilities_num, uint8_t * capabilities, uint8_t size ){ 383 return avrcp_target_capability(avrcp_cid, AVRCP_CAPABILITY_ID_COMPANY, capabilities_num, capabilities, size); 384 } 385 386 uint8_t avrcp_target_play_status(uint16_t avrcp_cid, uint32_t song_length_ms, uint32_t song_position_ms, avrcp_play_status_t play_status){ 387 avrcp_connection_t * connection = NULL; 388 uint8_t status = avrcp_prepare_vendor_dependent_response(avrcp_cid, &connection, AVRCP_PDU_ID_GET_PLAY_STATUS, 11); 389 if (status != ERROR_CODE_SUCCESS) return status; 390 391 big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_length_ms); 392 connection->cmd_operands_length += 4; 393 big_endian_store_32(connection->cmd_operands, connection->cmd_operands_length, song_position_ms); 394 connection->cmd_operands_length += 4; 395 connection->cmd_operands[connection->cmd_operands_length++] = play_status; 396 397 connection->state = AVCTP_W2_SEND_RESPONSE; 398 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 399 return ERROR_CODE_SUCCESS; 400 } 401 402 uint8_t avrcp_target_now_playing_info(uint16_t avrcp_cid){ 403 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 404 if (!connection){ 405 log_error("avrcp tartget: could not find a connection."); 406 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 407 } 408 409 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 410 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 411 connection->command_type = AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE; 412 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 413 connection->subunit_id = AVRCP_SUBUNIT_ID; 414 415 connection->now_playing_info_response = 1; 416 connection->state = AVCTP_W2_SEND_RESPONSE; 417 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 418 return ERROR_CODE_SUCCESS; 419 } 420 421 static uint8_t avrcp_target_store_media_attr(uint16_t avrcp_cid, avrcp_media_attribute_id_t attr_id, const char * value){ 422 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 423 if (!connection){ 424 log_error("avrcp_unit_info: could not find a connection."); 425 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 426 } 427 428 int index = attr_id - 1; 429 connection->now_playing_info[index].value = (uint8_t*)value; 430 connection->now_playing_info[index].len = strlen(value); 431 return ERROR_CODE_SUCCESS; 432 } 433 434 uint8_t avrcp_target_set_now_playing_title(uint16_t avrcp_cid, const char * title){ 435 return avrcp_target_store_media_attr(avrcp_cid, AVRCP_MEDIA_ATTR_TITLE, title); 436 } 437 438 uint8_t avrcp_target_set_now_playing_artist(uint16_t avrcp_cid, const char * artist){ 439 return avrcp_target_store_media_attr(avrcp_cid, AVRCP_MEDIA_ATTR_ARTIST, artist); 440 } 441 442 uint8_t avrcp_target_set_now_playing_album(uint16_t avrcp_cid, const char * album){ 443 return avrcp_target_store_media_attr(avrcp_cid, AVRCP_MEDIA_ATTR_ALBUM, album); 444 } 445 446 uint8_t avrcp_target_set_now_playing_genre(uint16_t avrcp_cid, const char * genre){ 447 return avrcp_target_store_media_attr(avrcp_cid, AVRCP_MEDIA_ATTR_GENRE, genre); 448 } 449 450 uint8_t avrcp_target_set_now_playing_song_length_ms(uint16_t avrcp_cid, const uint32_t song_length_ms){ 451 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 452 if (!connection){ 453 log_error("avrcp_unit_info: could not find a connection."); 454 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 455 } 456 connection->song_length_ms = song_length_ms; 457 return ERROR_CODE_SUCCESS; 458 } 459 460 uint8_t avrcp_target_set_now_playing_total_tracks(uint16_t avrcp_cid, const int total_tracks){ 461 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 462 if (!connection){ 463 log_error("avrcp_unit_info: could not find a connection."); 464 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 465 } 466 connection->total_tracks = total_tracks; 467 return ERROR_CODE_SUCCESS; 468 } 469 470 uint8_t avrcp_target_set_now_playing_track_nr(uint16_t avrcp_cid, const int track_nr){ 471 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 472 if (!connection){ 473 log_error("avrcp_unit_info: could not find a connection."); 474 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 475 } 476 connection->track_nr = track_nr; 477 return ERROR_CODE_SUCCESS; 478 } 479 480 static uint8_t * avrcp_get_company_id(uint8_t *packet, uint16_t size){ 481 UNUSED(size); 482 return packet + 6; 483 } 484 485 static uint8_t * avrcp_get_pdu(uint8_t *packet, uint16_t size){ 486 UNUSED(size); 487 return packet + 9; 488 } 489 490 static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connection_t * connection, uint8_t *packet, uint16_t size){ 491 UNUSED(connection); 492 UNUSED(packet); 493 UNUSED(size); 494 495 // uint8_t opcode; 496 497 uint8_t transport_header = packet[0]; 498 connection->transaction_label = transport_header >> 4; 499 // uint8_t packet_type = (transport_header & 0x0F) >> 2; 500 // uint8_t frame_type = (transport_header & 0x03) >> 1; 501 // uint8_t ipid = transport_header & 0x01; 502 // uint8_t byte_value = packet[2]; 503 // uint16_t pid = (byte_value << 8) | packet[2]; 504 505 // avrcp_command_type_t ctype = (avrcp_command_type_t) packet[3]; 506 // uint8_t byte_value = packet[4]; 507 avrcp_subunit_type_t subunit_type = (avrcp_subunit_type_t) (packet[4] >> 3); 508 avrcp_subunit_id_t subunit_id = (avrcp_subunit_id_t) (packet[4] & 0x07); 509 // opcode = packet[pos++]; 510 511 // printf(" Transport header 0x%02x (transaction_label %d, packet_type %d, frame_type %d, ipid %d), pid 0x%4x\n", 512 // transport_header, transaction_label, packet_type, frame_type, ipid, pid); 513 // printf_hexdump(packet+pos, size-pos); 514 515 avrcp_command_opcode_t opcode = avrcp_cmd_opcode(packet,size); 516 uint8_t * company_id = avrcp_get_company_id(packet, size); 517 uint8_t * pdu = avrcp_get_pdu(packet, size); 518 // uint16_t param_length = big_endian_read_16(pdu, 2); 519 520 int pos = 4; 521 uint8_t pdu_id; 522 connection->cmd_operands_length = 0; 523 524 switch (opcode){ 525 case AVRCP_CMD_OPCODE_UNIT_INFO: 526 avrcp_target_emit_respond_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_UNIT_INFO_QUERY); 527 break; 528 case AVRCP_CMD_OPCODE_SUBUNIT_INFO:{ 529 uint8_t offset = 4 * (packet[pos+2]>>4); 530 avrcp_target_emit_respond_subunit_info_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, offset); 531 break; 532 } 533 case AVRCP_CMD_OPCODE_PASS_THROUGH: 534 log_info("AVRCP_OPERATION_ID 0x%02x, operands length %d, operand %d", packet[6], packet[7], packet[8]); 535 avrcp_target_emit_operation(avrcp_target_context.avrcp_callback, connection->avrcp_cid, packet[6], packet[7], packet[8]); 536 break; 537 case AVRCP_CMD_OPCODE_VENDOR_DEPENDENT: 538 pdu_id = pdu[0]; 539 // 1 - reserved 540 // 2-3 param length, 541 memcpy(connection->cmd_operands, company_id, 3); 542 connection->cmd_operands_length = 3; 543 switch (pdu_id){ 544 case AVRCP_PDU_ID_GET_CAPABILITIES:{ 545 avrcp_capability_id_t capability_id = (avrcp_capability_id_t) pdu[pos]; 546 switch (capability_id){ 547 case AVRCP_CAPABILITY_ID_EVENT: 548 avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_EVENT_IDS_QUERY); 549 break; 550 case AVRCP_CAPABILITY_ID_COMPANY: 551 avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_COMPANY_IDS_QUERY); 552 break; 553 default: 554 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER); 555 break; 556 } 557 break; 558 } 559 case AVRCP_PDU_ID_GET_PLAY_STATUS: 560 avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_PLAY_STATUS_QUERY); 561 break; 562 case AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES:{ 563 uint8_t play_identifier[8]; 564 memset(play_identifier, 0, 8); 565 if (memcmp(pdu+pos, play_identifier, 8) != 0) { 566 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_PARAMETER); 567 return; 568 } 569 avrcp_target_emit_respond_vendor_dependent_query(avrcp_target_context.avrcp_callback, connection->avrcp_cid, AVRCP_SUBEVENT_NOW_PLAYING_INFO_QUERY); 570 break; 571 } 572 default: 573 printf("unhandled pdu id 0x%02x\n", pdu_id); 574 avrcp_target_response_reject(connection, subunit_type, subunit_id, opcode, pdu_id, AVRCP_STATUS_INVALID_COMMAND); 575 break; 576 } 577 break; 578 default: 579 printf("AVRCP target: opcode 0x%02x not implemented\n", avrcp_cmd_opcode(packet,size)); 580 break; 581 } 582 } 583 584 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 585 avrcp_connection_t * connection; 586 switch (packet_type) { 587 case L2CAP_DATA_PACKET: 588 connection = get_avrcp_connection_for_l2cap_signaling_cid(channel, &avrcp_target_context); 589 if (!connection) break; 590 avrcp_handle_l2cap_data_packet_for_signaling_connection(connection, packet, size); 591 break; 592 case HCI_EVENT_PACKET: 593 switch (hci_event_packet_get_type(packet)){ 594 case L2CAP_EVENT_CAN_SEND_NOW: 595 connection = get_avrcp_connection_for_l2cap_signaling_cid(channel, &avrcp_target_context); 596 if (!connection) break; 597 switch (connection->state){ 598 case AVCTP_W2_SEND_RESPONSE: 599 connection->state = AVCTP_CONNECTION_OPENED; 600 if (connection->now_playing_info_response){ 601 printf("now_playing_info_response \n"); 602 connection->now_playing_info_response = 0; 603 avrcp_target_send_now_playing_info(connection->l2cap_signaling_cid, connection); 604 break; 605 } 606 avrcp_target_send_response(connection->l2cap_signaling_cid, connection); 607 break; 608 default: 609 return; 610 } 611 break; 612 default: 613 avrcp_packet_handler(packet_type, channel, packet, size, &avrcp_target_context); 614 break; 615 } 616 default: 617 break; 618 } 619 } 620 621 void avrcp_target_init(void){ 622 avrcp_target_context.role = AVRCP_TARGET; 623 avrcp_target_context.connections = NULL; 624 avrcp_target_context.packet_handler = avrcp_controller_packet_handler; 625 l2cap_register_service(&avrcp_controller_packet_handler, BLUETOOTH_PROTOCOL_AVCTP, 0xffff, LEVEL_0); 626 } 627 628 void avrcp_target_register_packet_handler(btstack_packet_handler_t callback){ 629 if (callback == NULL){ 630 log_error("avrcp_register_packet_handler called with NULL callback"); 631 return; 632 } 633 avrcp_target_context.avrcp_callback = callback; 634 } 635 636 uint8_t avrcp_target_connect(bd_addr_t bd_addr, uint16_t * avrcp_cid){ 637 return avrcp_connect(bd_addr, &avrcp_target_context, avrcp_cid); 638 } 639 640 uint8_t avrcp_target_disconnect(uint16_t avrcp_cid){ 641 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_target_context); 642 if (!connection){ 643 log_error("avrcp_get_capabilities: could not find a connection."); 644 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 645 } 646 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 647 l2cap_disconnect(connection->l2cap_signaling_cid, 0); 648 return ERROR_CODE_SUCCESS; 649 } 650 651