AVRCP
This manual describes the AVRCP API definition. AVRCP defines the features and procedures required in order to ensure interoperability between Bluetooth devices with audio/video control functions in the audio/video distribution scenarios.
Terminology and Concepts
AVRCP Roles
The following roles are defined for devices that implement this profile:
Controller (CT) - A device that initiates a transaction by sending a command frame to a target. Examples for CT are a personal computer, a Personal Digital Assistant, a mobile phone, a remote controller, or an audio/video device (such as an in car system, headphone, player/recorder, timer, tuner, monitor, etc.).
Target (TG) - A device that receives a command frame and accordingly generates a response frame. Examples for TG are an audio player/recorder, a video player/recorder, a TV, a tuner, an amplifier, or a headphone.
AVRCP SDP Record
AVRCP local record avrcp_ct_sdp_record
and avrcp_tg_sdp_record
should be registered by bt_sdp_record_add()
.
static const uint8_t avrcp_ct_sdp_record[] =
{
//Total length
SDP_DATA_ELEM_SEQ_HDR,
0x3B,//0x49,//0x62,
//Attribute SDP_ATTR_SRV_CLASS_ID_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_SRV_CLASS_ID_LIST >> 8),
(uint8_t)SDP_ATTR_SRV_CLASS_ID_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x06, //Attribute length: 6 bytes
//Service Class #0: A/V Remote Control
SDP_UUID16_HDR,
(uint8_t)(UUID_AV_REMOTE_CONTROL >> 8),
(uint8_t)(UUID_AV_REMOTE_CONTROL),
//Service Class #1: A/V Remote Control Controller
SDP_UUID16_HDR,
(uint8_t)(UUID_AV_REMOTE_CONTROL_CONTROLLER >> 8),
(uint8_t)(UUID_AV_REMOTE_CONTROL_CONTROLLER),
//Attribute SDP_ATTR_PROTO_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROTO_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROTO_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x10, //Attribute length: 12 bytes
//Protocol #0: L2CAP
SDP_DATA_ELEM_SEQ_HDR,
0x06, //Element length: 3 bytes
SDP_UUID16_HDR,
(uint8_t)(UUID_L2CAP >> 8),
(uint8_t)(UUID_L2CAP),
//Parameter #0 for Protocol #0: PSM = AVCTP
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(PSM_AVCTP >> 8),
(uint8_t)PSM_AVCTP,
//Protocol #1: AVCTP
SDP_DATA_ELEM_SEQ_HDR,
0x06, //Element length: 5 bytes
SDP_UUID16_HDR,
(uint8_t)(UUID_AVCTP >> 8),
(uint8_t)(UUID_AVCTP),
//Parameter #0 for Protocol #1: 0x0104 (v1.4)
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(0x0104 >> 8),
(uint8_t)(0x0104),
//Attribute SDP_ATTR_PROFILE_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROFILE_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROFILE_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x08, //Attribute length: 8 bytes
//Profile #0: A/V Remote Control
SDP_DATA_ELEM_SEQ_HDR,
0x06, //Element length: 6 bytes
SDP_UUID16_HDR,
(uint8_t)(UUID_AV_REMOTE_CONTROL >> 8),
(uint8_t)(UUID_AV_REMOTE_CONTROL),
//Parameter #0 for Profile #0: 0x0106 (v1.6)
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(0x0106 >> 8),
(uint8_t)(0x0106),
//Attribute SDP_ATTR_SUPPORTED_FEATURES
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_SUPPORTED_FEATURES) >> 8),
(uint8_t)(SDP_ATTR_SUPPORTED_FEATURES),
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(0x0001 >> 8), //Category 1 Player / Recorder //Supported Features
(uint8_t)(0x0001),
//Attribute SDP_ATTR_BROWSE_GROUP_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_BROWSE_GROUP_LIST >> 8),
(uint8_t)SDP_ATTR_BROWSE_GROUP_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x03,
SDP_UUID16_HDR,
(uint8_t)(UUID_PUBLIC_BROWSE_GROUP >> 8),
(uint8_t)UUID_PUBLIC_BROWSE_GROUP
};
static const uint8_t avrcp_tg_sdp_record[] =
{
//Total length
SDP_DATA_ELEM_SEQ_HDR,
0x38,//0x46,//0x5F,
//Attribute SDP_ATTR_SRV_CLASS_ID_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_SRV_CLASS_ID_LIST >> 8),
(uint8_t)SDP_ATTR_SRV_CLASS_ID_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x03, //Attribute length: 6 bytes
//Service Class #0: A/V Remote Control Target
SDP_UUID16_HDR,
(uint8_t)(UUID_AV_REMOTE_CONTROL_TARGET >> 8),
(uint8_t)(UUID_AV_REMOTE_CONTROL_TARGET),
//Attribute SDP_ATTR_PROTO_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROTO_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROTO_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x10, //Attribute length: 12 bytes
//Protocol #0: L2CAP
SDP_DATA_ELEM_SEQ_HDR,
0x06, //Element length: 3 bytes
SDP_UUID16_HDR,
(uint8_t)(UUID_L2CAP >> 8),
(uint8_t)(UUID_L2CAP),
//Parameter #0 for Protocol #0: PSM = AVCTP
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(PSM_AVCTP >> 8),
(uint8_t)PSM_AVCTP,
//Protocol #1: AVCTP
SDP_DATA_ELEM_SEQ_HDR,
0x06, //Element length: 5 bytes
SDP_UUID16_HDR,
(uint8_t)(UUID_AVCTP >> 8),
(uint8_t)(UUID_AVCTP),
//Parameter #0 for Protocol #1: 0x0104 (v1.4)
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(0x0104 >> 8),
(uint8_t)(0x0104),
//Attribute SDP_ATTR_PROFILE_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROFILE_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROFILE_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x08, //Attribute length: 8 bytes
//Profile #0: A/V Remote Control
SDP_DATA_ELEM_SEQ_HDR,
0x06, //Element length: 6 bytes
SDP_UUID16_HDR,
(uint8_t)(UUID_AV_REMOTE_CONTROL >> 8),
(uint8_t)(UUID_AV_REMOTE_CONTROL),
//Parameter #0 for Profile #0: 0x0106 (v1.6)
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(0x0106 >> 8),
(uint8_t)(0x0106),
//Attribute SDP_ATTR_SUPPORTED_FEATURES
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_SUPPORTED_FEATURES) >> 8),
(uint8_t)(SDP_ATTR_SUPPORTED_FEATURES),
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(0x0002 >> 8), //Category 2 Amplifier
(uint8_t)(0x0002),
//Attribute SDP_ATTR_BROWSE_GROUP_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_BROWSE_GROUP_LIST >> 8),
(uint8_t)SDP_ATTR_BROWSE_GROUP_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x03,
SDP_UUID16_HDR,
(uint8_t)(UUID_PUBLIC_BROWSE_GROUP >> 8),
(uint8_t)UUID_PUBLIC_BROWSE_GROUP
/*
//Attribute SDP_ATTR_LANG_BASE_ATTR_ID_LIST...it is used for SDP_ATTR_SRV_NAME
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_LANG_BASE_ATTR_ID_LIST >> 8),
(uint8_t)SDP_ATTR_LANG_BASE_ATTR_ID_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x09,
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_LANG_ENGLISH >> 8),
(uint8_t)SDP_LANG_ENGLISH,
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_CHARACTER_UTF8 >> 8),
(uint8_t)SDP_CHARACTER_UTF8,
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_BASE_LANG_OFFSET >> 8),
(uint8_t)SDP_BASE_LANG_OFFSET,
//Attribute SDP_ATTR_PROVIDER_NAME
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_PROVIDER_NAME + SDP_BASE_LANG_OFFSET) >> 8),
(uint8_t)(SDP_ATTR_PROVIDER_NAME + SDP_BASE_LANG_OFFSET),
SDP_STRING_HDR,
0x07, //Attribute length: 7 bytes
0x52, 0x65, 0x61, 0x6C, 0x54, 0x65, 0x6B, //RealTek
//Attribute SDP_ATTR_SRV_NAME
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET) >> 8),
(uint8_t)(SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET),
SDP_STRING_HDR,
0x08, //Attribute length: 8 bytes
0x41, 0x56, 0x52, 0x43, 0x50, 0x20, 0x54, 0x47, //AVRCP TG
*/
};
The bits for supported features are set to 1. Others are set to 0.
Bit |
Description |
---|---|
0 |
Category 1 Player / Recorder |
1 |
Category 2 Monitor/Amplifier |
2 |
Category 3 Tuner |
3 |
Category 4 Menu |
4-5 |
RFA |
6 |
Supports Browsing |
7 |
Supports Cover Art GetImageProperties Feature |
8 |
Supports Cover Art GetImage Feature |
9 |
Supports Cover Art GetLinkedThumbnail Feature |
10-15 |
RFA |
Feature Set
The functions provided by AVRCP API are as below:
Connecting and Disconnecting: Including functions to connect/disconnect AVRCP.
AVRCP Control APIs: Including functions to play/pause music, etc.
AVRCP Browsing APIs: Including functions to retrieve information about the available browsable items.
Cover Art APIs: Including functions to retrieve images associated with the media on the TG.
Provided APIs
This figure shows the relationship between applications, AVRCP, and Bluetooth host. Above the horizon line is developed by the applications. Below the horizon line is developed by Realtek.

