Skip to content

Commit

Permalink
feat(bt/bluedroid): Support get play status in AVRCP CT
Browse files Browse the repository at this point in the history
  • Loading branch information
esp-lrh committed Dec 20, 2024
1 parent d679115 commit 4a9a6b1
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 3 deletions.
25 changes: 25 additions & 0 deletions components/bt/host/bluedroid/api/esp_avrc_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,31 @@ esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}

esp_err_t esp_avrc_ct_send_get_play_status_cmd(uint8_t tl)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}

if (tl > ESP_AVRC_TRANS_LABEL_MAX) {
return ESP_ERR_INVALID_ARG;
}

btc_msg_t msg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_AVRC_CT;
msg.act = BTC_AVRC_STATUS_API_SND_GET_PLAY_STATUS_EVT;

btc_avrc_args_t arg;
memset(&arg, 0, sizeof(btc_avrc_args_t));

arg.get_play_status_cmd.tl = tl;

/* Switch to BTC context */
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
}

#if BTC_AV_CA_INCLUDED

esp_err_t esp_avrc_ct_cover_art_connect(uint16_t mtu)
Expand Down
21 changes: 21 additions & 0 deletions components/bt/host/bluedroid/api/include/api/esp_avrc_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,15 @@ typedef union {
int attr_length; /*!< attribute character length */
} meta_rsp; /*!< metadata attributes response */

/**
* @brief ESP_AVRC_CT_PLAY_STATUS_RSP_EVT
*/
struct avrc_ct_get_play_status_rsp_param {
uint32_t song_length; /*!< total length of the playing song in milliseconds */
uint32_t song_position; /*!< current position of the playing song in milliseconds elapsed */
esp_avrc_playback_stat_t play_status; /*!< current status of playing */
} play_status_rsp; /*!< get play status command response */

/**
* @brief ESP_AVRC_CT_CHANGE_NOTIFY_EVT
*/
Expand Down Expand Up @@ -586,6 +595,18 @@ esp_err_t esp_avrc_ct_send_metadata_cmd(uint8_t tl, uint8_t attr_mask);
*/
esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state);

/**
* @brief Send get play status command to AVRCP target. This function should be called after
* ESP_AVRC_CT_CONNECTION_STATE_EVT is received and AVRCP connection is established.
*
* @param[in] tl : transaction label, 0 to 15, consecutive commands should use different values.
*
* @return
* - ESP_OK: success
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*/
esp_err_t esp_avrc_ct_send_get_play_status_cmd(uint8_t tl);

/**
* @brief Register application callbacks to AVRCP target module. This function should be
Expand Down
51 changes: 51 additions & 0 deletions components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,18 @@ static void handle_rc_set_absolute_volume_rsp(tAVRC_SET_VOLUME_RSP *rsp)
btc_avrc_ct_cb_to_app(ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT, &param);
}

static void handle_rc_get_play_status_rsp(tAVRC_GET_PLAY_STATUS_RSP *rsp)
{
esp_avrc_ct_cb_param_t param;
memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));

param.play_status_rsp.song_length = rsp->song_len;
param.play_status_rsp.song_position = rsp->song_pos;
param.play_status_rsp.play_status = rsp->play_status;

btc_avrc_ct_cb_to_app(ESP_AVRC_CT_PLAY_STATUS_RSP_EVT, &param);
}

/***************************************************************************
* Function handle_rc_metamsg_cmd
*
Expand Down Expand Up @@ -898,6 +910,9 @@ static void handle_rc_metamsg_rsp (tBTA_AV_META_MSG *p_meta_msg)
handle_rc_set_absolute_volume_rsp(&avrc_response.volume);
}
break;
case AVRC_PDU_GET_PLAY_STATUS:
handle_rc_get_play_status_rsp(&avrc_response.get_play_status);
break;
default:
BTC_TRACE_WARNING("%s: unhandled meta rsp: pdu 0x%x", __FUNCTION__, avrc_response.rsp.pdu);
}
Expand Down Expand Up @@ -1333,6 +1348,38 @@ static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask)
return status;
}

static bt_status_t btc_avrc_ct_send_get_play_status_cmd(uint8_t tl)
{
tAVRC_STS status = BT_STATUS_UNSUPPORTED;

#if (AVRC_METADATA_INCLUDED == TRUE)
CHECK_ESP_RC_CONNECTED;

tAVRC_COMMAND avrc_cmd = {0};
BT_HDR *p_msg = NULL;

avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR;
avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR;
avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS;

if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) {
status = AVRC_BldCommand(&avrc_cmd, &p_msg);
if (status == AVRC_STS_NO_ERROR) {
BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_STATUS, p_msg);
status = BT_STATUS_SUCCESS;
}
} else {
status = BT_STATUS_FAIL;
BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
}

#else
BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
#endif

return status;
}

static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state)
{
tAVRC_STS status = BT_STATUS_UNSUPPORTED;
Expand Down Expand Up @@ -1550,6 +1597,10 @@ void btc_avrc_ct_call_handler(btc_msg_t *msg)
btc_avrc_ct_send_metadata_cmd(arg->md_cmd.tl, arg->md_cmd.attr_mask);
break;
}
case BTC_AVRC_STATUS_API_SND_GET_PLAY_STATUS_EVT: {
btc_avrc_ct_send_get_play_status_cmd(arg->get_play_status_cmd.tl);
break;
}
case BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT: {
btc_avrc_ct_send_get_rn_caps_cmd(arg->get_caps_cmd.tl);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ typedef enum {
BTC_AVRC_STATUS_API_SND_META_EVT,
BTC_AVRC_STATUS_API_SND_PLAY_STATUS_EVT,
BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT,
BTC_AVRC_STATUS_API_SND_GET_PLAY_STATUS_EVT,
BTC_AVRC_NOTIFY_API_SND_REG_NOTIFY_EVT,
BTC_AVRC_CTRL_API_SND_SET_PLAYER_SETTING_EVT,
BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT,
Expand Down Expand Up @@ -76,6 +77,10 @@ typedef struct {
uint8_t tl;
} get_caps_cmd_t;

typedef struct {
uint8_t tl;
} get_play_status_cmd_t;

#define BTC_AVRC_MIN_VOLUME 0x00
#define BTC_AVRC_MAX_VOLUME 0x7f

Expand Down Expand Up @@ -113,6 +118,7 @@ typedef union {
rn_cmd_t rn_cmd;
ps_cmd_t ps_cmd;
get_caps_cmd_t get_caps_cmd;
get_play_status_cmd_t get_play_status_cmd;
set_abs_vol_cmd_t set_abs_vol_cmd;
#if BTC_AV_CA_INCLUDED
ca_conn_t ca_conn;
Expand Down
24 changes: 21 additions & 3 deletions components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static tAVRC_STS avrc_bld_next_cmd (tAVRC_NEXT_CMD *p_cmd, BT_HDR *p_pkt)
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */

