components/bt: Add AVRCP feature about volume

This commit is contained in:
baohongde
2019-06-28 11:29:07 +08:00
committed by bot
parent 39a5fbdfee
commit 30d7002731
8 changed files with 315 additions and 64 deletions
+115 -1
View File
@@ -27,6 +27,11 @@
#include "esp_avrc_api.h"
#define BT_AV_TAG "BT_AV"
#define BT_RC_CT_TAG "RCCT"
// AVRCP used transaction label
#define APP_RC_CT_TL_GET_CAPS (0)
#define APP_RC_CT_TL_RN_VOLUME_CHANGE (1)
/* event for handler "bt_av_hdl_stack_up */
enum {
@@ -63,11 +68,17 @@ static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param);
/// callback function for A2DP source audio data stream
static int32_t bt_app_a2d_data_cb(uint8_t *data, int32_t len);
/// callback function for AVRCP controller
static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param);
static void a2d_app_heart_beat(void *arg);
/// A2DP application state machine
static void bt_app_av_sm_hdlr(uint16_t event, void *param);
/// avrc CT event handler
static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param);
/* A2DP application state machine handler for each state */
static void bt_app_av_state_unconnected(uint16_t event, void *param);
static void bt_app_av_state_connecting(uint16_t event, void *param);
@@ -81,7 +92,7 @@ static int s_media_state = APP_AV_MEDIA_STATE_IDLE;
static int s_intv_cnt = 0;
static int s_connecting_intv = 0;
static uint32_t s_pkt_cnt = 0;
static esp_avrc_rn_evt_cap_mask_t s_avrc_peer_rn_cap;
static TimerHandle_t s_tmr;
static char *bda2str(esp_bd_addr_t bda, char *str, size_t size)
@@ -322,6 +333,14 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param)
/* register GAP callback function */
esp_bt_gap_register_callback(bt_app_gap_cb);
/* initialize AVRCP controller */
esp_avrc_ct_init();
esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
esp_avrc_rn_evt_cap_mask_t evt_set = {0};
esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_SET, &evt_set, ESP_AVRC_RN_VOLUME_CHANGE);
assert(esp_avrc_tg_set_rn_evt_cap(&evt_set) == ESP_OK);
/* initialize A2DP source */
esp_a2d_register_callback(&bt_app_a2d_cb);
esp_a2d_source_register_data_callback(bt_app_a2d_data_cb);
@@ -578,3 +597,98 @@ static void bt_app_av_state_disconnecting(uint16_t event, void *param)
break;
}
}
static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param)
{
switch (event) {
case ESP_AVRC_CT_METADATA_RSP_EVT:
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_REMOTE_FEATURES_EVT:
case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT:
case ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT: {
bt_app_work_dispatch(bt_av_hdl_avrc_ct_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL);
break;
}
default:
ESP_LOGE(BT_RC_CT_TAG, "Invalid AVRC event: %d", event);
break;
}
}
static void bt_av_volume_changed(void)
{
if (esp_avrc_rn_evt_bit_mask_operation(ESP_AVRC_BIT_MASK_OP_TEST, &s_avrc_peer_rn_cap,
ESP_AVRC_RN_VOLUME_CHANGE)) {
esp_avrc_ct_send_register_notification_cmd(APP_RC_CT_TL_RN_VOLUME_CHANGE, ESP_AVRC_RN_VOLUME_CHANGE, 0);
}
}
void bt_av_notify_evt_handler(uint8_t event_id, esp_avrc_rn_param_t *event_parameter)
{
switch (event_id) {
case ESP_AVRC_RN_VOLUME_CHANGE:
ESP_LOGI(BT_RC_CT_TAG, "Volume changed: %d", event_parameter->volume);
ESP_LOGI(BT_RC_CT_TAG, "Set absolute volume: volume %d", event_parameter->volume + 5);
esp_avrc_ct_send_set_absolute_volume_cmd(APP_RC_CT_TL_RN_VOLUME_CHANGE, event_parameter->volume + 5);
bt_av_volume_changed();
break;
}
}
static void bt_av_hdl_avrc_ct_evt(uint16_t event, void *p_param)
{
ESP_LOGD(BT_RC_CT_TAG, "%s evt %d", __func__, event);
esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(p_param);
switch (event) {
case ESP_AVRC_CT_CONNECTION_STATE_EVT: {
uint8_t *bda = rc->conn_stat.remote_bda;
ESP_LOGI(BT_RC_CT_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) {
// get remote supported event_ids of peer AVRCP Target
esp_avrc_ct_send_get_rn_capabilities_cmd(APP_RC_CT_TL_GET_CAPS);
} else {
// clear peer notification capability record
s_avrc_peer_rn_cap.bits = 0;
}
break;
}
case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: {
ESP_LOGI(BT_RC_CT_TAG, "AVRC passthrough rsp: key_code 0x%x, key_state %d", rc->psth_rsp.key_code, rc->psth_rsp.key_state);
break;
}
case ESP_AVRC_CT_METADATA_RSP_EVT: {
ESP_LOGI(BT_RC_CT_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text);
free(rc->meta_rsp.attr_text);
break;
}
case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: {
ESP_LOGI(BT_RC_CT_TAG, "AVRC event notification: %d", rc->change_ntf.event_id);
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_RC_CT_TAG, "AVRC remote features %x, TG features %x", rc->rmt_feats.feat_mask, rc->rmt_feats.tg_feat_flag);
break;
}
case ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT: {
ESP_LOGI(BT_RC_CT_TAG, "remote rn_cap: count %d, bitmask 0x%x", rc->get_rn_caps_rsp.cap_count,
rc->get_rn_caps_rsp.evt_set.bits);
s_avrc_peer_rn_cap.bits = rc->get_rn_caps_rsp.evt_set.bits;
bt_av_volume_changed();
break;
}
case ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT: {
ESP_LOGI(BT_RC_CT_TAG, "Set absolute volume rsp: volume %d", rc->set_volume_rsp.volume);
break;
}
default:
ESP_LOGE(BT_RC_CT_TAG, "%s unhandled evt %d", __func__, event);
break;
}
}