AVRCP Struct
The table below shows a simple description of AVRCP APIs. AVRCP related APIs are provided in the sdk\inc\framework\bt\bt_avrcp.h
.
Header File |
Description |
API Reference |
---|---|---|
|
ContConnect AVRCP, send and receive data etc.ents |
Functions
AVRCP Init
AVRCP initialization procedure involves profile initialization and supported features setting.

AVRCP Feature
Note
If Absolute Volume is supported, Category 2 in Controller shall be checked for A2DP source device. And for A2DP sink device, Category 2 in Target shall be checked.
void app_avrcp_init(void)
{
if (app_cfg_const.supported_profile_mask & AVRCP_PROFILE_MASK)
{
uint8_t ct_features;
uint8_t tg_features;
ct_features = (app_cfg_const.avrcp_features_ct.features_value & 0x0F);
tg_features = (app_cfg_const.avrcp_features_tg.features_value & 0x0F);
if (ct_features != 0)
{
bt_sdp_record_add((void *)avrcp_ct_sdp_record);
}
if (tg_features != 0)
{
bt_sdp_record_add((void *)avrcp_tg_sdp_record);
}
bt_avrcp_init(app_cfg_const.avrcp_link_number);
bt_avrcp_supported_features_set(ct_features, tg_features);
bt_mgr_cback_register(app_avrcp_bt_cback);
}
}
AVRCP Control
AVRCP Control Connect
Note
If both devices initiate a connection at the same time, both channels shall be closed and each device shall wait a random time (not more than 1s and not less than 100ms) and then try to initiate the connection again.
static void app_avrcp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_AVRCP_CONN_IND:
{
p_link = app_find_br_link(param->avrcp_conn_ind.bd_addr);
if (p_link != NULL)
{
bt_avrcp_connect_cfm(p_link->bd_addr, true);
}
}
break;
case BT_EVENT_AVRCP_CONN_CMPL:
break;
case BT_EVENT_AVRCP_CONN_FAIL:
break;
}
}
AVRCP Control Key
void app_avrcp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_AVRCP_PLAY_STATUS_RSP:
case BT_EVENT_AVRCP_PLAY_STATUS_CHANGED:
{
if (app_db.avrcp_play_status == param->avrcp_play_status_changed.play_status)
{
break;
}
app_db.avrcp_play_status = param->avrcp_play_status_changed.play_status;
//job to do
}
break;
}
}
Note
BT_EVENT_AVRCP_PLAY_STATUS_RSP
is reported after AVRCP play/pause CMD is accepted by phone.BT_EVENT_AVRCP_PLAY_STATUS_CHANGED
is reported only when receiving status changed event from phone.The play_status in
BT_EVENT_AVRCP_PLAY_STATUS_CHANGED
is the real play status of phone, but play_status inBT_EVENT_AVRCP_PLAY_STATUS_RSP
is related to the CMD sent to phone.
For example, if AVRCP pause is sent, the play_status in BT_EVENT_AVRCP_PLAY_STATUS_RSP
is paused.