/* add fixed lenth 1 - pdu_id (1) */
/* add fixed length 1 - pdu_id (1) */
UINT16_TO_BE_STREAM(p_data, 1);
UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu);
p_pkt->len = (p_data - p_start);
Expand Down Expand Up @@ -81,7 +81,7 @@ static tAVRC_STS avrc_bld_set_abs_volume_cmd (tAVRC_SET_VOLUME_CMD *p_cmd, BT_HD
/* get the existing length, if any, and also the num attributes */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */
/* add fixed lenth 1 - volume (1) */
/* add fixed length 1 - volume (1) */
UINT16_TO_BE_STREAM(p_data, 1);
UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume));
p_pkt->len = (p_data - p_start);
Expand Down Expand Up @@ -163,7 +163,7 @@ static BT_HDR *avrc_bld_init_cmd_buffer(tAVRC_COMMAND *p_cmd)
/* reserved 0, packet_type 0 */
UINT8_TO_BE_STREAM(p_data, 0);
/* continue to the next "case to add length */
/* add fixed lenth - 0 */
/* add fixed length - 0 */
UINT16_TO_BE_STREAM(p_data, 0);
break;
}
Expand Down Expand Up @@ -237,6 +237,20 @@ static tAVRC_STS avrc_bld_get_element_attr_cmd (tAVRC_GET_ELEM_ATTRS_CMD *p_cmd,
return AVRC_STS_NO_ERROR;
}

static tAVRC_STS avrc_bld_get_play_status_cmd(tAVRC_CMD *p_cmd, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;

AVRC_TRACE_API("avrc_bld_get_play_status");
/* get the existing length */
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
p_data = p_start + 2; /* pdu + rsvd */
/* add parameter length 0 */
UINT16_TO_BE_STREAM(p_data, 0);
p_pkt->len = (p_data - p_start);
return AVRC_STS_NO_ERROR;
}

static tAVRC_STS avrc_bld_get_caps_cmd(tAVRC_GET_CAPS_CMD *p_cmd, BT_HDR *p_pkt)
{
UINT8 *p_data, *p_start;
Expand Down Expand Up @@ -309,6 +323,10 @@ tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt)
status = avrc_bld_get_element_attr_cmd(&p_cmd->get_elem_attrs, p_pkt);
break;

case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */
status = avrc_bld_get_play_status_cmd(&p_cmd->get_play_status, p_pkt);
break;

case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
status = avrc_bld_register_change_notfn(p_cmd->reg_notif.event_id, p_cmd->reg_notif.param, p_pkt);
break;
Expand Down
13 changes: 13 additions & 0 deletions components/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,19 @@ static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p
}
}
break;
case AVRC_PDU_GET_PLAY_STATUS:
if (p_msg->hdr.ctype == AVRC_RSP_IMPL_STBL) {
BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p);
BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p);
BE_STREAM_TO_UINT8(p_result->get_play_status.play_status, p);
}
else {
/* got error response */
p_result->get_play_status.song_len = 0;
p_result->get_play_status.song_pos = 0;
p_result->get_play_status.play_status = AVRC_PLAYSTATE_ERROR;
}
break;
default:
status = AVRC_STS_BAD_CMD;
break;
Expand Down

0 comments on commit 4a9a6b1

Please sign in to comment.