components/bt: Add AVRCP feature about volume
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user