Avrcp Play Status
AVRCP Control Volume
void app_avrcp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_AVRCP_REG_VOLUME_CHANGED:
{
p_link = app_find_br_link(param->avrcp_reg_volume_changed.bd_addr);
if (p_link != NULL)
{
bt_avrcp_volume_change_register_rsp(p_link->bd_addr, vol);
}
}
break;
}
}
void app_mmi_handle_action(uint8_t action)
{
switch (action)
{
case MMI_DEV_SPK_VOL_UP:
{
...
bt_avrcp_volume_change_req(app_db.br_link[active_idx].bd_addr, level);
}
break;
}
}
Volume adjustment flow is introduced below when absolute volume is supported by both sides.

AVRCP Volume Adjust Src

AVRCP Volume Adjust Snk
AVRCP Control Miscellaneous
bt_avrcp_browsing_item_attrs_get()
is not supported.void app_avrcp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_AVRCP_TRACK_CHANGED:
{
uint8_t attr_list[7] = {1, 2, 3, 4, 5, 6, 7};
uint8_t num_of_attr = 7;
p_link = app_find_br_link(param->avrcp_track_changed.bd_addr);
if (p_link != NULL)
{
bt_avrcp_get_element_attr_req(p_link->bd_addr, num_of_attr, attr_list);
}
}
break;
case BT_EVENT_AVRCP_ELEM_ATTR:
{
int i = 0;
for(i = 0; i < param->avrcp_elem_attr.num_of_attr; i++)
{
//deal with param->avrcp_elem_attr.attr[i]
switch(param->avrcp_elem_attr.attr[i].attribute_id)
{
case BT_AVRCP_ELEM_ATTR_TITLE:
{
...
}
break;
case BT_AVRCP_ELEM_ATTR_ARTIST:
break;
...
}
}
}
break;
}
}
void app_avrcp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_AVRCP_GET_PLAY_STATUS_RSP:
{
uint8_t play_status = param->avrcp_get_play_status_rsp.play_status;
uint32_t song_length = param->avrcp_get_play_status_rsp.length_ms;
uint32_t song_pos = param->avrcp_get_play_status_rsp.position_ms;
}
break;
}
}
AVRCP Browsing
This section describes the AVRCP browsing API definition. These APIs enable the CT to navigate the media on the target device, and perform operations on a specific media item. Browsing commands are used to retrieve information about the available browsable items.
AVRCP Browsing Connect
void app_test_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_AVRCP_BROWSING_CONN_IND:
{
p_link = app_find_br_link(param->avrcp_browsing_conn_ind.bd_addr);
if (p_link != NULL)
{
bt_avrcp_browsing_connect_cfm(p_link->bd_addr, true);
}
}
break;
case BT_EVENT_AVRCP_BROWSING_CONN_CMPL:
break;
}
}
AVRCP Browsing Application Setting
avrcp.h
.avrcp.h
.void app_test_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
uint8_t i = 0;
switch (event_type)
{
case BT_EVENT_AVRCP_APP_SETTING_ATTRS_LIST_RSP:
{
if (param->avrcp_app_setting_attrs_list_rsp.state == 0)
{
for(i = 0; i < param->avrcp_app_setting_attrs_list_rsp.num_of_attr; i++)
{
APP_PRINT_INFO2("BT_EVENT_AVRCP_APP_SETTING_ATTRS_LIST_RSP: index %d, id %d",
i, param->avrcp_app_setting_attrs_list_rsp.p_attr_id[i]);
}
}
}
break;
case BT_EVENT_AVRCP_APP_SETTING_VALUES_LIST_RSP:
{
if (param->avrcp_app_setting_values_list_rsp.state == 0)
{
for(i = 0; i < param->avrcp_app_setting_values_list_rsp.num_of_value; i++)
{
APP_PRINT_INFO3("BT_EVENT_AVRCP_APP_SETTING_VALUES_LIST_RSP: index %d, value %d",
i, param->avrcp_app_setting_values_list_rsp.p_value[i]);
}
}
}
break;
case BT_EVENT_AVRCP_APP_SETTING_GET_RSP:
{
if (param->avrcp_app_setting_get_rsp.state == 0)
{
for(i = 0; i < param->avrcp_app_setting_get_rsp.num_of_attr; i++)
{
APP_PRINT_INFO3("BT_EVENT_AVRCP_APP_SETTING_GET_RSP: index %d, attr %d, value %d",
i, param->avrcp_app_setting_get_rsp.p_app_setting[i].attr,
param->avrcp_app_setting_get_rsp.p_app_setting[i].value);
}
}
}
break;
}
}
{
uint8_t attr_list[4];
attr_list[0] = APP_SETTING_ATTR_EQUALIZER;
attr_list[1] = EQUALIZER_STATUS_OFF;
attr_list[2] = APP_SETTING_ATTR_REPEAT_MODE;
attr_list[3] = REPEAT_MODE_STATUS_SINGLE;
bt_avrcp_app_setting_value_set(bd_addr, 2, attr_list);
}
AVRCP Browsing Search
The search procedure is shown below:

