forked from espressif/esp-idf
Merge branch 'feature/support_get_play_status_in_avrcp' into 'master'
feat(bt/bluedroid): Support get play status in AVRCP CT See merge request espressif/esp-idf!35674
This commit is contained in:
@@ -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;
|
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
|
#if BTC_AV_CA_INCLUDED
|
||||||
|
|
||||||
esp_err_t esp_avrc_ct_cover_art_connect(uint16_t mtu)
|
esp_err_t esp_avrc_ct_cover_art_connect(uint16_t mtu)
|
||||||
|
@@ -323,6 +323,15 @@ typedef union {
|
|||||||
int attr_length; /*!< attribute character length */
|
int attr_length; /*!< attribute character length */
|
||||||
} meta_rsp; /*!< metadata attributes response */
|
} 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
|
* @brief ESP_AVRC_CT_CHANGE_NOTIFY_EVT
|
||||||
*/
|
*/
|
||||||
@@ -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);
|
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
|
* @brief Register application callbacks to AVRCP target module. This function should be
|
||||||
|
@@ -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, ¶m);
|
btc_avrc_ct_cb_to_app(ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT, ¶m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_rc_get_play_status_rsp(tAVRC_GET_PLAY_STATUS_RSP *rsp)
|
||||||
|
{
|
||||||
|
esp_avrc_ct_cb_param_t param;
|
||||||
|
memset(¶m, 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, ¶m);
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Function handle_rc_metamsg_cmd
|
* Function handle_rc_metamsg_cmd
|
||||||
*
|
*
|
||||||
@@ -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);
|
handle_rc_set_absolute_volume_rsp(&avrc_response.volume);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case AVRC_PDU_GET_PLAY_STATUS:
|
||||||
|
handle_rc_get_play_status_rsp(&avrc_response.get_play_status);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BTC_TRACE_WARNING("%s: unhandled meta rsp: pdu 0x%x", __FUNCTION__, avrc_response.rsp.pdu);
|
BTC_TRACE_WARNING("%s: unhandled meta rsp: pdu 0x%x", __FUNCTION__, avrc_response.rsp.pdu);
|
||||||
}
|
}
|
||||||
@@ -1333,6 +1348,38 @@ static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask)
|
|||||||
return status;
|
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)
|
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;
|
tAVRC_STS status = BT_STATUS_UNSUPPORTED;
|
||||||
@@ -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);
|
btc_avrc_ct_send_metadata_cmd(arg->md_cmd.tl, arg->md_cmd.attr_mask);
|
||||||
break;
|
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: {
|
case BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT: {
|
||||||
btc_avrc_ct_send_get_rn_caps_cmd(arg->get_caps_cmd.tl);
|
btc_avrc_ct_send_get_rn_caps_cmd(arg->get_caps_cmd.tl);
|
||||||
break;
|
break;
|
||||||
|
@@ -37,6 +37,7 @@ typedef enum {
|
|||||||
BTC_AVRC_STATUS_API_SND_META_EVT,
|
BTC_AVRC_STATUS_API_SND_META_EVT,
|
||||||
BTC_AVRC_STATUS_API_SND_PLAY_STATUS_EVT,
|
BTC_AVRC_STATUS_API_SND_PLAY_STATUS_EVT,
|
||||||
BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_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_NOTIFY_API_SND_REG_NOTIFY_EVT,
|
||||||
BTC_AVRC_CTRL_API_SND_SET_PLAYER_SETTING_EVT,
|
BTC_AVRC_CTRL_API_SND_SET_PLAYER_SETTING_EVT,
|
||||||
BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT,
|
BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT,
|
||||||
@@ -76,6 +77,10 @@ typedef struct {
|
|||||||
uint8_t tl;
|
uint8_t tl;
|
||||||
} get_caps_cmd_t;
|
} get_caps_cmd_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t tl;
|
||||||
|
} get_play_status_cmd_t;
|
||||||
|
|
||||||
#define BTC_AVRC_MIN_VOLUME 0x00
|
#define BTC_AVRC_MIN_VOLUME 0x00
|
||||||
#define BTC_AVRC_MAX_VOLUME 0x7f
|
#define BTC_AVRC_MAX_VOLUME 0x7f
|
||||||
|
|
||||||
@@ -113,6 +118,7 @@ typedef union {
|
|||||||
rn_cmd_t rn_cmd;
|
rn_cmd_t rn_cmd;
|
||||||
ps_cmd_t ps_cmd;
|
ps_cmd_t ps_cmd;
|
||||||
get_caps_cmd_t get_caps_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;
|
set_abs_vol_cmd_t set_abs_vol_cmd;
|
||||||
#if BTC_AV_CA_INCLUDED
|
#if BTC_AV_CA_INCLUDED
|
||||||
ca_conn_t ca_conn;
|
ca_conn_t ca_conn;
|
||||||
|
@@ -956,7 +956,7 @@
|
|||||||
|
|
||||||
/* The number of security records for services. 32 AS Default*/
|
/* The number of security records for services. 32 AS Default*/
|
||||||
#ifndef BTM_SEC_MAX_SERVICE_RECORDS
|
#ifndef BTM_SEC_MAX_SERVICE_RECORDS
|
||||||
#define BTM_SEC_MAX_SERVICE_RECORDS 8 // 32
|
#define BTM_SEC_MAX_SERVICE_RECORDS 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If True, force a retrieval of remote device name for each bond in case it's changed */
|
/* If True, force a retrieval of remote device name for each bond in case it's changed */
|
||||||
|
@@ -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_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
|
||||||
p_data = p_start + 2; /* pdu + rsvd */
|
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);
|
UINT16_TO_BE_STREAM(p_data, 1);
|
||||||
UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu);
|
UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu);
|
||||||
p_pkt->len = (p_data - p_start);
|
p_pkt->len = (p_data - p_start);
|
||||||
@@ -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 */
|
/* get the existing length, if any, and also the num attributes */
|
||||||
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
|
p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset;
|
||||||
p_data = p_start + 2; /* pdu + rsvd */
|
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);
|
UINT16_TO_BE_STREAM(p_data, 1);
|
||||||
UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume));
|
UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume));
|
||||||
p_pkt->len = (p_data - p_start);
|
p_pkt->len = (p_data - p_start);
|
||||||
@@ -163,7 +163,7 @@ static BT_HDR *avrc_bld_init_cmd_buffer(tAVRC_COMMAND *p_cmd)
|
|||||||
/* reserved 0, packet_type 0 */
|
/* reserved 0, packet_type 0 */
|
||||||
UINT8_TO_BE_STREAM(p_data, 0);
|
UINT8_TO_BE_STREAM(p_data, 0);
|
||||||
/* continue to the next "case to add length */
|
/* continue to the next "case to add length */
|
||||||
/* add fixed lenth - 0 */
|
/* add fixed length - 0 */
|
||||||
UINT16_TO_BE_STREAM(p_data, 0);
|
UINT16_TO_BE_STREAM(p_data, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -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;
|
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)
|
static tAVRC_STS avrc_bld_get_caps_cmd(tAVRC_GET_CAPS_CMD *p_cmd, BT_HDR *p_pkt)
|
||||||
{
|
{
|
||||||
UINT8 *p_data, *p_start;
|
UINT8 *p_data, *p_start;
|
||||||
@@ -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);
|
status = avrc_bld_get_element_attr_cmd(&p_cmd->get_elem_attrs, p_pkt);
|
||||||
break;
|
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 */
|
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);
|
status = avrc_bld_register_change_notfn(p_cmd->reg_notif.event_id, p_cmd->reg_notif.param, p_pkt);
|
||||||
break;
|
break;
|
||||||
|
@@ -113,6 +113,19 @@ static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
status = AVRC_STS_BAD_CMD;
|
status = AVRC_STS_BAD_CMD;
|
||||||
break;
|
break;
|
||||||
|
@@ -359,7 +359,7 @@ UINT16 GOEPC_RequestAddHeader(UINT16 handle, UINT8 header_id, const UINT8 *data,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((data == NULL) ^ (data_len == 0)) {
|
if ((data == NULL && data_len != 0) || (data != NULL && data_len == 0)) {
|
||||||
ret = GOEP_INVALID_PARAM;
|
ret = GOEP_INVALID_PARAM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -491,7 +491,7 @@ UINT16 OBEX_AppendHeaderRaw(BT_HDR *pkt, UINT8 header_id, const UINT8 *data, UIN
|
|||||||
return OBEX_INVALID_PARAM;
|
return OBEX_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((data == NULL) ^ (data_len == 0)) {
|
if ((data == NULL && data_len != 0) || (data != NULL && data_len == 0)) {
|
||||||
return OBEX_INVALID_PARAM;
|
return OBEX_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user