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