AVRCP Search Flow
void app_test_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_AVRCP_SEARCH_RSP:
{
uint8_t num_of_items;
num_of_items = param->avrcp_search_rsp.num_of_items;
bt_avrcp_browsing_folder_items_get(param->avrcp_search_rsp.bd_addr, 2, 0, num_of_items-1, 0, NULL);
}
break;
case BT_EVENT_AVRCP_FOLDER_ITEMS_GET_RSP:
{
uint8_t item_type;
if (param->avrcp_folder_items_get_rsp.num_of_items > 0)
{
item_type = param->avrcp_folder_items_get_rsp.item_type;
if (item_type == 0x1)
{
//media player item, refer to T_BT_AVRCP_MEDIA_PLAYER_ITEM
//param->avrcp_folder_items_get_rsp.u.p_media_player_items
}
else if (item_type == 0x2)
{
//folder item, refer to T_BT_AVRCP_FOLDER_ITEM
//param->avrcp_folder_items_get_rsp.u.p_folder_items
}
else if (item_type == 0x3)
{
//media element item, refer to T_BT_AVRCP_MEDIA_ELEMENT_ITEM
//param->avrcp_folder_items_get_rsp.u.p_media_element_items
}
}
}
break;
case BT_EVENT_AVRCP_ITEM_ATTR_GET_RSP:
{
T_BT_AVRCP_ITEM_ATTR *attr;
uint8_t i;
for (i = 0; i < param->avrcp_item_attr_get_rsp.num_of_attr; i++)
{
attr = event->p_attr + i;
switch(attr->attribute_id)
{
case BT_AVRCP_ELEM_ATTR_TITLE:
{
...
}
break;
...
}
}
}
break;
}
}
AVRCP Browsing Miscellaneous
Note
Some players may not support browsing of the media player tree or search results unless the Browsed Player is set to the Addressed Player. This is indicated in the player feature bitmask.
void app_avrcp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case T_BT_EVENT_PARAM_AVRCP_ADDRESSED_PLAYER_SET_RSP:
{
...
}
break;
case T_BT_EVENT_PARAM_AVRCP_BROWSED_PLAYER_SET_RSP:
{
...
}
break;
}
}
Cover Art
The CT uses the Cover Art feature to retrieve the cover art associated with the browsed or played media items, as shown below:

