|
|
@@ -31,6 +31,7 @@
|
|
|
#include "btc_manage.h"
|
|
|
#include "esp_avrc_api.h"
|
|
|
#include "mutex.h"
|
|
|
+#include "allocator.h"
|
|
|
|
|
|
#if BTC_AV_INCLUDED
|
|
|
|
|
|
@@ -96,6 +97,7 @@ rc_device_t device;
|
|
|
static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open);
|
|
|
static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close);
|
|
|
static void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp);
|
|
|
+static void handle_rc_metadata_rsp ( tBTA_AV_META_MSG *p_remote_rsp);
|
|
|
|
|
|
/*****************************************************************************
|
|
|
** Static variables
|
|
|
@@ -250,6 +252,86 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+static void handle_rc_attributes_rsp ( tAVRC_MSG_VENDOR *vendor_msg)
|
|
|
+{
|
|
|
+ uint8_t attr_count = vendor_msg->p_vendor_data[4];
|
|
|
+ int attr_index = 5;
|
|
|
+ int attr_length = 0;
|
|
|
+ uint32_t attr_id = 0;
|
|
|
+
|
|
|
+ //Check if there are any attributes
|
|
|
+ if (attr_count < 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ esp_avrc_ct_cb_param_t param[attr_count];
|
|
|
+ memset(¶m[0], 0, sizeof(esp_avrc_ct_cb_param_t) * attr_count);
|
|
|
+
|
|
|
+ for (int i = 0; i < attr_count; i++) {
|
|
|
+ attr_length = (int) vendor_msg->p_vendor_data[7 + attr_index] | vendor_msg->p_vendor_data[6 + attr_index] << 8;
|
|
|
+
|
|
|
+ //Received attribute text is not null terminated, so it's useful to know it's length
|
|
|
+ param[i].meta_rsp.attr_length = attr_length;
|
|
|
+ param[i].meta_rsp.attr_text = &vendor_msg->p_vendor_data[8 + attr_index];
|
|
|
+
|
|
|
+ attr_id = vendor_msg->p_vendor_data[3 + attr_index] |
|
|
|
+ vendor_msg->p_vendor_data[2 + attr_index] << 8 | vendor_msg->p_vendor_data[1 + attr_index] << 16 |
|
|
|
+ vendor_msg->p_vendor_data[attr_index] << 24;
|
|
|
+
|
|
|
+ //Convert to mask id
|
|
|
+ param[i].meta_rsp.attr_id = (1 << (attr_id - 1));
|
|
|
+
|
|
|
+ btc_avrc_ct_cb_to_app(ESP_AVRC_CT_METADATA_RSP_EVT, ¶m[i]);
|
|
|
+
|
|
|
+ attr_index += (int) vendor_msg->p_vendor_data[7 + attr_index] + 8;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void handle_rc_notification_rsp ( tAVRC_MSG_VENDOR *vendor_msg)
|
|
|
+{
|
|
|
+ esp_avrc_ct_cb_param_t param;
|
|
|
+
|
|
|
+ param.change_ntf.event_id = vendor_msg->p_vendor_data[4];
|
|
|
+
|
|
|
+ param.change_ntf.event_parameter = vendor_msg->p_vendor_data[5] << 24 | vendor_msg->p_vendor_data[6] << 16 |
|
|
|
+ vendor_msg->p_vendor_data[7] << 8 | vendor_msg->p_vendor_data[8];
|
|
|
+
|
|
|
+ btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CHANGE_NOTIFY_EVT, ¶m);
|
|
|
+}
|
|
|
+
|
|
|
+/***************************************************************************
|
|
|
+ * Function handle_rc_metadata_rsp
|
|
|
+ *
|
|
|
+ * - Argument: tBTA_AV_META_MSG metadata command response
|
|
|
+ *
|
|
|
+ * - Description: Vendor metadata response handler
|
|
|
+ *
|
|
|
+ ***************************************************************************/
|
|
|
+static void handle_rc_metadata_rsp ( tBTA_AV_META_MSG *p_remote_rsp)
|
|
|
+{
|
|
|
+#if (AVRC_METADATA_INCLUDED == TRUE)
|
|
|
+ tAVRC_MSG *avrc_msg = p_remote_rsp->p_msg;
|
|
|
+ tAVRC_MSG_VENDOR *vendor_msg = &avrc_msg->vendor;
|
|
|
+
|
|
|
+ //Check what type of metadata was received
|
|
|
+ switch (vendor_msg->hdr.ctype) {
|
|
|
+ case AVRC_RSP_CHANGED:
|
|
|
+ if (vendor_msg->p_vendor_data[0] == AVRC_PDU_REGISTER_NOTIFICATION) {
|
|
|
+ handle_rc_notification_rsp(vendor_msg);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case AVRC_RSP_IMPL_STBL:
|
|
|
+ if (vendor_msg->p_vendor_data[0] == AVRC_PDU_GET_ELEMENT_ATTR) {
|
|
|
+ handle_rc_attributes_rsp(vendor_msg);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+#else
|
|
|
+ LOG_ERROR("%s AVRCP metadata is not enabled", __FUNCTION__);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
/***************************************************************************
|
|
|
* Function handle_rc_passthrough_rsp
|
|
|
*
|
|
|
@@ -326,8 +408,12 @@ void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
+ case BTA_AV_META_MSG_EVT: {
|
|
|
+ handle_rc_metadata_rsp(&(p_data->meta_msg));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
// below events are not handled for now
|
|
|
- case BTA_AV_META_MSG_EVT:
|
|
|
case BTA_AV_REMOTE_CMD_EVT:
|
|
|
default:
|
|
|
LOG_DEBUG("Unhandled RC event : 0x%x", event);
|
|
|
@@ -390,13 +476,124 @@ static void btc_avrc_ct_deinit(void)
|
|
|
LOG_INFO("## %s ## completed", __FUNCTION__);
|
|
|
}
|
|
|
|
|
|
-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_set_player_value_cmd(uint8_t tl, uint8_t attr_id, uint8_t value_id)
|
|
|
+{
|
|
|
+ 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;
|
|
|
+ tAVRC_APP_SETTING values = {0};
|
|
|
+
|
|
|
+ values.attr_id = attr_id;
|
|
|
+ values.attr_val = value_id;
|
|
|
+
|
|
|
+ avrc_cmd.set_app_val.opcode = AVRC_OP_VENDOR;
|
|
|
+ avrc_cmd.set_app_val.status = AVRC_STS_NO_ERROR;
|
|
|
+ avrc_cmd.set_app_val.num_val = 1;
|
|
|
+ avrc_cmd.set_app_val.p_vals = &values;
|
|
|
+ avrc_cmd.set_app_val.pdu = AVRC_PDU_SET_PLAYER_APP_VALUE;
|
|
|
+
|
|
|
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
|
|
|
+ if (status == AVRC_STS_NO_ERROR) {
|
|
|
+ if (btc_rc_vb.rc_features & BTA_AV_FEAT_METADATA) {
|
|
|
+ BTA_AvMetaCmd(btc_rc_vb.rc_handle, tl, BTA_AV_CMD_CTRL, p_msg);
|
|
|
+ status = BT_STATUS_SUCCESS;
|
|
|
+ } else {
|
|
|
+ status = BT_STATUS_FAIL;
|
|
|
+ LOG_DEBUG("%s: feature not supported", __FUNCTION__);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#else
|
|
|
+ LOG_DEBUG("%s: feature not enabled", __FUNCTION__);
|
|
|
+#endif
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+static bt_status_t btc_avrc_ct_send_register_notification_cmd(uint8_t tl, uint8_t event_id, uint32_t event_parameter)
|
|
|
{
|
|
|
tAVRC_STS status = BT_STATUS_UNSUPPORTED;
|
|
|
- if (tl >= 16 ||
|
|
|
- key_state > ESP_AVRC_PT_CMD_STATE_RELEASED) {
|
|
|
- return ESP_ERR_INVALID_ARG;
|
|
|
+
|
|
|
+#if (AVRC_METADATA_INCLUDED == TRUE)
|
|
|
+ CHECK_ESP_RC_CONNECTED;
|
|
|
+
|
|
|
+ tAVRC_COMMAND avrc_cmd = {0};
|
|
|
+ BT_HDR *p_msg = NULL;
|
|
|
+
|
|
|
+ avrc_cmd.reg_notif.opcode = AVRC_OP_VENDOR;
|
|
|
+ avrc_cmd.reg_notif.status = AVRC_STS_NO_ERROR;
|
|
|
+ avrc_cmd.reg_notif.event_id = event_id;
|
|
|
+ avrc_cmd.reg_notif.param = event_parameter;
|
|
|
+ avrc_cmd.reg_notif.pdu = AVRC_PDU_REGISTER_NOTIFICATION;
|
|
|
+
|
|
|
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
|
|
|
+ if (status == AVRC_STS_NO_ERROR) {
|
|
|
+ if (btc_rc_vb.rc_features & BTA_AV_FEAT_METADATA) {
|
|
|
+ BTA_AvMetaCmd(btc_rc_vb.rc_handle, tl, AVRC_CMD_NOTIF, p_msg);
|
|
|
+ status = BT_STATUS_SUCCESS;
|
|
|
+ } else {
|
|
|
+ status = BT_STATUS_FAIL;
|
|
|
+ LOG_DEBUG("%s: feature not supported", __FUNCTION__);
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+#else
|
|
|
+ LOG_DEBUG("%s: feature not enabled", __FUNCTION__);
|
|
|
+#endif
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask)
|
|
|
+{
|
|
|
+ tAVRC_STS status = BT_STATUS_UNSUPPORTED;
|
|
|
+
|
|
|
+#if (AVRC_METADATA_INCLUDED == TRUE)
|
|
|
+ CHECK_ESP_RC_CONNECTED;
|
|
|
+ uint32_t index = 0;
|
|
|
+
|
|
|
+ tAVRC_COMMAND avrc_cmd = {0};
|
|
|
+ BT_HDR *p_msg = NULL;
|
|
|
+
|
|
|
+ avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
|
|
|
+ avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
|
|
|
+ avrc_cmd.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
|
|
|
+
|
|
|
+ for (int count = 0; count < AVRC_MAX_ELEM_ATTR_SIZE; count++) {
|
|
|
+ if ((attr_mask & (1 << count)) > 0) {
|
|
|
+ avrc_cmd.get_elem_attrs.attrs[index] = count + 1;
|
|
|
+ index++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ avrc_cmd.get_elem_attrs.num_attr = index;
|
|
|
+
|
|
|
+ status = AVRC_BldCommand(&avrc_cmd, &p_msg);
|
|
|
+ if (status == AVRC_STS_NO_ERROR) {
|
|
|
+ if (btc_rc_vb.rc_features & BTA_AV_FEAT_METADATA) {
|
|
|
+ BTA_AvMetaCmd(btc_rc_vb.rc_handle, tl, AVRC_CMD_STATUS, p_msg);
|
|
|
+ status = BT_STATUS_SUCCESS;
|
|
|
+ } else {
|
|
|
+ status = BT_STATUS_FAIL;
|
|
|
+ LOG_DEBUG("%s: feature not supported", __FUNCTION__);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#else
|
|
|
+ LOG_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;
|
|
|
+
|
|
|
#if (AVRC_CTLR_INCLUDED == TRUE)
|
|
|
CHECK_ESP_RC_CONNECTED;
|
|
|
LOG_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
|
|
|
@@ -436,6 +633,18 @@ void btc_avrc_call_handler(btc_msg_t *msg)
|
|
|
// todo: callback to application
|
|
|
break;
|
|
|
}
|
|
|
+ case BTC_AVRC_STATUS_API_SND_META_EVT: {
|
|
|
+ btc_avrc_ct_send_metadata_cmd(arg->md_cmd.tl, arg->md_cmd.attr_mask);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case BTC_AVRC_NOTIFY_API_SND_REG_NOTIFY_EVT: {
|
|
|
+ btc_avrc_ct_send_register_notification_cmd(arg->rn_cmd.tl, arg->rn_cmd.event_id, arg->rn_cmd.event_parameter);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case BTC_AVRC_CTRL_API_SET_PLAYER_SETTING_EVT: {
|
|
|
+ btc_avrc_ct_send_set_player_value_cmd(arg->ps_cmd.tl, arg->ps_cmd.attr_id, arg->ps_cmd.value_id);
|
|
|
+ break;
|
|
|
+ }
|
|
|
default:
|
|
|
LOG_WARN("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
|
|
|
}
|