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_controller.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 #include "classic/avrcp_controller.h" 48 49 static avrcp_context_t avrcp_controller_context; 50 51 void avrcp_controller_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(1, service, service_record_handle, browsing, supported_features, service_name, service_provider_name); 53 } 54 55 static void avrcp_emit_repeat_and_shuffle_mode(btstack_packet_handler_t callback, uint16_t avrcp_cid, uint8_t ctype, avrcp_repeat_mode_t repeat_mode, avrcp_shuffle_mode_t shuffle_mode){ 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_SHUFFLE_AND_REPEAT_MODE; 62 little_endian_store_16(event, pos, avrcp_cid); 63 pos += 2; 64 event[pos++] = ctype; 65 event[pos++] = repeat_mode; 66 event[pos++] = shuffle_mode; 67 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 68 } 69 70 static void avrcp_emit_operation_status(btstack_packet_handler_t callback, uint8_t subevent, uint16_t avrcp_cid, uint8_t ctype, uint8_t operation_id){ 71 if (!callback) return; 72 uint8_t event[7]; 73 int pos = 0; 74 event[pos++] = HCI_EVENT_AVRCP_META; 75 event[pos++] = sizeof(event) - 2; 76 event[pos++] = subevent; 77 little_endian_store_16(event, pos, avrcp_cid); 78 pos += 2; 79 event[pos++] = ctype; 80 event[pos++] = operation_id; 81 (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 82 } 83 84 static void avrcp_press_and_hold_timeout_handler(btstack_timer_source_t * timer){ 85 UNUSED(timer); 86 avrcp_connection_t * connection = btstack_run_loop_get_timer_context(timer); 87 btstack_run_loop_set_timer(&connection->press_and_hold_cmd_timer, 2000); // 2 seconds timeout 88 btstack_run_loop_add_timer(&connection->press_and_hold_cmd_timer); 89 connection->state = AVCTP_W2_SEND_PRESS_COMMAND; 90 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 91 } 92 93 static void avrcp_press_and_hold_timer_start(avrcp_connection_t * connection){ 94 btstack_run_loop_remove_timer(&connection->press_and_hold_cmd_timer); 95 btstack_run_loop_set_timer_handler(&connection->press_and_hold_cmd_timer, avrcp_press_and_hold_timeout_handler); 96 btstack_run_loop_set_timer_context(&connection->press_and_hold_cmd_timer, connection); 97 btstack_run_loop_set_timer(&connection->press_and_hold_cmd_timer, 2000); // 2 seconds timeout 98 btstack_run_loop_add_timer(&connection->press_and_hold_cmd_timer); 99 } 100 101 static void avrcp_press_and_hold_timer_stop(avrcp_connection_t * connection){ 102 connection->continuous_fast_forward_cmd = 0; 103 btstack_run_loop_remove_timer(&connection->press_and_hold_cmd_timer); 104 } 105 106 static uint8_t request_pass_through_release_control_cmd(avrcp_connection_t * connection){ 107 connection->state = AVCTP_W2_SEND_RELEASE_COMMAND; 108 if (connection->continuous_fast_forward_cmd){ 109 avrcp_press_and_hold_timer_stop(connection); 110 } 111 connection->cmd_operands[0] = 0x80 | connection->cmd_operands[0]; 112 connection->transaction_label++; 113 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 114 return ERROR_CODE_SUCCESS; 115 } 116 117 static inline uint8_t request_pass_through_press_control_cmd(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint16_t playback_speed, uint8_t continuous_fast_forward_cmd, avrcp_context_t * context){ 118 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, context); 119 if (!connection){ 120 log_error("avrcp: could not find a connection."); 121 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 122 } 123 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 124 connection->state = AVCTP_W2_SEND_PRESS_COMMAND; 125 connection->command_opcode = AVRCP_CMD_OPCODE_PASS_THROUGH; 126 connection->command_type = AVRCP_CTYPE_CONTROL; 127 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 128 connection->subunit_id = AVRCP_SUBUNIT_ID; 129 connection->cmd_operands_length = 0; 130 131 connection->continuous_fast_forward_cmd = continuous_fast_forward_cmd; 132 connection->cmd_operands_length = 2; 133 connection->cmd_operands[0] = opid; 134 if (playback_speed > 0){ 135 connection->cmd_operands[2] = playback_speed; 136 connection->cmd_operands_length++; 137 } 138 connection->cmd_operands[1] = connection->cmd_operands_length - 2; 139 140 if (connection->continuous_fast_forward_cmd){ 141 avrcp_press_and_hold_timer_start(connection); 142 } 143 144 connection->transaction_label++; 145 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 146 return ERROR_CODE_SUCCESS; 147 } 148 149 static uint8_t request_single_pass_through_press_control_cmd(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint16_t playback_speed){ 150 return request_pass_through_press_control_cmd(avrcp_cid, opid, playback_speed, 0, &avrcp_controller_context); 151 } 152 153 static uint8_t request_continuous_pass_through_press_control_cmd(uint16_t avrcp_cid, avrcp_operation_id_t opid, uint16_t playback_speed){ 154 return request_pass_through_press_control_cmd(avrcp_cid, opid, playback_speed, 1, &avrcp_controller_context); 155 } 156 157 static int avrcp_send_cmd(uint16_t cid, avrcp_connection_t * connection){ 158 uint8_t command[30]; 159 int pos = 0; 160 // transport header 161 // Transaction label | Packet_type | C/R | IPID (1 == invalid profile identifier) 162 command[pos++] = (connection->transaction_label << 4) | (AVRCP_SINGLE_PACKET << 2) | (AVRCP_COMMAND_FRAME << 1) | 0; 163 // Profile IDentifier (PID) 164 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL >> 8; 165 command[pos++] = BLUETOOTH_SERVICE_CLASS_AV_REMOTE_CONTROL & 0x00FF; 166 167 // command_type 168 command[pos++] = connection->command_type; 169 // subunit_type | subunit ID 170 command[pos++] = (connection->subunit_type << 3) | connection->subunit_id; 171 // opcode 172 command[pos++] = (uint8_t)connection->command_opcode; 173 // operands 174 memcpy(command+pos, connection->cmd_operands, connection->cmd_operands_length); 175 pos += connection->cmd_operands_length; 176 177 return l2cap_send(cid, command, pos); 178 } 179 180 static int avrcp_register_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t event_id){ 181 if (connection->notifications_to_deregister & (1 << event_id)) return 0; 182 if (connection->notifications_enabled & (1 << event_id)) return 0; 183 if (connection->notifications_to_register & (1 << event_id)) return 0; 184 connection->notifications_to_register |= (1 << event_id); 185 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 186 return 1; 187 } 188 189 static void avrcp_prepare_notification(avrcp_connection_t * connection, avrcp_notification_event_id_t event_id){ 190 connection->transaction_label++; 191 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 192 connection->command_type = AVRCP_CTYPE_NOTIFY; 193 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 194 connection->subunit_id = AVRCP_SUBUNIT_ID; 195 int pos = 0; 196 big_endian_store_24(connection->cmd_operands, pos, BT_SIG_COMPANY_ID); 197 pos += 3; 198 connection->cmd_operands[pos++] = AVRCP_PDU_ID_REGISTER_NOTIFICATION; 199 connection->cmd_operands[pos++] = 0; // reserved(upper 6) | packet_type -> 0 200 big_endian_store_16(connection->cmd_operands, pos, 5); // parameter length 201 pos += 2; 202 connection->cmd_operands[pos++] = event_id; 203 big_endian_store_32(connection->cmd_operands, pos, 0); 204 pos += 4; 205 connection->cmd_operands_length = pos; 206 // AVRCP_SPEC_V14.pdf 166 207 // answer page 61 208 } 209 210 static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connection_t * connection, uint8_t *packet, uint16_t size){ 211 uint8_t operands[20]; 212 uint8_t opcode; 213 int pos = 3; 214 // uint8_t transport_header = packet[0]; 215 // uint8_t transaction_label = transport_header >> 4; 216 // uint8_t packet_type = (transport_header & 0x0F) >> 2; 217 // uint8_t frame_type = (transport_header & 0x03) >> 1; 218 // uint8_t ipid = transport_header & 0x01; 219 // uint8_t byte_value = packet[2]; 220 // uint16_t pid = (byte_value << 8) | packet[2]; 221 222 avrcp_command_type_t ctype = (avrcp_command_type_t) packet[pos++]; 223 uint8_t byte_value = packet[pos++]; 224 avrcp_subunit_type_t subunit_type = (avrcp_subunit_type_t) (byte_value >> 3); 225 avrcp_subunit_type_t subunit_id = (avrcp_subunit_type_t) (byte_value & 0x07); 226 opcode = packet[pos++]; 227 228 // printf(" Transport header 0x%02x (transaction_label %d, packet_type %d, frame_type %d, ipid %d), pid 0x%4x\n", 229 // transport_header, transaction_label, packet_type, frame_type, ipid, pid); 230 // // printf_hexdump(packet+pos, size-pos); 231 232 uint8_t pdu_id; 233 uint16_t param_length; 234 switch (avrcp_cmd_opcode(packet,size)){ 235 case AVRCP_CMD_OPCODE_UNIT_INFO:{ 236 if (connection->state != AVCTP_W2_RECEIVE_RESPONSE) return; 237 connection->state = AVCTP_CONNECTION_OPENED; 238 239 // operands: 240 memcpy(operands, packet+pos, 5); 241 uint8_t unit_type = operands[1] >> 3; 242 uint8_t unit = operands[1] & 0x07; 243 uint32_t company_id = operands[2] << 16 | operands[3] << 8 | operands[4]; 244 log_info(" UNIT INFO response: ctype 0x%02x (0C), subunit_type 0x%02x (1F), subunit_id 0x%02x (07), opcode 0x%02x (30), unit_type 0x%02x, unit %d, company_id 0x%06x", 245 ctype, subunit_type, subunit_id, opcode, unit_type, unit, company_id ); 246 break; 247 } 248 case AVRCP_CMD_OPCODE_VENDOR_DEPENDENT: 249 if (size - pos < 7) { 250 log_error("avrcp: wrong packet size"); 251 return; 252 }; 253 // operands: 254 memcpy(operands, packet+pos, 7); 255 pos += 7; 256 // uint32_t company_id = operands[0] << 16 | operands[1] << 8 | operands[2]; 257 pdu_id = operands[3]; 258 259 if (connection->state != AVCTP_W2_RECEIVE_RESPONSE && pdu_id != AVRCP_PDU_ID_REGISTER_NOTIFICATION){ 260 log_info("AVRCP_CMD_OPCODE_VENDOR_DEPENDENT state %d", connection->state); 261 return; 262 } 263 connection->state = AVCTP_CONNECTION_OPENED; 264 265 266 // uint8_t unit_type = operands[4] >> 3; 267 // uint8_t unit = operands[4] & 0x07; 268 param_length = big_endian_read_16(operands, 5); 269 270 // printf(" VENDOR DEPENDENT response: ctype 0x%02x (0C), subunit_type 0x%02x (1F), subunit_id 0x%02x (07), opcode 0x%02x (30), unit_type 0x%02x, unit %d, company_id 0x%06x\n", 271 // ctype, subunit_type, subunit_id, opcode, unit_type, unit, company_id ); 272 273 // if (ctype == AVRCP_CTYPE_RESPONSE_INTERIM) return; 274 log_info(" VENDOR DEPENDENT response: pdu id 0x%02x, param_length %d, status %s", pdu_id, param_length, avrcp_ctype2str(ctype)); 275 switch (pdu_id){ 276 case AVRCP_PDU_ID_GetCurrentPlayerApplicationSettingValue:{ 277 uint8_t num_attributes = packet[pos++]; 278 int i; 279 avrcp_repeat_mode_t repeat_mode = AVRCP_REPEAT_MODE_INVALID; 280 avrcp_shuffle_mode_t shuffle_mode = AVRCP_SHUFFLE_MODE_INVALID; 281 for (i = 0; i < num_attributes; i++){ 282 uint8_t attribute_id = packet[pos++]; 283 uint8_t value = packet[pos++]; 284 switch (attribute_id){ 285 case 0x02: 286 repeat_mode = (avrcp_repeat_mode_t) value; 287 break; 288 case 0x03: 289 shuffle_mode = (avrcp_shuffle_mode_t) value; 290 break; 291 default: 292 break; 293 } 294 } 295 avrcp_emit_repeat_and_shuffle_mode(avrcp_controller_context.avrcp_callback, connection->avrcp_cid, ctype, repeat_mode, shuffle_mode); 296 break; 297 } 298 case AVRCP_PDU_ID_SetPlayerApplicationSettingValue:{ 299 uint8_t event[6]; 300 int offset = 0; 301 event[offset++] = HCI_EVENT_AVRCP_META; 302 event[offset++] = sizeof(event) - 2; 303 event[offset++] = AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE; 304 little_endian_store_16(event, offset, connection->avrcp_cid); 305 offset += 2; 306 event[offset++] = ctype; 307 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 308 break; 309 } 310 case AVRCP_PDU_ID_SET_ABSOLUTE_VOLUME:{ 311 uint8_t event[7]; 312 int offset = 0; 313 event[offset++] = HCI_EVENT_AVRCP_META; 314 event[offset++] = sizeof(event) - 2; 315 event[offset++] = AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE; 316 little_endian_store_16(event, offset, connection->avrcp_cid); 317 offset += 2; 318 event[offset++] = ctype; 319 event[offset++] = packet[pos++]; 320 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 321 break; 322 } 323 case AVRCP_PDU_ID_GET_CAPABILITIES:{ 324 avrcp_capability_id_t capability_id = (avrcp_capability_id_t) packet[pos++]; 325 uint8_t capability_count = packet[pos++]; 326 int i; 327 switch (capability_id){ 328 case AVRCP_CAPABILITY_ID_COMPANY: 329 // log_info("Supported companies %d: ", capability_count); 330 for (i = 0; i < capability_count; i++){ 331 uint32_t company_id = big_endian_read_24(packet, pos); 332 pos += 3; 333 log_info(" 0x%06x, ", company_id); 334 } 335 break; 336 case AVRCP_CAPABILITY_ID_EVENT: 337 // log_info("Supported events %d: ", capability_count); 338 for (i = 0; i < capability_count; i++){ 339 uint8_t event_id = packet[pos++]; 340 log_info(" 0x%02x %s", event_id, avrcp_event2str(event_id)); 341 } 342 break; 343 } 344 break; 345 } 346 case AVRCP_PDU_ID_GET_PLAY_STATUS:{ 347 uint32_t song_length = big_endian_read_32(packet, pos); 348 pos += 4; 349 uint32_t song_position = big_endian_read_32(packet, pos); 350 pos += 4; 351 uint8_t play_status = packet[pos]; 352 // log_info(" GET_PLAY_STATUS length 0x%04X, position 0x%04X, status %s", song_length, song_position, avrcp_play_status2str(play_status)); 353 354 uint8_t event[15]; 355 int offset = 0; 356 event[offset++] = HCI_EVENT_AVRCP_META; 357 event[offset++] = sizeof(event) - 2; 358 event[offset++] = AVRCP_SUBEVENT_PLAY_STATUS; 359 little_endian_store_16(event, offset, connection->avrcp_cid); 360 offset += 2; 361 event[offset++] = ctype; 362 little_endian_store_32(event, offset, song_length); 363 offset += 4; 364 little_endian_store_32(event, offset, song_position); 365 offset += 4; 366 event[offset++] = play_status; 367 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 368 break; 369 } 370 case AVRCP_PDU_ID_REGISTER_NOTIFICATION:{ 371 avrcp_notification_event_id_t event_id = (avrcp_notification_event_id_t) packet[pos++]; 372 uint16_t event_mask = (1 << event_id); 373 uint16_t reset_event_mask = ~event_mask; 374 switch (ctype){ 375 case AVRCP_CTYPE_RESPONSE_INTERIM: 376 // register as enabled 377 connection->notifications_enabled |= event_mask; 378 // printf("INTERIM notifications_enabled 0x%2x, notifications_to_register 0x%2x\n", connection->notifications_enabled, connection->notifications_to_register); 379 break; 380 case AVRCP_CTYPE_RESPONSE_CHANGED_STABLE: 381 // received change, event is considered deregistered 382 // we are re-enabling it automatically, if it is not 383 // explicitly disabled 384 connection->notifications_enabled &= reset_event_mask; 385 if (! (connection->notifications_to_deregister & event_mask)){ 386 avrcp_register_notification(connection, event_id); 387 // printf("CHANGED_STABLE notifications_enabled 0x%2x, notifications_to_register 0x%2x\n", connection->notifications_enabled, connection->notifications_to_register); 388 } else { 389 connection->notifications_to_deregister &= reset_event_mask; 390 } 391 break; 392 default: 393 connection->notifications_to_register &= reset_event_mask; 394 connection->notifications_enabled &= reset_event_mask; 395 connection->notifications_to_deregister &= reset_event_mask; 396 break; 397 } 398 399 switch (event_id){ 400 case AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED:{ 401 uint8_t event[7]; 402 int offset = 0; 403 event[offset++] = HCI_EVENT_AVRCP_META; 404 event[offset++] = sizeof(event) - 2; 405 event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED; 406 little_endian_store_16(event, offset, connection->avrcp_cid); 407 offset += 2; 408 event[offset++] = ctype; 409 event[offset++] = packet[pos]; 410 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 411 break; 412 } 413 case AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED:{ 414 uint8_t event[6]; 415 int offset = 0; 416 event[offset++] = HCI_EVENT_AVRCP_META; 417 event[offset++] = sizeof(event) - 2; 418 event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED; 419 little_endian_store_16(event, offset, connection->avrcp_cid); 420 offset += 2; 421 event[offset++] = ctype; 422 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 423 break; 424 } 425 case AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED:{ 426 uint8_t event[6]; 427 int offset = 0; 428 event[offset++] = HCI_EVENT_AVRCP_META; 429 event[offset++] = sizeof(event) - 2; 430 event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED; 431 little_endian_store_16(event, offset, connection->avrcp_cid); 432 offset += 2; 433 event[offset++] = ctype; 434 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 435 break; 436 } 437 case AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED:{ 438 uint8_t event[6]; 439 int offset = 0; 440 event[offset++] = HCI_EVENT_AVRCP_META; 441 event[offset++] = sizeof(event) - 2; 442 event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED; 443 little_endian_store_16(event, offset, connection->avrcp_cid); 444 offset += 2; 445 event[offset++] = ctype; 446 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 447 break; 448 } 449 case AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED:{ 450 uint8_t event[7]; 451 int offset = 0; 452 event[offset++] = HCI_EVENT_AVRCP_META; 453 event[offset++] = sizeof(event) - 2; 454 event[offset++] = AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED; 455 little_endian_store_16(event, offset, connection->avrcp_cid); 456 offset += 2; 457 event[offset++] = ctype; 458 event[offset++] = packet[pos++] & 0x7F; 459 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 460 break; 461 } 462 // case AVRCP_NOTIFICATION_EVENT_PLAYER_APPLICATION_SETTING_CHANGED:{ 463 // uint8_t num_PlayerApplicationSettingAttributes = packet[pos++]; 464 // int i; 465 // for (i = 0; i < num_PlayerApplicationSettingAttributes; i++){ 466 // uint8_t PlayerApplicationSetting_AttributeID = packet[pos++]; 467 // uint8_t PlayerApplicationSettingValueID = packet[pos++]; 468 // } 469 // break; 470 // } 471 // case AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED: 472 // uint16_t player_id = big_endian_read_16(packet, pos); 473 // pos += 2; 474 // uint16_t uid_counter = big_endian_read_16(packet, pos); 475 // pos += 2; 476 // break; 477 // case AVRCP_NOTIFICATION_EVENT_UIDS_CHANGED: 478 // uint16_t uid_counter = big_endian_read_16(packet, pos); 479 // pos += 2; 480 // break; 481 default: 482 log_info("avrcp: not implemented"); 483 break; 484 } 485 if (connection->notifications_to_register != 0){ 486 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 487 } 488 break; 489 } 490 491 case AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES:{ 492 uint8_t num_attributes = packet[pos++]; 493 unsigned int i; 494 struct item { 495 uint16_t len; 496 uint8_t * value; 497 } items[AVRCP_MEDIA_ATTR_COUNT]; 498 memset(items, 0, sizeof(items)); 499 500 uint16_t string_attributes_len = 0; 501 uint8_t num_string_attributes = 0; 502 uint16_t total_event_payload_for_string_attributes = HCI_EVENT_PAYLOAD_SIZE-2; 503 uint16_t max_string_attribute_value_len = 0; 504 if (ctype == AVRCP_CTYPE_RESPONSE_IMPLEMENTED_STABLE || ctype == AVRCP_CTYPE_RESPONSE_CHANGED_STABLE){ 505 for (i = 0; i < num_attributes; i++){ 506 avrcp_media_attribute_id_t attr_id = (avrcp_media_attribute_id_t) big_endian_read_32(packet, pos); 507 pos += 4; 508 // uint16_t character_set = big_endian_read_16(packet, pos); 509 pos += 2; 510 uint16_t attr_value_length = big_endian_read_16(packet, pos); 511 pos += 2; 512 513 // debug - to remove later 514 uint8_t value[100]; 515 uint16_t value_len = sizeof(value) <= attr_value_length? sizeof(value) - 1 : attr_value_length; 516 memcpy(value, packet+pos, value_len); 517 value[value_len] = 0; 518 // printf("Now Playing Info %s: %s \n", attribute2str(attr_id), value); 519 // end debug 520 521 if ((attr_id >= 1) || (attr_id <= AVRCP_MEDIA_ATTR_COUNT)) { 522 items[attr_id-1].len = attr_value_length; 523 items[attr_id-1].value = &packet[pos]; 524 switch (attr_id){ 525 case AVRCP_MEDIA_ATTR_TITLE: 526 case AVRCP_MEDIA_ATTR_ARTIST: 527 case AVRCP_MEDIA_ATTR_ALBUM: 528 case AVRCP_MEDIA_ATTR_GENRE: 529 num_string_attributes++; 530 string_attributes_len += attr_value_length; 531 if (max_string_attribute_value_len < attr_value_length){ 532 max_string_attribute_value_len = attr_value_length; 533 } 534 break; 535 default: 536 break; 537 } 538 } 539 pos += attr_value_length; 540 } 541 } 542 543 // subtract space for fixed fields 544 total_event_payload_for_string_attributes -= 14 + 4; // 4 for '\0' 545 546 // @TODO optimize space by repeatedly decreasing max_string_attribute_value_len until it fits into buffer instead of crude divion 547 uint16_t max_value_len = total_event_payload_for_string_attributes > string_attributes_len? max_string_attribute_value_len : total_event_payload_for_string_attributes/(string_attributes_len+1) - 1; 548 // printf("num_string_attributes %d, string_attributes_len %d, total_event_payload_for_string_attributes %d, max_value_len %d \n", num_string_attributes, string_attributes_len, total_event_payload_for_string_attributes, max_value_len); 549 550 const uint8_t attribute_order[] = { 551 AVRCP_MEDIA_ATTR_TRACK, 552 AVRCP_MEDIA_ATTR_TOTAL_TRACKS, 553 AVRCP_MEDIA_ATTR_SONG_LENGTH, 554 AVRCP_MEDIA_ATTR_TITLE, 555 AVRCP_MEDIA_ATTR_ARTIST, 556 AVRCP_MEDIA_ATTR_ALBUM, 557 AVRCP_MEDIA_ATTR_GENRE 558 }; 559 560 uint8_t event[HCI_EVENT_BUFFER_SIZE]; 561 event[0] = HCI_EVENT_AVRCP_META; 562 pos = 2; 563 event[pos++] = AVRCP_SUBEVENT_NOW_PLAYING_INFO; 564 little_endian_store_16(event, pos, connection->avrcp_cid); 565 pos += 2; 566 event[pos++] = ctype; 567 for (i = 0; i < sizeof(attribute_order); i++){ 568 avrcp_media_attribute_id_t attr_id = (avrcp_media_attribute_id_t) attribute_order[i]; 569 uint16_t value_len = 0; 570 switch (attr_id){ 571 case AVRCP_MEDIA_ATTR_TITLE: 572 case AVRCP_MEDIA_ATTR_ARTIST: 573 case AVRCP_MEDIA_ATTR_ALBUM: 574 case AVRCP_MEDIA_ATTR_GENRE: 575 if (items[attr_id-1].value){ 576 value_len = items[attr_id-1].len <= max_value_len ? items[attr_id-1].len : max_value_len; 577 } 578 event[pos++] = value_len + 1; 579 if (value_len){ 580 memcpy(event+pos, items[attr_id-1].value, value_len); 581 pos += value_len; 582 } 583 event[pos++] = 0; 584 break; 585 case AVRCP_MEDIA_ATTR_SONG_LENGTH: 586 if (items[attr_id-1].value){ 587 little_endian_store_32(event, pos, btstack_atoi((char *)items[attr_id-1].value)); 588 } else { 589 little_endian_store_32(event, pos, 0); 590 } 591 pos += 4; 592 break; 593 case AVRCP_MEDIA_ATTR_TRACK: 594 case AVRCP_MEDIA_ATTR_TOTAL_TRACKS: 595 if (items[attr_id-1].value){ 596 event[pos++] = btstack_atoi((char *)items[attr_id-1].value); 597 } else { 598 event[pos++] = 0; 599 } 600 break; 601 } 602 } 603 event[1] = pos - 2; 604 // printf_hexdump(event, pos); 605 (*avrcp_controller_context.avrcp_callback)(HCI_EVENT_PACKET, 0, event, pos); 606 break; 607 } 608 default: 609 break; 610 } 611 break; 612 case AVRCP_CMD_OPCODE_PASS_THROUGH:{ 613 // 0x80 | connection->cmd_operands[0] 614 uint8_t operation_id = packet[pos++]; 615 switch (connection->state){ 616 case AVCTP_W2_RECEIVE_PRESS_RESPONSE: 617 if (connection->continuous_fast_forward_cmd){ 618 connection->state = AVCTP_W4_STOP; 619 } else { 620 connection->state = AVCTP_W2_SEND_RELEASE_COMMAND; 621 } 622 break; 623 case AVCTP_W2_RECEIVE_RESPONSE: 624 connection->state = AVCTP_CONNECTION_OPENED; 625 break; 626 default: 627 // check for notifications? move state transition down 628 // log_info("AVRCP_CMD_OPCODE_PASS_THROUGH state %d\n", connection->state); 629 break; 630 } 631 if (connection->state == AVCTP_W4_STOP){ 632 avrcp_emit_operation_status(avrcp_controller_context.avrcp_callback, AVRCP_SUBEVENT_OPERATION_START, connection->avrcp_cid, ctype, operation_id); 633 } 634 if (connection->state == AVCTP_CONNECTION_OPENED) { 635 // RELEASE response 636 operation_id = operation_id & 0x7F; 637 avrcp_emit_operation_status(avrcp_controller_context.avrcp_callback, AVRCP_SUBEVENT_OPERATION_COMPLETE, connection->avrcp_cid, ctype, operation_id); 638 } 639 if (connection->state == AVCTP_W2_SEND_RELEASE_COMMAND){ 640 // PRESS response 641 request_pass_through_release_control_cmd(connection); 642 } 643 break; 644 } 645 default: 646 break; 647 } 648 } 649 650 static void avrcp_controller_handle_can_send_now(avrcp_connection_t * connection){ 651 int i; 652 switch (connection->state){ 653 case AVCTP_W2_SEND_PRESS_COMMAND: 654 connection->state = AVCTP_W2_RECEIVE_PRESS_RESPONSE; 655 avrcp_send_cmd(connection->l2cap_signaling_cid, connection); 656 break; 657 case AVCTP_W2_SEND_COMMAND: 658 case AVCTP_W2_SEND_RELEASE_COMMAND: 659 connection->state = AVCTP_W2_RECEIVE_RESPONSE; 660 avrcp_send_cmd(connection->l2cap_signaling_cid, connection); 661 break; 662 case AVCTP_CONNECTION_OPENED: 663 if (connection->notifications_to_register != 0){ 664 for (i = 1; i <= AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED; i++){ 665 if (connection->notifications_to_register & (1<<i)){ 666 connection->notifications_to_register &= ~ (1 << i); 667 avrcp_prepare_notification(connection, (avrcp_notification_event_id_t) i); 668 connection->state = AVCTP_W2_RECEIVE_RESPONSE; 669 avrcp_send_cmd(connection->l2cap_signaling_cid, connection); 670 return; 671 } 672 } 673 } 674 return; 675 default: 676 return; 677 } 678 } 679 680 static void avrcp_controller_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 681 avrcp_connection_t * connection; 682 683 switch (packet_type) { 684 case L2CAP_DATA_PACKET: 685 connection = get_avrcp_connection_for_l2cap_signaling_cid(channel, &avrcp_controller_context); 686 if (!connection) break; 687 avrcp_handle_l2cap_data_packet_for_signaling_connection(connection, packet, size); 688 break; 689 case HCI_EVENT_PACKET: 690 switch (hci_event_packet_get_type(packet)){ 691 case L2CAP_EVENT_CAN_SEND_NOW: 692 connection = get_avrcp_connection_for_l2cap_signaling_cid(channel, &avrcp_controller_context); 693 if (!connection) break; 694 avrcp_controller_handle_can_send_now(connection); 695 break; 696 default: 697 avrcp_packet_handler(packet_type, channel, packet, size, &avrcp_controller_context); 698 break; 699 } 700 default: 701 break; 702 } 703 } 704 705 void avrcp_controller_init(void){ 706 avrcp_controller_context.role = AVRCP_CONTROLLER; 707 avrcp_controller_context.connections = NULL; 708 avrcp_controller_context.packet_handler = avrcp_controller_packet_handler; 709 l2cap_register_service(&avrcp_controller_packet_handler, BLUETOOTH_PROTOCOL_AVCTP, 0xffff, LEVEL_0); 710 } 711 712 void avrcp_controller_register_packet_handler(btstack_packet_handler_t callback){ 713 if (callback == NULL){ 714 log_error("avrcp_register_packet_handler called with NULL callback"); 715 return; 716 } 717 avrcp_controller_context.avrcp_callback = callback; 718 } 719 720 uint8_t avrcp_controller_connect(bd_addr_t bd_addr, uint16_t * avrcp_cid){ 721 return avrcp_connect(bd_addr, &avrcp_controller_context, avrcp_cid); 722 } 723 724 uint8_t avrcp_controller_unit_info(uint16_t avrcp_cid){ 725 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 726 if (!connection){ 727 log_error("avrcp_unit_info: could not find a connection."); 728 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 729 } 730 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 731 connection->state = AVCTP_W2_SEND_COMMAND; 732 733 connection->transaction_label++; 734 connection->command_opcode = AVRCP_CMD_OPCODE_UNIT_INFO; 735 connection->command_type = AVRCP_CTYPE_STATUS; 736 connection->subunit_type = AVRCP_SUBUNIT_TYPE_UNIT; //vendor unique 737 connection->subunit_id = AVRCP_SUBUNIT_ID_IGNORE; 738 memset(connection->cmd_operands, 0xFF, connection->cmd_operands_length); 739 connection->cmd_operands_length = 5; 740 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 741 return ERROR_CODE_SUCCESS; 742 } 743 744 static uint8_t avrcp_controller_get_capabilities(uint16_t avrcp_cid, uint8_t capability_id){ 745 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 746 if (!connection){ 747 log_error("avrcp_get_capabilities: could not find a connection."); 748 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 749 } 750 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 751 connection->state = AVCTP_W2_SEND_COMMAND; 752 753 connection->transaction_label++; 754 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 755 connection->command_type = AVRCP_CTYPE_STATUS; 756 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 757 connection->subunit_id = AVRCP_SUBUNIT_ID; 758 big_endian_store_24(connection->cmd_operands, 0, BT_SIG_COMPANY_ID); 759 connection->cmd_operands[3] = AVRCP_PDU_ID_GET_CAPABILITIES; // PDU ID 760 connection->cmd_operands[4] = 0; 761 big_endian_store_16(connection->cmd_operands, 5, 1); // parameter length 762 connection->cmd_operands[7] = capability_id; // capability ID 763 connection->cmd_operands_length = 8; 764 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 765 return ERROR_CODE_SUCCESS; 766 } 767 768 uint8_t avrcp_controller_get_supported_company_ids(uint16_t avrcp_cid){ 769 return avrcp_controller_get_capabilities(avrcp_cid, AVRCP_CAPABILITY_ID_COMPANY); 770 } 771 772 uint8_t avrcp_controller_get_supported_events(uint16_t avrcp_cid){ 773 return avrcp_controller_get_capabilities(avrcp_cid, AVRCP_CAPABILITY_ID_EVENT); 774 } 775 776 777 uint8_t avrcp_controller_play(uint16_t avrcp_cid){ 778 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_PLAY, 0); 779 } 780 781 uint8_t avrcp_controller_stop(uint16_t avrcp_cid){ 782 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_STOP, 0); 783 } 784 785 uint8_t avrcp_controller_pause(uint16_t avrcp_cid){ 786 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_PAUSE, 0); 787 } 788 789 uint8_t avrcp_controller_forward(uint16_t avrcp_cid){ 790 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_FORWARD, 0); 791 } 792 793 uint8_t avrcp_controller_backward(uint16_t avrcp_cid){ 794 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_BACKWARD, 0); 795 } 796 797 uint8_t avrcp_controller_start_rewind(uint16_t avrcp_cid){ 798 return request_continuous_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_REWIND, 0); 799 } 800 801 uint8_t avrcp_controller_volume_up(uint16_t avrcp_cid){ 802 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_VOLUME_UP, 0); 803 } 804 805 uint8_t avrcp_controller_volume_down(uint16_t avrcp_cid){ 806 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_VOLUME_DOWN, 0); 807 } 808 809 uint8_t avrcp_controller_mute(uint16_t avrcp_cid){ 810 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_MUTE, 0); 811 } 812 813 uint8_t avrcp_controller_skip(uint16_t avrcp_cid){ 814 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_SKIP, 0); 815 } 816 817 uint8_t avrcp_controller_stop_rewind(uint16_t avrcp_cid){ 818 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 819 if (!connection){ 820 log_error("avrcp_stop_rewind: could not find a connection."); 821 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 822 } 823 if (connection->state != AVCTP_W4_STOP) return ERROR_CODE_COMMAND_DISALLOWED; 824 return request_pass_through_release_control_cmd(connection); 825 } 826 827 uint8_t avrcp_controller_start_fast_forward(uint16_t avrcp_cid){ 828 return request_continuous_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_FAST_FORWARD, 0); 829 } 830 831 uint8_t avrcp_controller_fast_forward(uint16_t avrcp_cid){ 832 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_FAST_FORWARD, 0); 833 } 834 835 uint8_t avrcp_controller_rewind(uint16_t avrcp_cid){ 836 return request_single_pass_through_press_control_cmd(avrcp_cid, AVRCP_OPERATION_ID_REWIND, 0); 837 } 838 839 840 uint8_t avrcp_controller_stop_fast_forward(uint16_t avrcp_cid){ 841 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 842 if (!connection){ 843 log_error("avrcp_stop_fast_forward: could not find a connection."); 844 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 845 } 846 if (connection->state != AVCTP_W4_STOP) return ERROR_CODE_COMMAND_DISALLOWED; 847 return request_pass_through_release_control_cmd(connection); 848 } 849 850 uint8_t avrcp_controller_get_play_status(uint16_t avrcp_cid){ 851 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 852 if (!connection){ 853 log_error("avrcp_get_play_status: could not find a connection."); 854 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 855 } 856 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 857 connection->state = AVCTP_W2_SEND_COMMAND; 858 connection->transaction_label++; 859 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 860 connection->command_type = AVRCP_CTYPE_STATUS; 861 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 862 connection->subunit_id = AVRCP_SUBUNIT_ID; 863 big_endian_store_24(connection->cmd_operands, 0, BT_SIG_COMPANY_ID); 864 connection->cmd_operands[3] = AVRCP_PDU_ID_GET_PLAY_STATUS; 865 connection->cmd_operands[4] = 0; // reserved(upper 6) | packet_type -> 0 866 big_endian_store_16(connection->cmd_operands, 5, 0); // parameter length 867 connection->cmd_operands_length = 7; 868 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 869 return ERROR_CODE_SUCCESS; 870 } 871 872 uint8_t avrcp_controller_enable_notification(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id){ 873 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 874 if (!connection){ 875 log_error("avrcp_get_play_status: could not find a connection."); 876 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 877 } 878 avrcp_register_notification(connection, event_id); 879 return ERROR_CODE_SUCCESS; 880 } 881 882 uint8_t avrcp_controller_disable_notification(uint16_t avrcp_cid, avrcp_notification_event_id_t event_id){ 883 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 884 if (!connection){ 885 log_error("avrcp_get_play_status: could not find a connection."); 886 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 887 } 888 connection->notifications_to_deregister |= (1 << event_id); 889 return ERROR_CODE_SUCCESS; 890 } 891 892 uint8_t avrcp_controller_get_now_playing_info(uint16_t avrcp_cid){ 893 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 894 if (!connection){ 895 log_error("avrcp_get_capabilities: could not find a connection."); 896 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 897 } 898 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 899 connection->state = AVCTP_W2_SEND_COMMAND; 900 901 connection->transaction_label++; 902 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 903 connection->command_type = AVRCP_CTYPE_STATUS; 904 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 905 connection->subunit_id = AVRCP_SUBUNIT_ID; 906 int pos = 0; 907 big_endian_store_24(connection->cmd_operands, pos, BT_SIG_COMPANY_ID); 908 pos += 3; 909 connection->cmd_operands[pos++] = AVRCP_PDU_ID_GET_ELEMENT_ATTRIBUTES; // PDU ID 910 connection->cmd_operands[pos++] = 0; 911 912 // Parameter Length 913 big_endian_store_16(connection->cmd_operands, pos, 9); 914 pos += 2; 915 916 // write 8 bytes value 917 memset(connection->cmd_operands + pos, 0, 8); // identifier: PLAYING 918 pos += 8; 919 920 connection->cmd_operands[pos++] = 0; // attribute count, if 0 get all attributes 921 // every attribute is 4 bytes long 922 923 connection->cmd_operands_length = pos; 924 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 925 return ERROR_CODE_SUCCESS; 926 } 927 928 uint8_t avrcp_controller_set_absolute_volume(uint16_t avrcp_cid, uint8_t volume){ 929 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 930 if (!connection){ 931 log_error("avrcp_get_capabilities: could not find a connection."); 932 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 933 } 934 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 935 connection->state = AVCTP_W2_SEND_COMMAND; 936 937 connection->transaction_label++; 938 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 939 connection->command_type = AVRCP_CTYPE_CONTROL; 940 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 941 connection->subunit_id = AVRCP_SUBUNIT_ID; 942 int pos = 0; 943 big_endian_store_24(connection->cmd_operands, pos, BT_SIG_COMPANY_ID); 944 pos += 3; 945 connection->cmd_operands[pos++] = AVRCP_PDU_ID_SET_ABSOLUTE_VOLUME; // PDU ID 946 connection->cmd_operands[pos++] = 0; 947 948 // Parameter Length 949 big_endian_store_16(connection->cmd_operands, pos, 1); 950 pos += 2; 951 connection->cmd_operands[pos++] = volume; 952 953 connection->cmd_operands_length = pos; 954 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 955 return ERROR_CODE_SUCCESS; 956 } 957 958 uint8_t avrcp_controller_query_shuffle_and_repeat_modes(uint16_t avrcp_cid){ 959 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 960 if (!connection){ 961 log_error("avrcp_get_capabilities: could not find a connection."); 962 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 963 } 964 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 965 connection->state = AVCTP_W2_SEND_COMMAND; 966 967 connection->transaction_label++; 968 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 969 connection->command_type = AVRCP_CTYPE_STATUS; 970 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 971 connection->subunit_id = AVRCP_SUBUNIT_ID; 972 big_endian_store_24(connection->cmd_operands, 0, BT_SIG_COMPANY_ID); 973 connection->cmd_operands[3] = AVRCP_PDU_ID_GetCurrentPlayerApplicationSettingValue; // PDU ID 974 connection->cmd_operands[4] = 0; 975 big_endian_store_16(connection->cmd_operands, 5, 5); // parameter length 976 connection->cmd_operands[7] = 4; // NumPlayerApplicationSettingAttributeID 977 // PlayerApplicationSettingAttributeID1 AVRCP Spec, Appendix F, 133 978 connection->cmd_operands[8] = 0x01; // equalizer (1-OFF, 2-ON) 979 connection->cmd_operands[9] = 0x02; // repeat (1-off, 2-single track, 3-all tracks, 4-group repeat) 980 connection->cmd_operands[10] = 0x03; // shuffle (1-off, 2-all tracks, 3-group shuffle) 981 connection->cmd_operands[11] = 0x04; // scan (1-off, 2-all tracks, 3-group scan) 982 connection->cmd_operands_length = 12; 983 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 984 return ERROR_CODE_SUCCESS; 985 } 986 987 static uint8_t avrcp_controller_set_current_player_application_setting_value(uint16_t avrcp_cid, uint8_t attr_id, uint8_t attr_value){ 988 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 989 if (!connection){ 990 log_error("avrcp_get_capabilities: could not find a connection."); 991 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 992 } 993 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 994 connection->state = AVCTP_W2_SEND_COMMAND; 995 996 connection->transaction_label++; 997 connection->command_opcode = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT; 998 connection->command_type = AVRCP_CTYPE_CONTROL; 999 connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL; 1000 connection->subunit_id = AVRCP_SUBUNIT_ID; 1001 int pos = 0; 1002 big_endian_store_24(connection->cmd_operands, pos, BT_SIG_COMPANY_ID); 1003 pos += 3; 1004 connection->cmd_operands[pos++] = AVRCP_PDU_ID_SetPlayerApplicationSettingValue; // PDU ID 1005 connection->cmd_operands[pos++] = 0; 1006 // Parameter Length 1007 big_endian_store_16(connection->cmd_operands, pos, 3); 1008 pos += 2; 1009 connection->cmd_operands[pos++] = 2; 1010 connection->cmd_operands_length = pos; 1011 connection->cmd_operands[pos++] = attr_id; 1012 connection->cmd_operands[pos++] = attr_value; 1013 connection->cmd_operands_length = pos; 1014 avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid); 1015 return ERROR_CODE_SUCCESS; 1016 } 1017 1018 uint8_t avrcp_controller_set_shuffle_mode(uint16_t avrcp_cid, avrcp_shuffle_mode_t mode){ 1019 if (mode < AVRCP_SHUFFLE_MODE_OFF || mode > AVRCP_SHUFFLE_MODE_GROUP) return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; 1020 return avrcp_controller_set_current_player_application_setting_value(avrcp_cid, 0x03, mode); 1021 } 1022 1023 uint8_t avrcp_controller_set_repeat_mode(uint16_t avrcp_cid, avrcp_repeat_mode_t mode){ 1024 if (mode < AVRCP_REPEAT_MODE_OFF || mode > AVRCP_REPEAT_MODE_GROUP) return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; 1025 return avrcp_controller_set_current_player_application_setting_value(avrcp_cid, 0x02, mode); 1026 } 1027 1028 uint8_t avrcp_controller_disconnect(uint16_t avrcp_cid){ 1029 avrcp_connection_t * connection = get_avrcp_connection_for_avrcp_cid(avrcp_cid, &avrcp_controller_context); 1030 if (!connection){ 1031 log_error("avrcp_get_capabilities: could not find a connection."); 1032 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; 1033 } 1034 if (connection->state != AVCTP_CONNECTION_OPENED) return ERROR_CODE_COMMAND_DISALLOWED; 1035 l2cap_disconnect(connection->l2cap_signaling_cid, 0); 1036 return ERROR_CODE_SUCCESS; 1037 }