AVRCP Cover Art
This section describes the Cover Art API definition and how to retrieve images associated with the media on the TG. These APIs are used over an OBEX connection, as shown below:

Profile AVRCP
Cover Art Retrieve Procedure
The procedure is shown below.

Cover Art Retrieve Flow
AVRCP Cover Art Connect
void app_avrcp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_SDP_ATTR_INFO:
{
T_BT_SDP_ATTR_INFO *sdp_info = ¶m->sdp_attr_info.info;
if (sdp_info->srv_class_uuid_data.uuid_16 == UUID_AV_REMOTE_CONTROL_TARGET)
{
bt_avrcp_cover_art_connect_req(bd_addr, sdp_info->l2c_psm);
}
}
break;
}
}
Note
There is no restriction when this API shall be called. However, as BIP image handles are valid only during the lifetime of a Cover Art connection, an OBEX level connection shall exist before the BIP image handle can be successfully retrieved and the handles retrieved can only be used during that Cover Art connection.
AVRCP Cover Art Retrieve
uint8_t image_handle[16];
void app_avrcp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
switch (event_type)
{
case BT_EVENT_AVRCP_TRACK_CHANGED:
{
bt_avrcp_get_element_attr_req(param->avrcp_track_changed.bd_addr, 0, NULL);
}
break;
case BT_EVENT_AVRCP_ELEM_ATTR:
{
uint8_t num_of_attr = param->avrcp_elem_attr.num_of_attr;
uint8_t i;
for (i = 0; i < num_of_attr; i++)
{
if(param->avrcp_elem_attr.attr[i].attribute_id == BT_AVRCP_ELEM_ATTR_DEFAULT_COVER_ART)
{
utf8_to_unicode(param->avrcp_elem_attr.attr[i].p_buf, 7, image_handle);
image_handle[14] = '\0';
image_handle[15] = '\0';
bt_avrcp_cover_art_get(param->avrcp_elem_attr.bd_addr, image_handle);
break;
}
}
}
break;
case BT_EVENT_AVRCP_COVER_ART_DATA_IND:
{
if (!param->avrcp_cover_art_data_ind.data_end)
{
bt_avrcp_cover_art_get(param->avrcp_cover_art_data_ind.bd_addr, image_handle);
}
//deal with data
}
break;
}
}
Image Handle can be retrieved by bt_avrcp_get_element_attr_req()
or bt_avrcp_browsing_item_attrs_get()
.
Note
The image handle retrieved is a 7-character UTF-8 string and should be converted to a NULL-terminated UTF-16 string.
AVRCP Cover Art Disconnect
When the OBEX level connection is closed, the BIP image handles retrieved during that OBEX connection will no longer be valid.
Sample Projects
SDK provides a corresponding demo application for developers’ reference in development. The BR/EDR Audio gives a simple example on how to use AVRCP.