avrcp: get play status

This commit is contained in:
Milanka Ringwald 2017-02-06 16:54:38 +01:00 committed by Matthias Ringwald
parent a85ed257c2
commit 1270af140e
3 changed files with 108 additions and 8 deletions

View File

@ -412,7 +412,7 @@ static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connec
avrcp_subunit_type_t subunit_type;
avrcp_subunit_type_t subunit_id;
uint8_t operands[5];
uint8_t operands[20];
uint8_t opcode;
uint8_t value;
int pos = 0;
@ -448,10 +448,48 @@ static void avrcp_handle_l2cap_data_packet_for_signaling_connection(avrcp_connec
break;
}
case AVRCP_CMD_OPCODE_VENDOR_DEPENDENT:
ctype = packet[pos++];
value = packet[pos++];
subunit_type = value >> 3;
subunit_id = value & 0x07;
opcode = packet[pos++];
if (size - pos < 7) {
log_error("avrcp: wrong packet size");
return;
};
// operands:
memcpy(operands, packet+pos, 7);
pos += 7;
// uint32_t company_id = operands[0] << 16 | operands[1] << 8 | operands[2];
uint8_t pdu_id = operands[3];
// uint8_t unit_type = operands[4] >> 3;
// uint8_t unit = operands[4] & 0x07;
uint16_t param_length = big_endian_read_16(operands, 5);
// 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",
// ctype, subunit_type, subunit_id, opcode, unit_type, unit, company_id );
printf(" VENDOR DEPENDENT response: pdu id 0x%02x, param_length %d\n", pdu_id, param_length);
switch (pdu_id){
case AVRCP_PDU_ID_GET_PLAY_STATUS:{
uint32_t song_length = big_endian_read_32(packet, pos);
pos += 32;
uint32_t song_position = big_endian_read_32(packet, pos);
pos += 32;
uint8_t status = packet[pos];
printf_hexdump(packet+pos, size - pos);
printf(" GET_PLAY_STATUS length 0x%04X, position 0x%04X, status %d\n", song_length, song_position, status);
break;
}
default:
break;
}
break;
case AVRCP_CMD_OPCODE_PASS_THROUGH:
if (connection->state == AVCTP_W2_SEND_RELEASE_COMMAND){
request_pass_through_release_control_cmd(connection);
break;
}
break;
default:
@ -613,7 +651,7 @@ void avrcp_unit_info(uint16_t con_handle){
void avrcp_get_capabilities(uint16_t con_handle){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle);
if (!connection){
log_error("avrcp_unit_info: coud not find a connection.");
log_error("avrcp_get_capabilities: coud not find a connection.");
return;
}
if (connection->state != AVCTP_CONNECTION_OPENED) return;
@ -625,7 +663,7 @@ void avrcp_get_capabilities(uint16_t con_handle){
connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
connection->subunit_id = 0;
big_endian_store_24(connection->cmd_operands, 0, BT_SIG_COMPANY_ID);
connection->cmd_operands[3] = 0x10;
connection->cmd_operands[3] = AVRCP_PDU_ID_GET_CAPABILITIES; // PDU ID
connection->cmd_operands[4] = 0;
big_endian_store_16(connection->cmd_operands, 5, 1);
connection->cmd_operands[7] = 0x02;
@ -661,7 +699,7 @@ void avrcp_start_rewind(uint16_t con_handle){
void avrcp_stop_rewind(uint16_t con_handle){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle);
if (!connection){
log_error("avrcp_unit_info: coud not find a connection.");
log_error("avrcp_stop_rewind: coud not find a connection.");
return;
}
if (connection->state != AVCTP_W4_STOP) return;
@ -675,9 +713,31 @@ void avrcp_start_fast_forward(uint16_t con_handle){
void avrcp_stop_fast_forward(uint16_t con_handle){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle);
if (!connection){
log_error("avrcp_unit_info: coud not find a connection.");
log_error("avrcp_stop_fast_forward: coud not find a connection.");
return;
}
if (connection->state != AVCTP_W4_STOP) return;
request_pass_through_release_control_cmd(connection);
}
void avrcp_get_play_status(uint16_t con_handle){
avrcp_connection_t * connection = get_avrcp_connection_for_con_handle(con_handle);
if (!connection){
log_error("avrcp_get_play_status: coud not find a connection.");
return;
}
if (connection->state != AVCTP_CONNECTION_OPENED) return;
connection->state = AVCTP_W2_SEND_COMMAND;
connection->transaction_label++;
connection->cmd_to_send = AVRCP_CMD_OPCODE_VENDOR_DEPENDENT;
connection->command_type = AVRCP_CTYPE_STATUS;
connection->subunit_type = AVRCP_SUBUNIT_TYPE_PANEL;
connection->subunit_id = 0;
big_endian_store_24(connection->cmd_operands, 0, BT_SIG_COMPANY_ID);
connection->cmd_operands[3] = AVRCP_PDU_ID_GET_PLAY_STATUS;
connection->cmd_operands[4] = 0; // reserved(upper 6) | packet_type -> 0
big_endian_store_16(connection->cmd_operands, 5, 0); // parameter length
connection->cmd_operands_lenght = 7;
avrcp_request_can_send_now(connection, connection->l2cap_signaling_cid);
}

View File

@ -53,6 +53,23 @@ extern "C" {
#define BT_SIG_COMPANY_ID 0x001958
/* API_START */
typedef enum {
AVRCP_PDU_ID_GET_CAPABILITIES = 0x10,
AVRCP_PDU_ID_GET_PLAY_STATUS = 0x30,
AVRCP_PDU_ID_REGISTER_NOTIFICATION = 0x31
} avrcp_pdu_id_t;
typedef enum {
AVRCP_NOTIFICATION_EVENT_PLAYBACK_STATUS_CHANGED ,
AVRCP_NOTIFICATION_EVENT_TRACK_CHANGED,
AVRCP_NOTIFICATION_EVENT_NOW_PLAYING_CONTENT_CHANGED,
AVRCP_NOTIFICATION_EVENT_AVAILABLE_PLAYERS_CHANGED,
AVRCP_NOTIFICATION_EVENT_ADDRESSED_PLAYER_CHANGED,
AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED
} avrcp_notification_event_t;
typedef enum {
AVRCP_CTYPE_CONTROL = 0,
AVRCP_CTYPE_STATUS,
@ -153,6 +170,15 @@ typedef struct {
btstack_timer_source_t press_and_hold_cmd_timer;
} avrcp_connection_t;
typedef enum {
AVRCP_PLAY_STATUS_STOPPED = 0x00,
AVRCP_PLAY_STATUS_PLAYING,
AVRCP_PLAY_STATUS_PAUSED,
AVRCP_PLAY_STATUS_FWD_SEEK,
AVRCP_PLAY_STATUS_REV_SEEK,
AVRCP_PLAY_STATUS_ERROR = 0xFF
} avrcp_play_status_t;
/**
* @brief AVDTP Sink service record.
* @param service
@ -250,6 +276,13 @@ void avrcp_forward(uint16_t con_handle);
void avrcp_backward(uint16_t con_handle);
/**
* @brief Get play status. Returns event of type AVRCP_SUBEVENT_PLAY_STATUS (length, position, play_status).
* If TG does not support SongLength And SongPosition on TG, then TG shall return 0xFFFFFFFF.
* @param con_handle
*/
void avrcp_get_play_status(uint16_t con_handle);
/**
* @brief Register notification.
* - EVENT_PLAYBACK_STATUS_CHANGED

View File

@ -61,11 +61,12 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
// mac 2013: static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
// phone: static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
static bd_addr_t remote = {0xD8, 0xBB, 0x2C, 0xDF, 0xF1, 0x08};
// static bd_addr_t remote = {0xD8, 0xBB, 0x2C, 0xDF, 0xF1, 0x08};
static uint16_t con_handle = 0;
static uint8_t sdp_avrcp_controller_service_buffer[150];
static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(channel);
UNUSED(size);
@ -91,6 +92,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
printf("AVRCP_SUBEVENT_CONNECTION_RELEASED: con_handle 0x%02x\n", avrcp_subevent_connection_closed_get_con_handle(packet));
con_handle = 0;
break;
// case AVRCP_SUBEVENT_PLAY_STATUS:
// printf("AVRCP_SUBEVENT_PLAY_STATUS\n");
// break;
default:
printf("--- avrcp_test: Not implemented\n");
break;
@ -123,6 +127,7 @@ static void show_usage(void){
printf("R - avrcp_stop_rewind\n");
printf("f - avrcp_forward\n");
printf("b - avrcp_backward\n");
printf("S - get play status\n");
printf("Ctrl-c - exit\n");
printf("---\n");
}
@ -170,7 +175,9 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
case 'b':
avrcp_backward(con_handle);
break;
case 'S':
avrcp_get_play_status(con_handle);
break;
default:
show_usage();
break;