component/bt: add AVRC event for remote features indication

1. remove the feature mask parameter from AVRC connection state event, as the AVCTP connection can be initiated by remote device before service discovery to remote device is performed. \
In this case, AVRCP connection state event may not be reported after connection initated by remote device is established.
2. remove ESP_AVRC_CT_MAX_EVT
3. add more documentations to AVRC APIs
This commit is contained in:
wangmengyang 2017-12-27 19:49:11 +08:00
parent 5401a75bad
commit e07b43e924
6 changed files with 77 additions and 89 deletions

View file

@ -58,10 +58,10 @@ typedef enum {
ESP_AVRC_CT_METADATA_RSP_EVT = 2, /*!< metadata response event */
ESP_AVRC_CT_PLAY_STATUS_RSP_EVT = 3, /*!< play status response event */
ESP_AVRC_CT_CHANGE_NOTIFY_EVT = 4, /*!< notification event */
ESP_AVRC_CT_MAX_EVT
ESP_AVRC_CT_REMOTE_FEATURES_EVT = 5, /*!< feature of remote device indication event */
} esp_avrc_ct_cb_event_t;
//AVRC metadata attribute mask
/// AVRC metadata attribute mask
typedef enum {
ESP_AVRC_MD_ATTR_TITLE = 0x1, /*!< title of the playing track */
ESP_AVRC_MD_ATTR_ARTIST = 0x2, /*!< track artist */
@ -72,7 +72,7 @@ typedef enum {
ESP_AVRC_MD_ATTR_PLAYING_TIME = 0x40 /*!< total album playing time in miliseconds */
} esp_avrc_md_attr_mask_t;
//AVRC event notification ids
/// AVRC event notification ids
typedef enum {
ESP_AVRC_RN_PLAY_STATUS_CHANGE = 0x01, /*!< track status change, eg. from playing to paused */
ESP_AVRC_RN_TRACK_CHANGE = 0x02, /*!< new track is loaded */
@ -85,7 +85,7 @@ typedef enum {
ESP_AVRC_RN_MAX_EVT
} esp_avrc_rn_event_ids_t;
//AVRC player setting ids
/// AVRC player setting ids
typedef enum {
ESP_AVRC_PS_EQUALIZER = 0x01, /*!< equalizer, on or off */
ESP_AVRC_PS_REPEAT_MODE = 0x02, /*!< repeat mode */
@ -94,32 +94,32 @@ typedef enum {
ESP_AVRC_PS_MAX_ATTR
} esp_avrc_ps_attr_ids_t;
//AVRC equalizer modes
/// AVRC equalizer modes
typedef enum {
ESP_AVRC_PS_EQUALIZER_OFF = 0x1,
ESP_AVRC_PS_EQUALIZER_ON = 0x2
ESP_AVRC_PS_EQUALIZER_OFF = 0x1, /*!< equalizer OFF */
ESP_AVRC_PS_EQUALIZER_ON = 0x2 /*!< equalizer ON */
} esp_avrc_ps_eq_value_ids_t;
//AVRC repeat modes
/// AVRC repeat modes
typedef enum {
ESP_AVRC_PS_REPEAT_OFF = 0x1,
ESP_AVRC_PS_REPEAT_SINGLE = 0x2,
ESP_AVRC_PS_REPEAT_GROUP = 0x3
ESP_AVRC_PS_REPEAT_OFF = 0x1, /*!< repeat mode off */
ESP_AVRC_PS_REPEAT_SINGLE = 0x2, /*!< single track repeat */
ESP_AVRC_PS_REPEAT_GROUP = 0x3 /*!< group repeat */
} esp_avrc_ps_rpt_value_ids_t;
//AVRC shuffle modes
/// AVRC shuffle modes
typedef enum {
ESP_AVRC_PS_SHUFFLE_OFF = 0x1,
ESP_AVRC_PS_SHUFFLE_ALL = 0x2,
ESP_AVRC_PS_SHUFFLE_GROUP = 0x3
ESP_AVRC_PS_SHUFFLE_OFF = 0x1, /*<! shuffle off */
ESP_AVRC_PS_SHUFFLE_ALL = 0x2, /*<! all trackes shuffle */
ESP_AVRC_PS_SHUFFLE_GROUP = 0x3 /*<! group shuffle */
} esp_avrc_ps_shf_value_ids_t;
//AVRC scan modes
/// AVRC scan modes
typedef enum {
ESP_AVRC_PS_SCAN_OFF = 0x1,
ESP_AVRC_PS_SCAN_ALL = 0x2,
ESP_AVRC_PS_SCAN_GROUP = 0x3
ESP_AVRC_PS_SCAN_OFF = 0x1, /*!< scan off */
ESP_AVRC_PS_SCAN_ALL = 0x2, /*!< all tracks scan */
ESP_AVRC_PS_SCAN_GROUP = 0x3 /*!< group scan */
} esp_avrc_ps_scn_value_ids_t;
/// AVRC controller callback parameters
@ -129,7 +129,6 @@ typedef union {
*/
struct avrc_ct_conn_stat_param {
bool connected; /*!< whether AVRC connection is set up */
uint32_t feat_mask; /*!< AVRC feature mask of remote device */
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */
} conn_stat; /*!< AVRC connection status */
@ -159,6 +158,14 @@ typedef union {
uint32_t event_parameter; /*!< event notification parameter */
} change_ntf; /*!< notifications */
/**
* @brief ESP_AVRC_CT_REMOTE_FEATURES_EVT
*/
struct avrc_ct_rmt_feats_param {
uint32_t feat_mask; /*!< AVRC feature mask of remote device */
esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */
} rmt_feats; /*!< AVRC features discovered from remote SDP server */
} esp_avrc_ct_cb_param_t;
@ -212,7 +219,19 @@ esp_err_t esp_avrc_ct_init(void);
*/
esp_err_t esp_avrc_ct_deinit(void);
/* add description */
/**
*
* @brief Send player application settings 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.
* @param[in] attr_id : player application setting attribute IDs from one of esp_avrc_ps_attr_ids_t
* @param[in] value_id : attribute value defined for the specific player application setting attribute
* @return
* - ESP_OK: success
* - ESP_INVALID_STATE: if bluetooth stack is not yet enabled
* - ESP_FAIL: others
*/
esp_err_t esp_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t attr_id, uint8_t value_id);
/**

View file

@ -529,6 +529,7 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
bdcpy(rc_open.peer_addr, p_data->rc_conn_chg.peer_addr);
rc_open.peer_features = p_cb->rcb[i].peer_features;
rc_open.sdp_disc_done = TRUE;
rc_open.status = BTA_AV_SUCCESS;
APPL_TRACE_DEBUG("local features:x%x peer_features:x%x", p_cb->features,
rc_open.peer_features);
@ -536,6 +537,7 @@ void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
/* we have not done SDP on peer RC capabilities.
* peer must have initiated the RC connection */
rc_open.peer_features = BTA_AV_FEAT_RCCT;
rc_open.sdp_disc_done = FALSE;
bta_av_rc_disc(disc);
}
(*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
@ -1610,6 +1612,7 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
p_scb->use_rc = FALSE;
bdcpy(rc_open.peer_addr, p_scb->peer_addr);
rc_open.peer_features = 0;
rc_open.sdp_disc_done = FALSE;
rc_open.status = BTA_AV_FAIL_SDP;
(*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
}

View file

@ -375,6 +375,7 @@ typedef struct {
/* data associated with BTA_AV_RC_OPEN_EVT */
typedef struct {
UINT8 rc_handle;
BOOLEAN sdp_disc_done;
tBTA_AV_FEAT peer_features;
BD_ADDR peer_addr;
tBTA_AV_STATUS status;

View file

@ -120,30 +120,11 @@ static inline void btc_avrc_ct_cb_to_app(esp_avrc_ct_cb_event_t event, esp_avrc_
static void handle_rc_features(void)
{
btrc_remote_features_t rc_features = BTRC_FEAT_NONE;
bt_bdaddr_t rc_addr;
bdcpy(rc_addr.address, btc_rc_vb.rc_addr);
// TODO(eisenbach): If devices need to be blacklisted for absolute
// volume, it should be added to device/include/interop_database.h
// For now, everything goes... If blacklisting is necessary, exclude
// the following bit here:
// btc_rc_vb.rc_features &= ~BTA_AV_FEAT_ADV_CTRL;
if (btc_rc_vb.rc_features & BTA_AV_FEAT_BROWSE) {
rc_features |= BTRC_FEAT_BROWSE;
}
if ( (btc_rc_vb.rc_features & BTA_AV_FEAT_ADV_CTRL) &&
(btc_rc_vb.rc_features & BTA_AV_FEAT_RCTG)) {
rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
}
if (btc_rc_vb.rc_features & BTA_AV_FEAT_METADATA) {
rc_features |= BTRC_FEAT_METADATA;
}
LOG_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
esp_avrc_ct_cb_param_t param;
memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
param.rmt_feats.feat_mask = btc_rc_vb.rc_features;
memcpy(param.rmt_feats.remote_bda, btc_rc_vb.rc_addr, sizeof(esp_bd_addr_t));
btc_avrc_ct_cb_to_app(ESP_AVRC_CT_REMOTE_FEATURES_EVT, &param);
}
@ -158,9 +139,7 @@ static void handle_rc_features(void)
static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
{
LOG_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle);
#if (AVRC_CTLR_INCLUDED == TRUE)
bt_bdaddr_t rc_addr;
#endif
if (p_rc_open->status == BTA_AV_SUCCESS) {
//check if already some RC is connected
@ -182,22 +161,18 @@ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
btc_rc_vb.rc_connected = TRUE;
btc_rc_vb.rc_handle = p_rc_open->rc_handle;
/* on locally initiated connection we will get remote features as part of connect */
if (btc_rc_vb.rc_features != 0) {
handle_rc_features();
}
#if (AVRC_CTLR_INCLUDED == TRUE)
bdcpy(rc_addr.address, btc_rc_vb.rc_addr);
/* report connection state if device is AVRCP target */
if (btc_rc_vb.rc_features & BTA_AV_FEAT_RCTG) {
esp_avrc_ct_cb_param_t param;
memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
param.conn_stat.connected = true;
param.conn_stat.feat_mask = btc_rc_vb.rc_features;
memcpy(param.conn_stat.remote_bda, &rc_addr, sizeof(esp_bd_addr_t));
btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, &param);
/* on locally initiated connection we will get remote features as part of connect */
if (p_rc_open->sdp_disc_done == TRUE) {
handle_rc_features();
}
#endif
} else {
LOG_ERROR("%s Connect failed with error code: %d",
__FUNCTION__, p_rc_open->status);
@ -215,10 +190,8 @@ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
***************************************************************************/
static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
{
#if (AVRC_CTLR_INCLUDED == TRUE)
bt_bdaddr_t rc_addr;
tBTA_AV_FEAT features;
#endif
LOG_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle);
if ((p_rc_close->rc_handle != btc_rc_vb.rc_handle)
&& (bdcmp(btc_rc_vb.rc_addr, p_rc_close->peer_addr))) {
@ -230,26 +203,21 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
btc_rc_vb.rc_connected = FALSE;
memset(btc_rc_vb.rc_addr, 0, sizeof(BD_ADDR));
memset(btc_rc_vb.rc_notif, 0, sizeof(btc_rc_vb.rc_notif));
#if (AVRC_CTLR_INCLUDED == TRUE)
features = btc_rc_vb.rc_features;
#endif
btc_rc_vb.rc_features = 0;
btc_rc_vb.rc_vol_label = MAX_LABEL;
btc_rc_vb.rc_volume = MAX_VOLUME;
#if (AVRC_CTLR_INCLUDED == TRUE)
bdcpy(rc_addr.address, btc_rc_vb.rc_addr);
#endif
memset(btc_rc_vb.rc_addr, 0, sizeof(BD_ADDR));
#if (AVRC_CTLR_INCLUDED == TRUE)
/* report connection state if device is AVRCP target */
if (features & BTA_AV_FEAT_RCTG) {
/* report connection state */
esp_avrc_ct_cb_param_t param;
memset(&param, 0, sizeof(esp_avrc_ct_cb_param_t));
param.conn_stat.connected = false;
memcpy(param.conn_stat.remote_bda, &rc_addr, sizeof(esp_bd_addr_t));
btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, &param);
}
#endif
}
static void handle_rc_attributes_rsp ( tAVRC_MSG_VENDOR *vendor_msg)

View file

@ -28,14 +28,6 @@
#define BTC_AVRC_TGT_INCLUDED FALSE
#endif
/* Macros */
typedef enum {
BTRC_FEAT_NONE = 0x00, /* AVRCP 1.0 */
BTRC_FEAT_METADATA = 0x01, /* AVRCP 1.3 */
BTRC_FEAT_ABSOLUTE_VOLUME = 0x02, /* Supports TG role and volume sync */
BTRC_FEAT_BROWSE = 0x04, /* AVRCP 1.4 and up, with Browsing support */
} btrc_remote_features_t;
typedef enum {
BTC_AVRC_CTRL_API_INIT_EVT = 0,
BTC_AVRC_CTRL_API_DEINIT_EVT,

View file

@ -79,7 +79,8 @@ void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param
bt_app_alloc_meta_buffer(param);
case ESP_AVRC_CT_CONNECTION_STATE_EVT:
case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT:
case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: {
case ESP_AVRC_CT_CHANGE_NOTIFY_EVT:
case ESP_AVRC_CT_REMOTE_FEATURES_EVT: {
bt_app_work_dispatch(bt_av_hdl_avrc_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL);
break;
}
@ -162,8 +163,8 @@ static void bt_av_hdl_avrc_evt(uint16_t event, void *p_param)
switch (event) {
case ESP_AVRC_CT_CONNECTION_STATE_EVT: {
uint8_t *bda = rc->conn_stat.remote_bda;
ESP_LOGI(BT_AV_TAG, "avrc conn_state evt: state %d, feature 0x%x, [%02x:%02x:%02x:%02x:%02x:%02x]",
rc->conn_stat.connected, rc->conn_stat.feat_mask, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
ESP_LOGI(BT_AV_TAG, "avrc conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]",
rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
if (rc->conn_stat.connected) {
bt_av_new_track();
@ -184,6 +185,10 @@ static void bt_av_hdl_avrc_evt(uint16_t event, void *p_param)
bt_av_notify_evt_handler(rc->change_ntf.event_id, rc->change_ntf.event_parameter);
break;
}
case ESP_AVRC_CT_REMOTE_FEATURES_EVT: {
ESP_LOGI(BT_AV_TAG, "avrc remote features %x", rc->rmt_feats.feat_mask);
break;
}
default:
ESP_LOGE(BT_AV_TAG, "%s unhandled evt %d", __func__, event);
break;