mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(bt/bluedroid): Support AVRCP Cover Art feature
This commit is contained in:
parent
d7298a71c3
commit
cb0d073551
@ -1,4 +1,4 @@
|
||||
[codespell]
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn,registr
|
||||
write-changes = true
|
||||
|
@ -156,6 +156,8 @@ if(CONFIG_BT_ENABLED)
|
||||
host/bluedroid/stack/avdt/include
|
||||
host/bluedroid/stack/a2dp/include
|
||||
host/bluedroid/stack/rfcomm/include
|
||||
host/bluedroid/stack/obex/include
|
||||
host/bluedroid/stack/goep/include
|
||||
host/bluedroid/stack/include
|
||||
host/bluedroid/common/include
|
||||
host/bluedroid/config/include)
|
||||
@ -183,6 +185,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/bta/av/bta_av_aact.c"
|
||||
"host/bluedroid/bta/av/bta_av_act.c"
|
||||
"host/bluedroid/bta/av/bta_av_api.c"
|
||||
"host/bluedroid/bta/av/bta_av_ca_act.c"
|
||||
"host/bluedroid/bta/av/bta_av_ca_sm.c"
|
||||
"host/bluedroid/bta/av/bta_av_cfg.c"
|
||||
"host/bluedroid/bta/av/bta_av_ci.c"
|
||||
"host/bluedroid/bta/av/bta_av_main.c"
|
||||
@ -378,6 +382,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/stack/gatt/gatt_sr.c"
|
||||
"host/bluedroid/stack/gatt/gatt_sr_hash.c"
|
||||
"host/bluedroid/stack/gatt/gatt_utils.c"
|
||||
"host/bluedroid/stack/goep/goepc_api.c"
|
||||
"host/bluedroid/stack/goep/goepc_main.c"
|
||||
"host/bluedroid/stack/hcic/hciblecmds.c"
|
||||
"host/bluedroid/stack/hcic/hcicmds.c"
|
||||
"host/bluedroid/stack/l2cap/l2c_api.c"
|
||||
@ -389,6 +395,9 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/stack/l2cap/l2c_ucd.c"
|
||||
"host/bluedroid/stack/l2cap/l2c_utils.c"
|
||||
"host/bluedroid/stack/l2cap/l2cap_client.c"
|
||||
"host/bluedroid/stack/obex/obex_api.c"
|
||||
"host/bluedroid/stack/obex/obex_main.c"
|
||||
"host/bluedroid/stack/obex/obex_tl_l2cap.c"
|
||||
"host/bluedroid/stack/rfcomm/port_api.c"
|
||||
"host/bluedroid/stack/rfcomm/port_rfc.c"
|
||||
"host/bluedroid/stack/rfcomm/port_utils.c"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -232,6 +232,145 @@ esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_avrc_ct_cover_art_connect(uint16_t mtu)
|
||||
{
|
||||
if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) ||
|
||||
(!btc_avrc_ct_connected_p())) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!btc_avrc_ct_check_cover_art_support()) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (mtu > ESP_AVRC_CA_MTU_MAX || mtu < ESP_AVRC_CA_MTU_MIN) {
|
||||
mtu = ESP_AVRC_CA_MTU_MAX;
|
||||
}
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_AVRC_CT;
|
||||
msg.act = BTC_AVRC_CT_API_COVER_ART_CONNECT_EVT;
|
||||
|
||||
btc_avrc_args_t arg;
|
||||
memset(&arg, 0, sizeof(btc_avrc_args_t));
|
||||
arg.ca_conn.mtu = mtu;
|
||||
|
||||
/* Switch to BTC context */
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_avrc_ct_cover_art_disconnect(void)
|
||||
{
|
||||
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!btc_avrc_ct_check_cover_art_support()) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_AVRC_CT;
|
||||
msg.act = BTC_AVRC_CT_API_COVER_ART_DISCONNECT_EVT;
|
||||
|
||||
/* Switch to BTC context */
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_avrc_ct_cover_art_get_image_properties(uint8_t *image_handle)
|
||||
{
|
||||
if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) ||
|
||||
(!btc_avrc_ct_connected_p())) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!btc_avrc_ct_check_cover_art_support()) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (image_handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_AVRC_CT;
|
||||
msg.act = BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_PROPERTIES_EVT;
|
||||
|
||||
btc_avrc_args_t arg;
|
||||
memset(&arg, 0, sizeof(btc_avrc_args_t));
|
||||
memcpy(arg.ca_get_img_prop.image_handle, image_handle, ESP_AVRC_CA_IMAGE_HANDLE_LEN);
|
||||
|
||||
/* Switch to BTC context */
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_avrc_ct_cover_art_get_image(uint8_t *image_handle, uint8_t *image_descriptor, uint16_t image_descriptor_len)
|
||||
{
|
||||
if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) ||
|
||||
(!btc_avrc_ct_connected_p())) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!btc_avrc_ct_check_cover_art_support()) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (image_handle == NULL || image_descriptor == NULL || image_descriptor_len == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_AVRC_CT;
|
||||
msg.act = BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT;
|
||||
|
||||
btc_avrc_args_t arg;
|
||||
memset(&arg, 0, sizeof(btc_avrc_args_t));
|
||||
|
||||
memcpy(arg.ca_get_img.image_handle, image_handle, ESP_AVRC_CA_IMAGE_HANDLE_LEN);
|
||||
arg.ca_get_img.image_descriptor_len = image_descriptor_len;
|
||||
arg.ca_get_img.image_descriptor = image_descriptor;
|
||||
|
||||
/* Switch to BTC context */
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), btc_avrc_arg_deep_copy, btc_avrc_arg_deep_free);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_avrc_ct_cover_art_get_linked_thumbnail(uint8_t *image_handle)
|
||||
{
|
||||
if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) ||
|
||||
(!btc_avrc_ct_connected_p())) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (!btc_avrc_ct_check_cover_art_support()) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (image_handle == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_AVRC_CT;
|
||||
msg.act = BTC_AVRC_CT_API_COVER_ART_GET_LINKED_THUMBNAIL_EVT;
|
||||
|
||||
btc_avrc_args_t arg;
|
||||
memset(&arg, 0, sizeof(btc_avrc_args_t));
|
||||
memcpy(arg.ca_get_lk_thn.image_handle, image_handle, ESP_AVRC_CA_IMAGE_HANDLE_LEN);
|
||||
|
||||
/* Switch to BTC context */
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
/** following is the API of AVRCP target role **/
|
||||
/*********************************************************************************************/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -18,6 +18,10 @@ extern "C" {
|
||||
|
||||
#define ESP_AVRC_TRANS_LABEL_MAX 15 /*!< max transaction label */
|
||||
|
||||
#define ESP_AVRC_CA_IMAGE_HANDLE_LEN 7 /* The image handle length is fixed to 7, specified by Basic Image Profile */
|
||||
#define ESP_AVRC_CA_MTU_MIN 255 /* Minimal MTU can be used in Cover Art OBEX connection */
|
||||
#define ESP_AVRC_CA_MTU_MAX 1691 /* Maximum MTU can be used in Cover Art OBEX connection */
|
||||
|
||||
/// AVRC feature bit mask
|
||||
typedef enum {
|
||||
ESP_AVRC_FEAT_RCTG = 0x0001, /*!< remote control target */
|
||||
@ -30,14 +34,18 @@ typedef enum {
|
||||
|
||||
/// AVRC supported features flag retrieved in SDP record
|
||||
typedef enum {
|
||||
/* CT and TG common features flag */
|
||||
ESP_AVRC_FEAT_FLAG_CAT1 = 0x0001, /*!< category 1 */
|
||||
ESP_AVRC_FEAT_FLAG_CAT2 = 0x0002, /*!< category 2 */
|
||||
ESP_AVRC_FEAT_FLAG_CAT3 = 0x0004, /*!< category 3 */
|
||||
ESP_AVRC_FEAT_FLAG_CAT4 = 0x0008, /*!< category 4 */
|
||||
ESP_AVRC_FEAT_FLAG_BROWSING = 0x0040, /*!< browsing */
|
||||
ESP_AVRC_FEAT_FLAG_COVER_ART_GET_IMAGE_PROP = 0x0080, /*!< Cover Art GetImageProperties */
|
||||
ESP_AVRC_FEAT_FLAG_COVER_ART_GET_IMAGE = 0x0100, /*!< Cover Art GetImage */
|
||||
ESP_AVRC_FEAT_FLAG_COVER_ART_GET_LINKED_THUMBNAIL = 0x0200, /*!< Cover Art GetLinkedThumbnail */
|
||||
/* CT only features flag */
|
||||
ESP_AVRC_FEAT_FLAG_COVER_ART_GET_IMAGE_PROP = 0x0080, /*!< CT support Cover Art GetImageProperties */
|
||||
ESP_AVRC_FEAT_FLAG_COVER_ART_GET_IMAGE = 0x0100, /*!< CT support Cover Art GetImage */
|
||||
ESP_AVRC_FEAT_FLAG_COVER_ART_GET_LINKED_THUMBNAIL = 0x0200, /*!< CT support Cover Art GetLinkedThumbnail */
|
||||
/* TG only features flag */
|
||||
ESP_AVRC_FEAT_FLAG_TG_COVER_ART = 0x0100, /*!< TG support Cover Art */
|
||||
} esp_avrc_feature_flag_t;
|
||||
|
||||
/// AVRC passthrough command code
|
||||
@ -135,6 +143,8 @@ typedef enum {
|
||||
ESP_AVRC_CT_REMOTE_FEATURES_EVT = 5, /*!< feature of remote device indication event */
|
||||
ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT = 6, /*!< supported notification events capability of peer device */
|
||||
ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT = 7, /*!< set absolute volume response event */
|
||||
ESP_AVRC_CT_COVER_ART_STATE_EVT = 8, /*!< cover art client connection state changed event */
|
||||
ESP_AVRC_CT_COVER_ART_DATA_EVT = 9, /*!< cover art client data event */
|
||||
} esp_avrc_ct_cb_event_t;
|
||||
|
||||
/// AVRC Target callback events
|
||||
@ -155,7 +165,8 @@ typedef enum {
|
||||
ESP_AVRC_MD_ATTR_TRACK_NUM = 0x8, /*!< track position on the album */
|
||||
ESP_AVRC_MD_ATTR_NUM_TRACKS = 0x10, /*!< number of tracks on the album */
|
||||
ESP_AVRC_MD_ATTR_GENRE = 0x20, /*!< track genre */
|
||||
ESP_AVRC_MD_ATTR_PLAYING_TIME = 0x40 /*!< total album playing time in miliseconds */
|
||||
ESP_AVRC_MD_ATTR_PLAYING_TIME = 0x40, /*!< total album playing time in milliseconds */
|
||||
ESP_AVRC_MD_ATTR_COVER_ART = 0x80 /*!< cover art image handle */
|
||||
} esp_avrc_md_attr_mask_t;
|
||||
|
||||
/// AVRC event notification ids
|
||||
@ -261,6 +272,12 @@ typedef enum {
|
||||
ESP_AVRC_PLAYBACK_ERROR = 0xFF, /*!< error */
|
||||
} esp_avrc_playback_stat_t;
|
||||
|
||||
/// AVRC Cover Art connection error code
|
||||
typedef enum {
|
||||
ESP_AVRC_COVER_ART_DISCONNECTED, /*!< Cover Art connection disconnected or connection failed */
|
||||
ESP_AVRC_COVER_ART_CONNECTED, /*!< Cover Art connection established */
|
||||
} esp_avrc_cover_art_conn_state_t;
|
||||
|
||||
/// AVRCP notification parameters
|
||||
typedef union
|
||||
{
|
||||
@ -337,6 +354,24 @@ typedef union {
|
||||
struct avrc_ct_set_volume_rsp_param {
|
||||
uint8_t volume; /*!< the volume which has actually been set, range is 0 to 0x7f, means 0% to 100% */
|
||||
} set_volume_rsp; /*!< set absolute volume response event */
|
||||
|
||||
/**
|
||||
* @brief ESP_AVRC_CT_COVER_ART_STATE_EVT
|
||||
*/
|
||||
struct avrc_ct_cover_art_state_param {
|
||||
esp_avrc_cover_art_conn_state_t state; /*!< indicate the Cover Art connection status */
|
||||
esp_bt_status_t reason; /*!< the disconnect reason of Cover Art connection */
|
||||
} cover_art_state; /*!< AVRC Cover Art connection state change event */
|
||||
|
||||
/**
|
||||
* @brief ESP_AVRC_CT_COVER_ART_DATA_EVT
|
||||
*/
|
||||
struct avrc_ct_cover_art_data_param {
|
||||
esp_bt_status_t status; /*!< indicate whether the get operation is success, p_data is valid only when status is ESP_BT_STATUS_SUCCESS */
|
||||
bool final; /*!< indicate whether this data event is the final one, true if we have received the entire object */
|
||||
uint16_t data_len; /*!< the data length of this data event, in bytes */
|
||||
uint8_t *p_data; /*!< pointer to data, should copy to other buff before event callback return */
|
||||
} cover_art_data; /*!< AVRC Cover Art data event */
|
||||
} esp_avrc_ct_cb_param_t;
|
||||
|
||||
/// AVRC target callback parameters
|
||||
@ -656,11 +691,11 @@ bool esp_avrc_psth_bit_mask_operation(esp_avrc_bit_mask_op_t op, esp_avrc_psth_b
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Get the requested event notification capabilies on local AVRC target. The capability is returned
|
||||
* @brief Get the requested event notification capabilities on local AVRC target. The capability is returned
|
||||
* in a bit mask representation in evt_set. This function should be called after esp_avrc_tg_init().
|
||||
*
|
||||
* For capability type "ESP_AVRC_RN_CAP_ALLOWED_EVT, the retrieved event set is constant and
|
||||
* it covers all of the notifcation events that can possibly be supported with current
|
||||
* it covers all of the notification events that can possibly be supported with current
|
||||
* implementation.
|
||||
*
|
||||
* For capability type ESP_AVRC_RN_CAP_SUPPORTED_EVT, the event set covers the notification
|
||||
@ -729,6 +764,87 @@ bool esp_avrc_rn_evt_bit_mask_operation(esp_avrc_bit_mask_op_t op, esp_avrc_rn_e
|
||||
esp_err_t esp_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_rsp_t rsp,
|
||||
esp_avrc_rn_param_t *param);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Start the process to establish OBEX connection used in Cover Art Client. Once the operation done,
|
||||
* ESP_AVRC_CT_COVER_ART_STATE_EVT will come, operation result can be found in event param.
|
||||
*
|
||||
* @param[in] mtu: MTU used in lower level connection, should not smaller than ESP_AVRC_CA_MTU_MIN or larger than
|
||||
* ESP_AVRC_CA_MTU_MAX, if value is not valid, will be reset to ESP_AVRC_CA_MTU_MAX. This can limit
|
||||
* the max data length in cover_art_data event.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized
|
||||
* - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_avrc_ct_cover_art_connect(uint16_t mtu);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Start the process to release the OBEX connection used in Cover Art Client.Once the operation done,
|
||||
* ESP_AVRC_CT_COVER_ART_STATE_EVT will come, operation result can be found in event param.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized
|
||||
* - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_avrc_ct_cover_art_disconnect(void);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Start the process to get image properties from Cover Art server.
|
||||
*
|
||||
* @param[in] image_handle: pointer to image handle with a length of ESP_AVRC_CA_IMAGE_HANDLE_LEN bytes, can be freed
|
||||
* after this function return
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized
|
||||
* - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_avrc_ct_cover_art_get_image_properties(uint8_t *image_handle);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Start the process to get image from Cover Art server.
|
||||
*
|
||||
* @param[in] image_handle: pointer to image handle with a length of ESP_AVRC_CA_IMAGE_HANDLE_LEN bytes, can be freed
|
||||
* after this function return
|
||||
*
|
||||
* @param[in] image_descriptor: pointer to image descriptor, will be cache internally by bluetooth stack, can be freed
|
||||
* once this api return
|
||||
*
|
||||
* @param[in] image_descriptor_len: the length of image descriptor
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized
|
||||
* - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_avrc_ct_cover_art_get_image(uint8_t *image_handle, uint8_t *image_descriptor, uint16_t image_descriptor_len);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Start the process to get linked thumbnail from Cover Art server.
|
||||
*
|
||||
* @param[in] image_handle: pointer to image handle with a length of ESP_AVRC_CA_IMAGE_HANDLE_LEN bytes, can be freed
|
||||
* after this function return
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized
|
||||
* - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_avrc_ct_cover_art_get_linked_thumbnail(uint8_t *image_handle);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "stack/l2c_api.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/list.h"
|
||||
#include "stack/goep_common.h"
|
||||
#include "stack/goepc_api.h"
|
||||
#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
|
||||
#include "bta/bta_ar_api.h"
|
||||
#endif
|
||||
@ -98,6 +100,9 @@ void bta_av_del_rc(tBTA_AV_RCB *p_rcb)
|
||||
|
||||
p_scb = NULL;
|
||||
if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE) {
|
||||
/* reset cover art state */
|
||||
bta_av_ca_reset(p_rcb);
|
||||
|
||||
if (p_rcb->shdl) {
|
||||
/* Validate array index*/
|
||||
if ((p_rcb->shdl - 1) < BTA_AV_NUM_STRS) {
|
||||
@ -1143,7 +1148,7 @@ void bta_av_conn_chg(tBTA_AV_DATA *p_data)
|
||||
p_data->conn_chg.peer_addr[5]);
|
||||
if (p_lcb_rc->conn_msk && bdcmp(p_lcb_rc->addr, p_data->conn_chg.peer_addr) == 0) {
|
||||
/* AVRCP is already connected.
|
||||
* need to update the association betwen SCB and RCB */
|
||||
* need to update the association between SCB and RCB */
|
||||
p_lcb_rc->conn_msk = 0; /* indicate RC ONLY is not connected */
|
||||
p_lcb_rc->lidx = 0;
|
||||
p_scb->rc_handle = p_cb->rc_acp_handle;
|
||||
@ -1484,6 +1489,37 @@ static void bta_av_acp_sig_timer_cback (TIMER_LIST_ENT *p_tle)
|
||||
}
|
||||
}
|
||||
|
||||
UINT16 bta_av_extra_tg_cover_art_l2cap_psm(void)
|
||||
{
|
||||
tBTA_AV_CB *p_cb = &bta_av_cb;
|
||||
tSDP_DISC_REC *p_rec = NULL;
|
||||
tSDP_DISC_ATTR *p_add_prot_desc, *p_prot_desc;
|
||||
tSDP_PROTOCOL_ELEM elem_l2cap, elem_obex;
|
||||
UINT16 l2cap_psm = 0;
|
||||
|
||||
while (TRUE) {
|
||||
/* get next record; if none found, we're done */
|
||||
if ((p_rec = SDP_FindServiceInDb(p_cb->p_disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET, p_rec)) == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
p_add_prot_desc = SDP_FindAttributeInRec(p_rec, ATTR_ID_ADDITION_PROTO_DESC_LISTS);
|
||||
if ((p_add_prot_desc != NULL) && (SDP_DISC_ATTR_TYPE(p_add_prot_desc->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) {
|
||||
/* Walk through all protocol descriptor list */
|
||||
for (p_prot_desc = p_add_prot_desc->attr_value.v.p_sub_attr; p_prot_desc; p_prot_desc = p_prot_desc->p_next_attr) {
|
||||
if(SDP_FindProtocolListElem(p_prot_desc, UUID_PROTOCOL_L2CAP, &elem_l2cap)
|
||||
&& SDP_FindProtocolListElem(p_prot_desc, UUID_PROTOCOL_OBEX, &elem_obex))
|
||||
{
|
||||
/* found */
|
||||
l2cap_psm = elem_l2cap.params[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return l2cap_psm;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function bta_av_check_peer_rc_features
|
||||
@ -1539,6 +1575,10 @@ tBTA_AV_FEAT bta_av_check_peer_rc_features (UINT16 service_uuid, UINT16 *rc_feat
|
||||
if (categories & AVRC_SUPF_CT_BROWSE) {
|
||||
peer_features |= (BTA_AV_FEAT_BROWSE);
|
||||
}
|
||||
if ((service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET) && (categories & AVRC_SUPF_TG_COVER_ART)) {
|
||||
/* remote target support cover art */
|
||||
peer_features |= BTA_AV_FEAT_COVER_ART;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1573,6 +1613,7 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
|
||||
tBTA_AV_FEAT peer_features; /* peer features mask */
|
||||
UINT16 peer_ct_features; /* peer features mask as controller */
|
||||
UINT16 peer_tg_features; /* peer features mask as target */
|
||||
UINT16 obex_l2cap_psm = 0; /* target obex l2cap psm */
|
||||
UNUSED(p_data);
|
||||
|
||||
APPL_TRACE_DEBUG("bta_av_rc_disc_done disc:x%x", p_cb->disc);
|
||||
@ -1601,6 +1642,10 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
|
||||
peer_features = bta_av_check_peer_rc_features (UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_ct_features);
|
||||
peer_features |= bta_av_check_peer_rc_features (UUID_SERVCLASS_AV_REM_CTRL_TARGET, &peer_tg_features);
|
||||
|
||||
if (peer_features & BTA_AV_FEAT_COVER_ART) {
|
||||
obex_l2cap_psm = bta_av_extra_tg_cover_art_l2cap_psm();
|
||||
}
|
||||
|
||||
p_cb->disc = 0;
|
||||
utl_freebuf((void **) &p_cb->p_disc_db);
|
||||
|
||||
@ -1618,6 +1663,7 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
|
||||
p_cb->rcb[rc_handle].peer_features = peer_features;
|
||||
p_cb->rcb[rc_handle].peer_ct_features = peer_ct_features;
|
||||
p_cb->rcb[rc_handle].peer_tg_features = peer_tg_features;
|
||||
p_cb->rcb[rc_handle].cover_art_l2cap_psm = obex_l2cap_psm;
|
||||
}
|
||||
#if (BT_USE_TRACES == TRUE || BT_TRACE_APPL == TRUE)
|
||||
else {
|
||||
@ -1636,6 +1682,7 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
|
||||
}
|
||||
} else {
|
||||
p_cb->rcb[rc_handle].peer_features = peer_features;
|
||||
p_cb->rcb[rc_handle].cover_art_l2cap_psm = obex_l2cap_psm;
|
||||
rc_feat.rc_handle = rc_handle;
|
||||
rc_feat.peer_features = peer_features;
|
||||
rc_feat.peer_ct_features = peer_ct_features;
|
||||
@ -1676,6 +1723,10 @@ void bta_av_rc_closed(tBTA_AV_DATA *p_data)
|
||||
p_rcb->peer_features = 0;
|
||||
p_rcb->peer_ct_features = 0;
|
||||
p_rcb->peer_tg_features = 0;
|
||||
|
||||
/* reset cover art state */
|
||||
bta_av_ca_reset(p_rcb);
|
||||
|
||||
APPL_TRACE_DEBUG(" shdl:%d, lidx:%d", p_rcb->shdl, p_rcb->lidx);
|
||||
if (p_rcb->shdl) {
|
||||
if ((p_rcb->shdl - 1) < BTA_AV_NUM_STRS) {
|
||||
@ -1748,6 +1799,7 @@ void bta_av_rc_disc(UINT8 disc)
|
||||
tAVRC_SDP_DB_PARAMS db_params;
|
||||
UINT16 attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
|
||||
ATTR_ID_BT_PROFILE_DESC_LIST,
|
||||
ATTR_ID_ADDITION_PROTO_DESC_LISTS,
|
||||
ATTR_ID_SUPPORTED_FEATURES
|
||||
};
|
||||
UINT8 hdi;
|
||||
@ -1785,7 +1837,7 @@ void bta_av_rc_disc(UINT8 disc)
|
||||
if (p_cb->p_disc_db) {
|
||||
/* set up parameters */
|
||||
db_params.db_len = BTA_AV_DISC_BUF_SIZE;
|
||||
db_params.num_attr = 3;
|
||||
db_params.num_attr = 4;
|
||||
db_params.p_db = p_cb->p_disc_db;
|
||||
db_params.p_attrs = attr_list;
|
||||
|
||||
|
@ -613,4 +613,73 @@ void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_AvCaOpen
|
||||
**
|
||||
** Description Open a Cover Art OBEX connection to peer device. This function
|
||||
** can only be used if peer device TG support Cover Art feature and
|
||||
** AV is enabled with feature BTA_AV_FEAT_METADATA.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTA_AvCaOpen(UINT8 rc_handle, UINT16 mtu)
|
||||
{
|
||||
tBTA_AV_API_CA_OPEN *p_buf;
|
||||
|
||||
if ((p_buf = (tBTA_AV_API_CA_OPEN *) osi_malloc(sizeof(tBTA_AV_API_CA_OPEN))) != NULL) {
|
||||
p_buf->hdr.event = BTA_AV_API_CA_OPEN_EVT;
|
||||
p_buf->hdr.layer_specific = rc_handle;
|
||||
p_buf->mtu = mtu;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_AvCaClose
|
||||
**
|
||||
** Description Close a Cover Art OBEX connection.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTA_AvCaClose(UINT8 rc_handle)
|
||||
{
|
||||
tBTA_AV_API_CA_CLOSE *p_buf;
|
||||
|
||||
if ((p_buf = (tBTA_AV_API_CA_CLOSE *) osi_malloc(sizeof(tBTA_AV_API_CA_CLOSE))) != NULL) {
|
||||
p_buf->hdr.event = BTA_AV_API_CA_CLOSE_EVT;
|
||||
p_buf->hdr.layer_specific = rc_handle;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_AvCaGet
|
||||
**
|
||||
** Description Start the process to get image properties, get image or get
|
||||
** linked thumbnail. This function can only be used if Cover Art
|
||||
** OBEX connection is established.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTA_AvCaGet(UINT8 rc_handle, tBTA_AV_GET_TYPE type, UINT8 *image_handle, UINT8 *image_descriptor, UINT16 image_descriptor_len)
|
||||
{
|
||||
tBTA_AV_API_CA_GET *p_buf;
|
||||
|
||||
if ((p_buf = (tBTA_AV_API_CA_GET *) osi_malloc(sizeof(tBTA_AV_API_CA_GET))) != NULL) {
|
||||
p_buf->hdr.event = BTA_AV_API_CA_GET_EVT;
|
||||
p_buf->hdr.layer_specific = rc_handle;
|
||||
p_buf->type = type;
|
||||
memcpy(p_buf->image_handle, image_handle, BTA_AV_CA_IMG_HDL_LEN);
|
||||
p_buf->image_descriptor = image_descriptor;
|
||||
p_buf->image_descriptor_len = image_descriptor_len;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BTA_AV_INCLUDED */
|
||||
|
495
components/bt/host/bluedroid/bta/av/bta_av_ca_act.c
Normal file
495
components/bt/host/bluedroid/bta/av/bta_av_ca_act.c
Normal file
@ -0,0 +1,495 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
|
||||
|
||||
#include <string.h>
|
||||
#include "bta/bta_av_api.h"
|
||||
#include "bta_av_int.h"
|
||||
#include "stack/avdt_api.h"
|
||||
#include "bta/utl.h"
|
||||
#include "stack/l2c_api.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/list.h"
|
||||
#include "stack/goep_common.h"
|
||||
#include "stack/goepc_api.h"
|
||||
#include "stack/obex_api.h"
|
||||
#include "common/bt_trace.h"
|
||||
|
||||
#define COVER_ART_HEADER_ID_IMG_HANDLE 0x30
|
||||
#define COVER_ART_HEADER_ID_IMG_DESCRIPTOR 0x71
|
||||
static const UINT8 cover_art_uuid[16] = {0x71, 0x63, 0xDD, 0x54, 0x4A, 0x7E, 0x11, 0xE2, 0xB4, 0x7C, 0x00, 0x50, 0xC2, 0x49, 0x00, 0x48};
|
||||
static const char *cover_art_img_type_img = "x-bt/img-img";
|
||||
static const char *cover_art_img_type_thm = "x-bt/img-thm";
|
||||
static const char *cover_art_img_type_prop = "x-bt/img-properties";
|
||||
|
||||
#define COVER_ART_IMG_TYPE_IMG_LEN 13
|
||||
#define COVER_ART_IMG_TYPE_THM_LEN 13
|
||||
#define COVER_ART_IMG_TYPE_PROP_LEN 20
|
||||
|
||||
|
||||
static BOOLEAN find_rcb_idx_by_goep_handle(UINT16 handle, UINT16 *out_idx)
|
||||
{
|
||||
for (UINT16 i = 0; i < BTA_AV_NUM_RCB; ++i) {
|
||||
if (bta_av_cb.rcb[i].handle != BTA_AV_RC_HANDLE_NONE && bta_av_cb.rcb[i].cover_art_goep_hdl == handle) {
|
||||
*out_idx = i;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static UINT8 get_rcb_idx(tBTA_AV_RCB *p_rcb)
|
||||
{
|
||||
return (p_rcb - &bta_av_cb.rcb[0]);
|
||||
}
|
||||
|
||||
static void get_peer_bd_addr(tBTA_AV_RCB *p_rcb, BD_ADDR out_addr)
|
||||
{
|
||||
/* check if this rcb is related to a scb */
|
||||
if (p_rcb->shdl && p_rcb->shdl <= BTA_AV_NUM_STRS) {
|
||||
tBTA_AV_SCB *p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
|
||||
bdcpy(out_addr, p_scb->peer_addr);
|
||||
}
|
||||
/* else, try get peer addr from lcb */
|
||||
else if (p_rcb->lidx && p_rcb->lidx <= BTA_AV_NUM_LINKS + 1)
|
||||
{
|
||||
bdcpy(out_addr, bta_av_cb.lcb[p_rcb->lidx-1].addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void report_data_event(BT_HDR *pkt, UINT8 *p_data, UINT16 data_len, BOOLEAN final)
|
||||
{
|
||||
tBTA_AV_CA_DATA ca_data;
|
||||
ca_data.status = BT_STATUS_SUCCESS;
|
||||
ca_data.final = final;
|
||||
ca_data.data_len = data_len;
|
||||
ca_data.p_data = p_data;
|
||||
ca_data.p_hdr = pkt;
|
||||
(*bta_av_cb.p_cback)(BTA_AV_CA_DATA_EVT, (tBTA_AV *) &ca_data);
|
||||
}
|
||||
|
||||
static void report_error_data_event(UINT16 status)
|
||||
{
|
||||
tBTA_AV_CA_DATA ca_data;
|
||||
ca_data.status = status;
|
||||
ca_data.final = TRUE;
|
||||
ca_data.data_len = 0;
|
||||
ca_data.p_data = NULL;
|
||||
ca_data.p_hdr = NULL;
|
||||
(*bta_av_cb.p_cback)(BTA_AV_CA_DATA_EVT, (tBTA_AV *) &ca_data);
|
||||
}
|
||||
|
||||
static void build_and_send_connect_req(tBTA_AV_RCB *p_rcb)
|
||||
{
|
||||
tOBEX_PARSE_INFO info = {0};
|
||||
info.opcode = OBEX_OPCODE_CONNECT;
|
||||
info.obex_version_number = 0x15;
|
||||
info.max_packet_length = p_rcb->cover_art_max_rx;
|
||||
/* before OBEX connect response, we dont know cover_art_max_tx, use BT_SMALL_BUFFER_SIZE as tx buff size */
|
||||
if (GOEPC_PrepareRequest(p_rcb->cover_art_goep_hdl, &info, BT_SMALL_BUFFER_SIZE) == GOEP_SUCCESS) {
|
||||
GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_TARGET, (UINT8 *)cover_art_uuid, 16);
|
||||
GOEPC_SendRequest(p_rcb->cover_art_goep_hdl);
|
||||
}
|
||||
}
|
||||
|
||||
static void build_and_send_disconnect_req(tBTA_AV_RCB *p_rcb)
|
||||
{
|
||||
tOBEX_PARSE_INFO info = {0};
|
||||
info.opcode = OBEX_OPCODE_DISCONNECT;
|
||||
if (GOEPC_PrepareRequest(p_rcb->cover_art_goep_hdl, &info, BT_SMALL_BUFFER_SIZE) == GOEP_SUCCESS) {
|
||||
GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_CONNECTION_ID, (UINT8 *)(&p_rcb->cover_art_cid), 4);
|
||||
GOEPC_SendRequest(p_rcb->cover_art_goep_hdl);
|
||||
}
|
||||
}
|
||||
|
||||
static void build_and_send_empty_get_req(tBTA_AV_RCB *p_rcb)
|
||||
{
|
||||
tOBEX_PARSE_INFO info = {0};
|
||||
info.opcode = OBEX_OPCODE_GET_FINAL;
|
||||
/* empty get request, use a small buff size */
|
||||
UINT16 tx_buff_size = BT_SMALL_BUFFER_SIZE < p_rcb->cover_art_max_tx ? BT_SMALL_BUFFER_SIZE : p_rcb->cover_art_max_tx;
|
||||
if (GOEPC_PrepareRequest(p_rcb->cover_art_goep_hdl, &info, tx_buff_size) == GOEP_SUCCESS) {
|
||||
GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_CONNECTION_ID, (UINT8 *)(&p_rcb->cover_art_cid), 4);
|
||||
GOEPC_SendRequest(p_rcb->cover_art_goep_hdl);
|
||||
}
|
||||
}
|
||||
|
||||
static void close_goepc_and_disconnect(tBTA_AV_RCB *p_rcb)
|
||||
{
|
||||
if (p_rcb->cover_art_goep_hdl) {
|
||||
GOEPC_Close(p_rcb->cover_art_goep_hdl);
|
||||
}
|
||||
p_rcb->cover_art_goep_hdl = 0;
|
||||
p_rcb->cover_art_cid = 0;
|
||||
p_rcb->cover_art_max_tx = 0;
|
||||
p_rcb->cover_art_max_rx = 0;
|
||||
|
||||
tBTA_AV_DATA *p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA));
|
||||
if (p_data == NULL) {
|
||||
assert(0);
|
||||
}
|
||||
p_data->hdr.event = BTA_AV_CA_GOEP_DISCONNECT_EVT;
|
||||
p_data->hdr.layer_specific = get_rcb_idx(p_rcb);
|
||||
p_data->ca_disconnect.reason = BT_STATUS_FAIL;
|
||||
bta_sys_sendmsg(p_data);
|
||||
}
|
||||
|
||||
static void image_handle_to_utf16(const UINT8 *image_handle, UINT8 *buffer)
|
||||
{
|
||||
UINT8 pos = 0;
|
||||
for (int i = 0 ; i < BTA_AV_CA_IMG_HDL_LEN ; i++){
|
||||
buffer[pos++] = 0;
|
||||
buffer[pos++] = image_handle[i];
|
||||
}
|
||||
buffer[pos++] = 0;
|
||||
buffer[pos++] = 0;
|
||||
}
|
||||
|
||||
void bta_av_ca_goep_event_handler(UINT16 handle, UINT8 event, tGOEPC_MSG *p_msg)
|
||||
{
|
||||
tBTA_AV_DATA *p_data = NULL;
|
||||
UINT16 rcb_idx;
|
||||
if (!find_rcb_idx_by_goep_handle(handle, &rcb_idx)) {
|
||||
/* can not find a rcb, go error */
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (event == GOEPC_RESPONSE_EVT || event == GOEPC_OPENED_EVT || event == GOEPC_CLOSED_EVT) {
|
||||
p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA));
|
||||
assert(p_data != NULL);
|
||||
}
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case GOEPC_OPENED_EVT:
|
||||
p_data->hdr.layer_specific = rcb_idx;
|
||||
p_data->hdr.event = BTA_AV_CA_GOEP_CONNECT_EVT;
|
||||
p_data->ca_connect.max_rx = p_msg->opened.our_mtu;
|
||||
break;
|
||||
case GOEPC_CLOSED_EVT:
|
||||
p_data->hdr.layer_specific = rcb_idx;
|
||||
p_data->hdr.event = BTA_AV_CA_GOEP_DISCONNECT_EVT;
|
||||
p_data->ca_disconnect.reason = BT_STATUS_FAIL;
|
||||
break;
|
||||
case GOEPC_RESPONSE_EVT:
|
||||
p_data->hdr.layer_specific = rcb_idx;
|
||||
p_data->ca_response.pkt = p_msg->response.pkt;
|
||||
p_data->ca_response.opcode = p_msg->response.opcode;
|
||||
p_data->ca_response.srm_en = p_msg->response.srm_en;
|
||||
p_data->ca_response.srm_wait = p_msg->response.srm_wait;
|
||||
if (p_msg->response.final) {
|
||||
p_data->hdr.event = BTA_AV_CA_RESPONSE_FINAL_EVT;
|
||||
}
|
||||
else {
|
||||
p_data->hdr.event = BTA_AV_CA_RESPONSE_EVT;
|
||||
}
|
||||
break;
|
||||
case GOEPC_MTU_CHANGED_EVT:
|
||||
case GOEPC_CONGEST_EVT:
|
||||
case GOEPC_UNCONGEST_EVT:
|
||||
/* ignore these event */
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
if (p_data) {
|
||||
bta_sys_sendmsg(p_data);
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
/* can not find rcb, just free resource and disconnect */
|
||||
if (p_data != NULL) {
|
||||
osi_free(p_data);
|
||||
}
|
||||
if (event == GOEPC_RESPONSE_EVT && p_msg->response.pkt != NULL) {
|
||||
osi_free(p_msg->response.pkt);
|
||||
}
|
||||
if (event != GOEPC_CLOSED_EVT) {
|
||||
GOEPC_Close(handle);
|
||||
}
|
||||
}
|
||||
|
||||
void bta_av_ca_api_open(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
tOBEX_SVR_INFO svr = {0};
|
||||
svr.tl = OBEX_OVER_L2CAP;
|
||||
svr.l2cap.psm = p_rcb->cover_art_l2cap_psm;
|
||||
svr.l2cap.pref_mtu = p_data->api_ca_open.mtu;
|
||||
/* reuse the security mask store in bta_av_cb, when support multi connection, this may need change */
|
||||
svr.l2cap.sec_mask = bta_av_cb.sec_mask;
|
||||
p_rcb->cover_art_max_rx = p_data->api_ca_open.mtu;
|
||||
get_peer_bd_addr(p_rcb, svr.l2cap.addr);
|
||||
|
||||
if (GOEPC_Open(&svr, bta_av_ca_goep_event_handler, &p_rcb->cover_art_goep_hdl) != GOEP_SUCCESS) {
|
||||
/* open failed */
|
||||
if ((p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA))) == NULL) {
|
||||
assert(0);
|
||||
}
|
||||
p_data->hdr.event = BTA_AV_CA_GOEP_DISCONNECT_EVT;
|
||||
p_data->hdr.layer_specific = get_rcb_idx(p_rcb);
|
||||
p_data->ca_disconnect.reason = BT_STATUS_FAIL;
|
||||
bta_sys_sendmsg(p_data);
|
||||
}
|
||||
}
|
||||
|
||||
void bta_av_ca_api_close(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
/* this is a normal disconnect, just build and send OBEX disconnect request */
|
||||
build_and_send_disconnect_req(p_rcb);
|
||||
}
|
||||
|
||||
void bta_av_ca_api_get(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
tOBEX_PARSE_INFO info = {0};
|
||||
UINT8 image_handle_utf16[BTA_AV_CA_IMG_HDL_UTF16_LEN];
|
||||
info.opcode = OBEX_OPCODE_GET_FINAL;
|
||||
/* limit the tx buff size to BT_DEFAULT_BUFFER_SIZE */
|
||||
UINT16 tx_buff_size = BT_DEFAULT_BUFFER_SIZE < p_rcb->cover_art_max_tx ? BT_DEFAULT_BUFFER_SIZE : p_rcb->cover_art_max_tx;
|
||||
if (GOEPC_PrepareRequest(p_rcb->cover_art_goep_hdl, &info, tx_buff_size) != GOEP_SUCCESS) {
|
||||
/* something error */
|
||||
goto error;
|
||||
}
|
||||
|
||||
GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_CONNECTION_ID, (UINT8 *)(&p_rcb->cover_art_cid), 4);
|
||||
switch (p_data->api_ca_get.type)
|
||||
{
|
||||
case BTA_AV_CA_GET_IMAGE_PROPERTIES:
|
||||
GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_TYPE, (const UINT8 *)cover_art_img_type_prop, COVER_ART_IMG_TYPE_PROP_LEN);
|
||||
break;
|
||||
case BTA_AV_CA_GET_IMAGE:
|
||||
GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_TYPE, (const UINT8 *)cover_art_img_type_img, COVER_ART_IMG_TYPE_IMG_LEN);
|
||||
break;
|
||||
case BTA_AV_CA_GET_LINKED_THUMBNAIL:
|
||||
GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_TYPE, (const UINT8 *)cover_art_img_type_thm, COVER_ART_IMG_TYPE_THM_LEN);
|
||||
break;
|
||||
default:
|
||||
/* should not go here */
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
image_handle_to_utf16(p_data->api_ca_get.image_handle, image_handle_utf16);
|
||||
GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, COVER_ART_HEADER_ID_IMG_HANDLE, (UINT8 *)image_handle_utf16, BTA_AV_CA_IMG_HDL_UTF16_LEN);
|
||||
if (p_data->api_ca_get.type == BTA_AV_CA_GET_IMAGE) {
|
||||
GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, COVER_ART_HEADER_ID_IMG_DESCRIPTOR, (UINT8 *)p_data->api_ca_get.image_descriptor, p_data->api_ca_get.image_descriptor_len);
|
||||
}
|
||||
/* always request to enable srm */
|
||||
GOEPC_RequestSetSRM(p_rcb->cover_art_goep_hdl, TRUE, FALSE);
|
||||
|
||||
if (GOEPC_SendRequest(p_rcb->cover_art_goep_hdl) != GOEP_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
error:
|
||||
close_goepc_and_disconnect(p_rcb);
|
||||
}
|
||||
|
||||
void bta_av_ca_response(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
tOBEX_PARSE_INFO info;
|
||||
OBEX_ParseResponse(p_data->ca_response.pkt, p_data->ca_response.opcode, &info);
|
||||
/* we always use a final get */
|
||||
if (p_data->ca_response.opcode == OBEX_OPCODE_GET_FINAL
|
||||
&& (info.response_code == OBEX_RESPONSE_CODE_CONTINUE || info.response_code == (OBEX_RESPONSE_CODE_CONTINUE | OBEX_FINAL_BIT_MASK)))
|
||||
{
|
||||
UINT8 *header = NULL;
|
||||
UINT8 *body_data = NULL;
|
||||
UINT16 body_data_len = 0;
|
||||
while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) {
|
||||
switch (*header)
|
||||
{
|
||||
case OBEX_HEADER_ID_BODY:
|
||||
/* actually,END_OF_BODY should not in this continue response */
|
||||
case OBEX_HEADER_ID_END_OF_BODY:
|
||||
if (body_data == NULL) {
|
||||
/* first body header */
|
||||
body_data = header + 3; /* skip opcode, length */
|
||||
body_data_len = OBEX_GetHeaderLength(header) - 3;
|
||||
}
|
||||
else {
|
||||
/* another body header found */
|
||||
report_data_event(NULL, body_data, body_data_len, FALSE);
|
||||
body_data = header + 3; /* skip opcode, length */
|
||||
body_data_len = OBEX_GetHeaderLength(header) - 3;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (body_data != NULL) {
|
||||
/* the only one or the last body data */
|
||||
report_data_event(p_data->ca_response.pkt, body_data, body_data_len, FALSE);
|
||||
}
|
||||
else {
|
||||
/* not any body data */
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
}
|
||||
|
||||
/* if SRM not enable, we need to send a empty get request */
|
||||
if (!p_data->ca_response.srm_en || p_data->ca_response.srm_wait) {
|
||||
build_and_send_empty_get_req(p_rcb);
|
||||
}
|
||||
}
|
||||
else {
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
close_goepc_and_disconnect(p_rcb);
|
||||
}
|
||||
|
||||
void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
tOBEX_PARSE_INFO info;
|
||||
OBEX_ParseResponse(p_data->ca_response.pkt, p_data->ca_response.opcode, &info);
|
||||
UINT8 *header = NULL;
|
||||
if (p_data->ca_response.opcode == OBEX_OPCODE_CONNECT) {
|
||||
/* we expect a success response code with final bit set */
|
||||
if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) {
|
||||
if (info.max_packet_length < 255) {
|
||||
p_rcb->cover_art_max_tx = 255;
|
||||
}
|
||||
else {
|
||||
p_rcb->cover_art_max_tx = info.max_packet_length;
|
||||
}
|
||||
BOOLEAN cid_found = false;
|
||||
while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) {
|
||||
if (*header == OBEX_HEADER_ID_CONNECTION_ID) {
|
||||
cid_found = true;
|
||||
memcpy((UINT8 *)(&p_rcb->cover_art_cid), header + 1, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cid_found) {
|
||||
goto error;
|
||||
}
|
||||
tBTA_AV_CA_STATUS ca_status;
|
||||
ca_status.connected = TRUE;
|
||||
ca_status.reason = BT_STATUS_SUCCESS;
|
||||
(*bta_av_cb.p_cback)(BTA_AV_CA_STATUS_EVT, (tBTA_AV *) &ca_status);
|
||||
/* done, free response packet */
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
}
|
||||
else {
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (p_data->ca_response.opcode == OBEX_OPCODE_GET_FINAL) {
|
||||
UINT8 *body_data = NULL;
|
||||
UINT16 body_data_len = 0;
|
||||
/* check response code is success */
|
||||
if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) {
|
||||
while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) {
|
||||
switch (*header)
|
||||
{
|
||||
/* actually, BODY should not in this final response */
|
||||
case OBEX_HEADER_ID_BODY:
|
||||
case OBEX_HEADER_ID_END_OF_BODY:
|
||||
if (body_data == NULL) {
|
||||
/* first body header */
|
||||
body_data = header + 3; /* skip opcode, length */
|
||||
body_data_len = OBEX_GetHeaderLength(header) - 3;
|
||||
}
|
||||
else {
|
||||
/* another body header found */
|
||||
report_data_event(NULL, body_data, body_data_len, FALSE);
|
||||
body_data = header + 3; /* skip opcode, length */
|
||||
body_data_len = OBEX_GetHeaderLength(header) - 3;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (body_data != NULL) {
|
||||
/* the only one or the last body data, packet will be free by upper layer */
|
||||
report_data_event(p_data->ca_response.pkt, body_data, body_data_len, TRUE);
|
||||
}
|
||||
else {
|
||||
/* not any body data */
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
}
|
||||
}
|
||||
else {
|
||||
report_error_data_event(BT_STATUS_FAIL);
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
}
|
||||
}
|
||||
else if (p_data->ca_response.opcode == OBEX_OPCODE_DISCONNECT) {
|
||||
/* received disconnect response, close l2cap channel and reset cover art value */
|
||||
bta_av_ca_force_disconnect(p_rcb, p_data);
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
}
|
||||
else {
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
goto error;
|
||||
}
|
||||
return;
|
||||
|
||||
error:
|
||||
close_goepc_and_disconnect(p_rcb);
|
||||
}
|
||||
|
||||
void bta_av_ca_goep_connect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
/* goep connection open, use a smaller value as max_rx */
|
||||
if (p_rcb->cover_art_max_rx > p_data->ca_connect.max_rx) {
|
||||
p_rcb->cover_art_max_rx = p_data->ca_connect.max_rx;
|
||||
}
|
||||
build_and_send_connect_req(p_rcb);
|
||||
}
|
||||
|
||||
void bta_av_ca_goep_disconnect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
p_rcb->cover_art_goep_hdl = 0;
|
||||
p_rcb->cover_art_max_rx = 0;
|
||||
p_rcb->cover_art_max_tx = 0;
|
||||
p_rcb->cover_art_cid = 0;
|
||||
|
||||
tBTA_AV_CA_STATUS ca_status;
|
||||
ca_status.connected = FALSE;
|
||||
ca_status.reason = p_data->ca_disconnect.reason;
|
||||
(*bta_av_cb.p_cback)(BTA_AV_CA_STATUS_EVT, (tBTA_AV *) &ca_status);
|
||||
}
|
||||
|
||||
void bta_av_ca_force_disconnect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
if (p_rcb->cover_art_goep_hdl) {
|
||||
GOEPC_Close(p_rcb->cover_art_goep_hdl);
|
||||
}
|
||||
/* dont reset p_rcb->cover_art_l2cap_psm */
|
||||
p_rcb->cover_art_goep_hdl = 0;
|
||||
p_rcb->cover_art_cid = 0;
|
||||
p_rcb->cover_art_max_tx = 0;
|
||||
p_rcb->cover_art_max_rx = 0;
|
||||
tBTA_AV_CA_STATUS ca_status;
|
||||
ca_status.connected = FALSE;
|
||||
/* force disconnect by upper, set reason to success */
|
||||
ca_status.reason = BT_STATUS_SUCCESS;
|
||||
(*bta_av_cb.p_cback)(BTA_AV_CA_STATUS_EVT, (tBTA_AV *) &ca_status);
|
||||
}
|
||||
|
||||
void bta_av_ca_reset(tBTA_AV_RCB *p_rcb)
|
||||
{
|
||||
if (p_rcb->cover_art_goep_hdl) {
|
||||
GOEPC_Close(p_rcb->cover_art_goep_hdl);
|
||||
}
|
||||
p_rcb->cover_art_l2cap_psm = 0;
|
||||
p_rcb->cover_art_goep_hdl = 0;
|
||||
p_rcb->cover_art_state = 0;
|
||||
p_rcb->cover_art_cid = 0;
|
||||
p_rcb->cover_art_max_tx = 0;
|
||||
p_rcb->cover_art_max_rx = 0;
|
||||
}
|
||||
|
||||
#endif /* BTA_AV_INCLUDED */
|
170
components/bt/host/bluedroid/bta/av/bta_av_ca_sm.c
Normal file
170
components/bt/host/bluedroid/bta/av/bta_av_ca_sm.c
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
|
||||
|
||||
#include <string.h>
|
||||
#include "bta/bta_av_api.h"
|
||||
#include "bta_av_int.h"
|
||||
#include "stack/avdt_api.h"
|
||||
#include "bta/utl.h"
|
||||
#include "stack/l2c_api.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/list.h"
|
||||
|
||||
#include "common/bt_trace.h"
|
||||
|
||||
/* state machine states */
|
||||
enum {
|
||||
BTA_AV_CA_INIT_ST,
|
||||
BTA_AV_CA_OPENING_ST,
|
||||
BTA_AV_CA_CONNECTING_ST,
|
||||
BTA_AV_CA_CONNECTED_ST,
|
||||
BTA_AV_CA_GETTING_ST,
|
||||
BTA_AV_CA_CLOSING_ST
|
||||
};
|
||||
|
||||
/* state machine action enumeration list */
|
||||
enum {
|
||||
BTA_AV_API_CA_OPEN,
|
||||
BTA_AV_API_CA_CLOSE,
|
||||
BTA_AV_API_CA_GET,
|
||||
BTA_AV_CA_RESPONSE,
|
||||
BTA_AV_CA_RESPONSE_FINAL,
|
||||
BTA_AV_CA_GOEP_CONNECT,
|
||||
BTA_AV_CA_GOEP_DISCONNECT,
|
||||
BTA_AV_CA_FORCE_DISCONNECT,
|
||||
BTA_AV_CA_NUM_ACTIONS
|
||||
};
|
||||
|
||||
#define BTA_AV_CA_IGNORE BTA_AV_CA_NUM_ACTIONS
|
||||
|
||||
/* type for action functions */
|
||||
typedef void (*tBTA_AV_CA_ACTION)(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data);
|
||||
|
||||
/* action functions */
|
||||
const tBTA_AV_CA_ACTION bta_av_ca_action[] = {
|
||||
bta_av_ca_api_open,
|
||||
bta_av_ca_api_close,
|
||||
bta_av_ca_api_get,
|
||||
bta_av_ca_response,
|
||||
bta_av_ca_response_final,
|
||||
bta_av_ca_goep_connect,
|
||||
bta_av_ca_goep_disconnect,
|
||||
bta_av_ca_force_disconnect,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* state table information */
|
||||
#define BTA_AV_CA_ACTION_COL 0 /* position of actions */
|
||||
#define BTA_AV_CA_NEXT_STATE 1 /* position of next state */
|
||||
#define BTA_AV_CA_NUM_COLS 2 /* number of columns in state tables */
|
||||
|
||||
/* state table for init state */
|
||||
static const UINT8 bta_av_ca_st_init[][BTA_AV_CA_NUM_COLS] = {
|
||||
/* Event Action 1 Next state */
|
||||
/* API_CA_OPEN_EVT */ {BTA_AV_API_CA_OPEN, BTA_AV_CA_OPENING_ST },
|
||||
/* API_CA_CLOSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST },
|
||||
/* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST },
|
||||
/* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST },
|
||||
/* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST },
|
||||
/* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST },
|
||||
/* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST },
|
||||
};
|
||||
|
||||
/* state table for opening state */
|
||||
static const UINT8 bta_av_ca_st_opening[][BTA_AV_CA_NUM_COLS] = {
|
||||
/* Event Action 1 Next state */
|
||||
/* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_OPENING_ST },
|
||||
/* API_CA_CLOSE_EVT */ {BTA_AV_CA_FORCE_DISCONNECT, BTA_AV_CA_INIT_ST },
|
||||
/* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_OPENING_ST },
|
||||
/* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_OPENING_ST },
|
||||
/* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_OPENING_ST },
|
||||
/* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_GOEP_CONNECT, BTA_AV_CA_CONNECTING_ST },
|
||||
/* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST },
|
||||
};
|
||||
|
||||
/* state table for connecting state */
|
||||
static const UINT8 bta_av_ca_st_connecting[][BTA_AV_CA_NUM_COLS] = {
|
||||
/* Event Action 1 Next state */
|
||||
/* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTING_ST },
|
||||
/* API_CA_CLOSE_EVT */ {BTA_AV_CA_FORCE_DISCONNECT, BTA_AV_CA_INIT_ST },
|
||||
/* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTING_ST },
|
||||
/* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTING_ST },
|
||||
/* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_RESPONSE_FINAL, BTA_AV_CA_CONNECTED_ST },
|
||||
/* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTING_ST },
|
||||
/* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST },
|
||||
};
|
||||
|
||||
/* state table for connected state */
|
||||
static const UINT8 bta_av_ca_st_connected[][BTA_AV_CA_NUM_COLS] = {
|
||||
/* Event Action 1 Next state */
|
||||
/* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTED_ST },
|
||||
/* API_CA_CLOSE_EVT */ {BTA_AV_API_CA_CLOSE, BTA_AV_CA_CLOSING_ST },
|
||||
/* API_CA_GET_EVT */ {BTA_AV_API_CA_GET, BTA_AV_CA_GETTING_ST },
|
||||
/* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTED_ST },
|
||||
/* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTED_ST },
|
||||
/* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTED_ST },
|
||||
/* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST },
|
||||
};
|
||||
|
||||
/* state table for getting state */
|
||||
static const UINT8 bta_av_ca_st_getting[][BTA_AV_CA_NUM_COLS] = {
|
||||
/* Event Action 1 Next state */
|
||||
/* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_GETTING_ST },
|
||||
/* API_CA_CLOSE_EVT */ {BTA_AV_CA_FORCE_DISCONNECT, BTA_AV_CA_INIT_ST },
|
||||
/* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_GETTING_ST },
|
||||
/* CA_RESPONSE_EVT */ {BTA_AV_CA_RESPONSE, BTA_AV_CA_GETTING_ST },
|
||||
/* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_RESPONSE_FINAL, BTA_AV_CA_CONNECTED_ST },
|
||||
/* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_GETTING_ST },
|
||||
/* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST },
|
||||
};
|
||||
|
||||
/* state table for closing state */
|
||||
static const UINT8 bta_av_ca_st_closing[][BTA_AV_CA_NUM_COLS] = {
|
||||
/* Event Action 1 Next state */
|
||||
/* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CLOSING_ST },
|
||||
/* API_CA_CLOSE_EVT */ {BTA_AV_CA_FORCE_DISCONNECT, BTA_AV_CA_INIT_ST },
|
||||
/* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CLOSING_ST },
|
||||
/* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CLOSING_ST },
|
||||
/* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_RESPONSE_FINAL, BTA_AV_CA_INIT_ST },
|
||||
/* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CLOSING_ST },
|
||||
/* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST },
|
||||
};
|
||||
|
||||
/* type for state table */
|
||||
typedef const UINT8 (*tBTA_AV_CA_ST_TBL)[BTA_AV_CA_NUM_COLS];
|
||||
|
||||
/* state table */
|
||||
static const tBTA_AV_CA_ST_TBL bta_av_ca_st_tbl[] = {
|
||||
bta_av_ca_st_init,
|
||||
bta_av_ca_st_opening,
|
||||
bta_av_ca_st_connecting,
|
||||
bta_av_ca_st_connected,
|
||||
bta_av_ca_st_getting,
|
||||
bta_av_ca_st_closing
|
||||
};
|
||||
|
||||
void bta_av_ca_sm_execute(tBTA_AV_RCB *p_rcb, UINT16 event, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
tBTA_AV_CA_ST_TBL state_table;
|
||||
UINT8 action;
|
||||
/* look up the state table for the current state */
|
||||
state_table = bta_av_ca_st_tbl[p_rcb->cover_art_state];
|
||||
|
||||
event -= BTA_AV_CA_FIRST_SM_EVT;
|
||||
|
||||
/* set next state */
|
||||
p_rcb->cover_art_state = state_table[event][BTA_AV_CA_NEXT_STATE];
|
||||
|
||||
/* execute action functions */
|
||||
if ((action = state_table[event][BTA_AV_CA_ACTION_COL]) != BTA_AV_CA_IGNORE) {
|
||||
(*bta_av_ca_action[action])(p_rcb, p_data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BTA_AV_INCLUDED */
|
@ -461,7 +461,7 @@ static void bta_av_a2dp_report_cback(UINT8 handle, AVDT_REPORT_TYPE type,
|
||||
**
|
||||
** Function bta_av_api_sink_enable
|
||||
**
|
||||
** Description activate, deactive A2DP Sink,
|
||||
** Description activate, deactivate A2DP Sink,
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
@ -593,7 +593,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set the Calss of Device (Audio & Capturing/Rendering service class bit) */
|
||||
/* Set the Class of Device (Audio & Capturing/Rendering service class bit) */
|
||||
if (p_data->api_reg.tsep == AVDT_TSEP_SRC) {
|
||||
cod.service = BTM_COD_SERVICE_CAPTURING | BTM_COD_SERVICE_AUDIO;
|
||||
cod.major = BTM_COD_MAJOR_AUDIO;
|
||||
@ -1248,6 +1248,11 @@ BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
|
||||
APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)\n", event, bta_av_evt_code(event));
|
||||
/* state machine events */
|
||||
bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA *) p_msg);
|
||||
} else if (event >= BTA_AV_CA_FIRST_SM_EVT && event <= BTA_AV_CA_LAST_SM_EVT) {
|
||||
if (p_msg->layer_specific < BTA_AV_NUM_RCB) {
|
||||
tBTA_AV_RCB *p_rcb = &bta_av_cb.rcb[p_msg->layer_specific];
|
||||
bta_av_ca_sm_execute(p_rcb, p_msg->event, (tBTA_AV_DATA *) p_msg);
|
||||
}
|
||||
} else {
|
||||
APPL_TRACE_VERBOSE("handle=0x%x\n", p_msg->layer_specific);
|
||||
tBTA_AV_SCB *p_scb = bta_av_hndl_to_scb(p_msg->layer_specific);
|
||||
|
@ -86,6 +86,15 @@ enum {
|
||||
BTA_AV_AVDT_DELAY_RPT_EVT,
|
||||
BTA_AV_ACP_CONNECT_EVT,
|
||||
|
||||
/* these events are handled by the Cover Art Client state machine */
|
||||
BTA_AV_API_CA_OPEN_EVT,
|
||||
BTA_AV_API_CA_CLOSE_EVT,
|
||||
BTA_AV_API_CA_GET_EVT,
|
||||
BTA_AV_CA_RESPONSE_EVT,
|
||||
BTA_AV_CA_RESPONSE_FINAL_EVT,
|
||||
BTA_AV_CA_GOEP_CONNECT_EVT,
|
||||
BTA_AV_CA_GOEP_DISCONNECT_EVT,
|
||||
|
||||
/* these events are handled outside of the state machine */
|
||||
BTA_AV_API_ENABLE_EVT,
|
||||
BTA_AV_API_REGISTER_EVT,
|
||||
@ -115,6 +124,10 @@ enum {
|
||||
#define BTA_AV_FIRST_SM_EVT BTA_AV_API_DISABLE_EVT
|
||||
#define BTA_AV_LAST_SM_EVT BTA_AV_AVRC_NONE_EVT
|
||||
|
||||
/* events for AVRC Cover Art state machine */
|
||||
#define BTA_AV_CA_FIRST_SM_EVT BTA_AV_API_CA_OPEN_EVT
|
||||
#define BTA_AV_CA_LAST_SM_EVT BTA_AV_CA_GOEP_DISCONNECT_EVT
|
||||
|
||||
/* events for AV stream control block state machine */
|
||||
#define BTA_AV_FIRST_SSM_EVT BTA_AV_API_OPEN_EVT
|
||||
|
||||
@ -348,6 +361,48 @@ typedef struct {
|
||||
BT_HDR hdr;
|
||||
} tBTA_AV_API_GET_DELAY_VALUE;
|
||||
|
||||
/* data type for BTA_AV_API_CA_OPEN_EVT */
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
UINT16 mtu;
|
||||
} tBTA_AV_API_CA_OPEN;
|
||||
|
||||
/* data type for BTA_AV_API_CA_CLOSE_EVT */
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
} tBTA_AV_API_CA_CLOSE;
|
||||
|
||||
/* data type for BTA_AV_API_CA_GET_EVT */
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
tBTA_AV_GET_TYPE type;
|
||||
UINT8 image_handle[7];
|
||||
/* Image descriptor used in get image function */
|
||||
UINT16 image_descriptor_len;
|
||||
UINT8 *image_descriptor;
|
||||
} tBTA_AV_API_CA_GET;
|
||||
|
||||
/* data type for BTA_AV_CA_RESPONSE_EVT and BTA_AV_CA_RESPONSE_FINAL_EVT */
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
BT_HDR *pkt;
|
||||
UINT8 opcode;
|
||||
BOOLEAN srm_en;
|
||||
BOOLEAN srm_wait;
|
||||
} tBTA_AV_CA_RESPONSE;
|
||||
|
||||
/* data type for BTA_AV_CA_CONNECT_EVT */
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
UINT16 max_rx;
|
||||
} tBTA_AV_CA_CONNECT;
|
||||
|
||||
/* data type for BTA_AV_CA_DISCONNECT_EVT */
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
UINT16 reason;
|
||||
} tBTA_AV_CA_DISCONNECT;
|
||||
|
||||
/* initiator/acceptor role for adaption */
|
||||
#define BTA_AV_ROLE_AD_INT 0x00 /* initiator */
|
||||
#define BTA_AV_ROLE_AD_ACP 0x01 /* acceptor */
|
||||
@ -382,6 +437,12 @@ typedef union {
|
||||
tBTA_AV_API_META_RSP api_meta_rsp;
|
||||
tBTA_AV_API_SET_DELAY_VALUE api_set_delay_vlaue;
|
||||
tBTA_AV_API_GET_DELAY_VALUE api_get_delay_value;
|
||||
tBTA_AV_API_CA_OPEN api_ca_open;
|
||||
tBTA_AV_API_CA_CLOSE api_ca_close;
|
||||
tBTA_AV_API_CA_GET api_ca_get;
|
||||
tBTA_AV_CA_RESPONSE ca_response;
|
||||
tBTA_AV_CA_CONNECT ca_connect;
|
||||
tBTA_AV_CA_DISCONNECT ca_disconnect;
|
||||
} tBTA_AV_DATA;
|
||||
|
||||
typedef void (tBTA_AV_VDP_DATA_ACT)(void *p_scb);
|
||||
@ -405,8 +466,8 @@ typedef union {
|
||||
#define BTA_AV_Q_TAG_START 0x02 /* before start sending media packets */
|
||||
#define BTA_AV_Q_TAG_STREAM 0x03 /* during streaming */
|
||||
|
||||
#define BTA_AV_WAIT_ACP_CAPS_ON 0x01 /* retriving the peer capabilities */
|
||||
#define BTA_AV_WAIT_ACP_CAPS_STARTED 0x02 /* started while retriving peer capabilities */
|
||||
#define BTA_AV_WAIT_ACP_CAPS_ON 0x01 /* retrieving the peer capabilities */
|
||||
#define BTA_AV_WAIT_ACP_CAPS_STARTED 0x02 /* started while retrieving peer capabilities */
|
||||
#define BTA_AV_WAIT_ROLE_SW_RES_OPEN 0x04 /* waiting for role switch result after API_OPEN, before STR_OPENED */
|
||||
#define BTA_AV_WAIT_ROLE_SW_RES_START 0x08 /* waiting for role switch result before streaming */
|
||||
#define BTA_AV_WAIT_ROLE_SW_STARTED 0x10 /* started while waiting for role switch result */
|
||||
@ -462,7 +523,7 @@ typedef struct {
|
||||
BOOLEAN use_rc; /* TRUE if AVRCP is allowed */
|
||||
BOOLEAN started; /* TRUE if stream started */
|
||||
UINT8 co_started; /* non-zero, if stream started from call-out perspective */
|
||||
BOOLEAN recfg_sup; /* TRUE if the first attempt to reconfigure the stream was successfull, else False if command fails */
|
||||
BOOLEAN recfg_sup; /* TRUE if the first attempt to reconfigure the stream was successful, else False if command fails */
|
||||
BOOLEAN suspend_sup; /* TRUE if Suspend stream is supported, else FALSE if suspend command fails */
|
||||
BOOLEAN deregistring; /* TRUE if deregistering */
|
||||
BOOLEAN sco_suspend; /* TRUE if SUSPEND is issued automatically for SCO */
|
||||
@ -471,7 +532,7 @@ typedef struct {
|
||||
UINT8 wait; /* set 0x1, when getting Caps as ACP, set 0x2, when started */
|
||||
UINT8 q_tag; /* identify the associated q_info union member */
|
||||
BOOLEAN no_rtp_hdr; /* TRUE if add no RTP header*/
|
||||
UINT8 disc_rsn; /* disconenction reason */
|
||||
UINT8 disc_rsn; /* disconnection reason */
|
||||
UINT16 uuid_int; /*intended UUID of Initiator to connect to */
|
||||
} tBTA_AV_SCB;
|
||||
|
||||
@ -481,6 +542,13 @@ typedef struct {
|
||||
|
||||
#define BTA_AV_RC_CONN_MASK 0x20
|
||||
|
||||
#define BTA_AV_CA_IMG_HDL_UTF16_LEN 16 /* Cover Art image handle in utf-16 format, fixed to 16 */
|
||||
|
||||
#define BTA_AV_CA_SRM_DISABLE 0x00
|
||||
#define BTA_AV_CA_SRM_ENABLE_REQ 0x01
|
||||
#define BTA_AV_CA_SRM_WAIT 0x02
|
||||
#define BTA_AV_CA_SRM_ENABLE 0x03
|
||||
|
||||
/* type for AV RCP control block */
|
||||
/* index to this control block is the rc handle */
|
||||
typedef struct {
|
||||
@ -491,6 +559,13 @@ typedef struct {
|
||||
tBTA_AV_FEAT peer_features; /* peer features mask */
|
||||
UINT16 peer_ct_features;
|
||||
UINT16 peer_tg_features;
|
||||
|
||||
UINT16 cover_art_l2cap_psm; /* OBEX over L2CAP PSM */
|
||||
UINT16 cover_art_goep_hdl; /* Cover Art client GOEP connection handle */
|
||||
UINT8 cover_art_state; /* Cover Art client state machine */
|
||||
UINT32 cover_art_cid; /* Cover Art client connection id */
|
||||
UINT16 cover_art_max_tx; /* max packet length peer device can receive */
|
||||
UINT16 cover_art_max_rx; /* max packet length we can receive */
|
||||
} tBTA_AV_RCB;
|
||||
#define BTA_AV_NUM_RCB (BTA_AV_NUM_STRS + 2)
|
||||
|
||||
@ -705,6 +780,17 @@ extern void bta_av_do_disc_vdp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_vdp_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_reg_vdp (tAVDT_CS *p_cs, char *p_service_name, void *p_data);
|
||||
|
||||
extern void bta_av_ca_api_open(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_ca_api_close(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_ca_api_get(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_ca_response(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_ca_goep_connect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_ca_goep_disconnect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_ca_force_disconnect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_ca_sm_execute(tBTA_AV_RCB *p_rcb, UINT16 event, tBTA_AV_DATA *p_data);
|
||||
extern void bta_av_ca_reset(tBTA_AV_RCB *p_rcb);
|
||||
|
||||
#endif ///BTA_AV_INCLUDED == TRUE
|
||||
|
||||
#endif /* BTA_AV_INT_H */
|
||||
|
@ -43,14 +43,14 @@
|
||||
#define BTA_AV_FAIL_STREAM 3 /* stream connection failed */
|
||||
#define BTA_AV_FAIL_RESOURCES 4 /* no resources */
|
||||
#define BTA_AV_FAIL_ROLE 5 /* failed due to role management related issues */
|
||||
#define BTA_AV_FAIL_GET_CAP 6 /* get capability failed due to no SEP availale on the peer */
|
||||
#define BTA_AV_FAIL_GET_CAP 6 /* get capability failed due to no SEP available on the peer */
|
||||
|
||||
typedef UINT8 tBTA_AV_STATUS;
|
||||
|
||||
/* AV features masks */
|
||||
#define BTA_AV_FEAT_RCTG 0x0001 /* remote control target */
|
||||
#define BTA_AV_FEAT_RCCT 0x0002 /* remote control controller */
|
||||
#define BTA_AV_FEAT_PROTECT 0x0004 /* streaming media contect protection */
|
||||
#define BTA_AV_FEAT_PROTECT 0x0004 /* streaming media context protection */
|
||||
#define BTA_AV_FEAT_VENDOR 0x0008 /* remote control vendor dependent commands */
|
||||
#define BTA_AV_FEAT_REPORT 0x0020 /* use reporting service for VDP */
|
||||
#define BTA_AV_FEAT_METADATA 0x0040 /* remote control Metadata Transfer command/response */
|
||||
@ -60,6 +60,7 @@ typedef UINT8 tBTA_AV_STATUS;
|
||||
#define BTA_AV_FEAT_ADV_CTRL 0x0200 /* remote control Advanced Control command/response */
|
||||
#define BTA_AV_FEAT_DELAY_RPT 0x0400 /* allow delay reporting */
|
||||
#define BTA_AV_FEAT_ACP_START 0x0800 /* start stream when 2nd SNK was accepted */
|
||||
#define BTA_AV_FEAT_COVER_ART 0x1000 /* remote control target cover art */
|
||||
|
||||
/* Internal features */
|
||||
#define BTA_AV_FEAT_NO_SCO_SSPD 0x8000 /* Do not suspend av streaming as to AG events(SCO or Call) */
|
||||
@ -107,6 +108,7 @@ typedef UINT8 tBTA_AV_HNDL;
|
||||
#define BTA_AV_MAX_VDP_MTU 1008
|
||||
#endif
|
||||
|
||||
#define BTA_AV_CA_IMG_HDL_LEN 7 /* Cover Art image handle len, fixed to 7 */
|
||||
|
||||
/* codec type */
|
||||
#define BTA_AV_CODEC_SBC A2D_MEDIA_CT_SBC /* SBC media codec type */
|
||||
@ -224,6 +226,12 @@ typedef UINT8 tBTA_AV_CODE;
|
||||
|
||||
typedef UINT8 tBTA_AV_ERR;
|
||||
|
||||
/* type codes for BTA_AV_API_CA_GET */
|
||||
#define BTA_AV_CA_GET_IMAGE_PROPERTIES 0x01
|
||||
#define BTA_AV_CA_GET_IMAGE 0x02
|
||||
#define BTA_AV_CA_GET_LINKED_THUMBNAIL 0x03
|
||||
|
||||
typedef UINT8 tBTA_AV_GET_TYPE;
|
||||
|
||||
/* AV callback events */
|
||||
#define BTA_AV_ENABLE_EVT 0 /* AV enabled */
|
||||
@ -253,8 +261,12 @@ typedef UINT8 tBTA_AV_ERR;
|
||||
#define BTA_AV_SET_DELAY_VALUE_EVT 22 /* set delay reporting value */
|
||||
#define BTA_AV_GET_DELAY_VALUE_EVT 23 /* get delay reporting value */
|
||||
#define BTA_AV_SNK_PSC_CFG_EVT 24 /* Protocol service capabilities. */
|
||||
|
||||
#define BTA_AV_CA_STATUS_EVT 25 /* Cover Art Client status event */
|
||||
#define BTA_AV_CA_DATA_EVT 26 /* Cover Art response body data */
|
||||
|
||||
/* Max BTA event */
|
||||
#define BTA_AV_MAX_EVT 25
|
||||
#define BTA_AV_MAX_EVT 27
|
||||
|
||||
|
||||
/* function types for call-out functions */
|
||||
@ -481,6 +493,20 @@ typedef struct {
|
||||
UINT16 psc_mask;
|
||||
} tBTA_AV_SNK_PSC_CFG;
|
||||
|
||||
/* data associated with BTA_AV_CA_STATUS_EVT */
|
||||
typedef struct {
|
||||
BOOLEAN connected; /* whether Cover Art connection is connected */
|
||||
UINT16 reason; /* connect failed or disconnect reason */
|
||||
} tBTA_AV_CA_STATUS;
|
||||
|
||||
/* data associated with BTA_AV_CA_DATA_EVT */
|
||||
typedef struct {
|
||||
UINT16 status; /* OBEX response status */
|
||||
BOOLEAN final; /* final data packet */
|
||||
UINT16 data_len; /* data len */
|
||||
UINT8 *p_data; /* point to the data in p_hdr */
|
||||
BT_HDR *p_hdr; /* after data pass to application, free this packet */
|
||||
} tBTA_AV_CA_DATA;
|
||||
|
||||
/* union of data associated with AV callback */
|
||||
typedef union {
|
||||
@ -506,6 +532,8 @@ typedef union {
|
||||
tBTA_AV_RC_FEAT rc_feat;
|
||||
tBTA_AV_DELAY delay;
|
||||
tBTA_AV_SNK_PSC_CFG psc;
|
||||
tBTA_AV_CA_STATUS ca_status;
|
||||
tBTA_AV_CA_DATA ca_data;
|
||||
} tBTA_AV;
|
||||
|
||||
/* union of data associated with AV Media callback */
|
||||
@ -865,6 +893,43 @@ void BTA_AvMetaRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code,
|
||||
*******************************************************************************/
|
||||
void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p_pkt);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_AvCaOpen
|
||||
**
|
||||
** Description Open a Cover Art OBEX connection to peer device. This function
|
||||
** can only be used if peer device TG support Cover Art feature and
|
||||
** AV is enabled with feature BTA_AV_FEAT_METADATA.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTA_AvCaOpen(UINT8 rc_handle, UINT16 pref_packet_len);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_AvCaClose
|
||||
**
|
||||
** Description Close a Cover Art OBEX connection.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTA_AvCaClose(UINT8 rc_handle);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTA_AvCaGet
|
||||
**
|
||||
** Description Start the process to get image properties, get image or get
|
||||
** linked thumbnail. This function can only be used if Cover Art
|
||||
** OBEX connection is established.
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTA_AvCaGet(UINT8 rc_handle, tBTA_AV_GET_TYPE type, UINT8 *image_handle, UINT8 *image_descriptor, UINT16 image_descriptor_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -91,7 +91,8 @@ typedef UINT16 tBTA_SYS_HW_MODULE;
|
||||
#define BTA_ID_GATTC 31 /* GATT Client */
|
||||
#define BTA_ID_GATTS 32 /* GATT Client */
|
||||
#define BTA_ID_SDP 33 /* SDP Client */
|
||||
#define BTA_ID_BLUETOOTH_MAX 34 /* last BT profile */
|
||||
#define BTA_ID_GOEPC 34 /* GOEP Client */
|
||||
#define BTA_ID_BLUETOOTH_MAX 35 /* last BT profile */
|
||||
|
||||
/* GENERIC */
|
||||
#define BTA_ID_PRM 38
|
||||
@ -142,7 +143,7 @@ typedef void (tBTA_SYS_CONN_CBACK)(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8
|
||||
typedef void (tBTA_SYS_SSR_CFG_CBACK)(UINT8 id, UINT8 app_id, UINT16 latency, UINT16 tout);
|
||||
|
||||
#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
|
||||
/* eir callback for adding/removeing UUID */
|
||||
/* eir callback for adding/removing UUID */
|
||||
typedef void (tBTA_SYS_EIR_CBACK)(tBT_UUID uuid, BOOLEAN adding);
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
#if BTC_AV_INCLUDED
|
||||
|
||||
// global variable to inidcate avrc is initialized with a2dp
|
||||
// global variable to indicate avrc is initialized with a2dp
|
||||
bool g_av_with_rc;
|
||||
// global variable to indicate a2dp is initialized
|
||||
bool g_a2dp_on_init;
|
||||
@ -127,6 +127,8 @@ static btc_av_cb_t *btc_av_cb_ptr = NULL;
|
||||
case BTA_AV_META_MSG_EVT: \
|
||||
case BTA_AV_RC_FEAT_EVT: \
|
||||
case BTA_AV_REMOTE_RSP_EVT: \
|
||||
case BTA_AV_CA_STATUS_EVT: \
|
||||
case BTA_AV_CA_DATA_EVT: \
|
||||
{ \
|
||||
btc_rc_handler(e, d);\
|
||||
}break; \
|
||||
@ -382,6 +384,8 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data)
|
||||
case BTA_AV_META_MSG_EVT:
|
||||
case BTA_AV_RC_FEAT_EVT:
|
||||
case BTA_AV_REMOTE_RSP_EVT:
|
||||
case BTA_AV_CA_STATUS_EVT:
|
||||
case BTA_AV_CA_DATA_EVT:
|
||||
btc_rc_handler(event, (tBTA_AV *)p_data);
|
||||
break;
|
||||
|
||||
@ -1355,7 +1359,7 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
|
||||
/* send a command to BT Media Task */
|
||||
btc_a2dp_sink_reset_decoder((UINT8 *)p_data);
|
||||
|
||||
/* currently only supportes SBC */
|
||||
/* currently only supports SBC */
|
||||
a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE);
|
||||
if (a2d_status == A2D_SUCCESS) {
|
||||
btc_msg_t msg;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -40,7 +40,7 @@ static void btc_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 c
|
||||
** Static variables
|
||||
******************************************************************************/
|
||||
|
||||
/* flag indicating wheter TG/CT is initialized */
|
||||
/* flag indicating whether TG/CT is initialized */
|
||||
static uint32_t s_rc_ct_init;
|
||||
static uint32_t s_rc_tg_init;
|
||||
|
||||
@ -157,6 +157,11 @@ bool btc_avrc_ct_rn_evt_supported(uint8_t event_id)
|
||||
true : false;
|
||||
}
|
||||
|
||||
bool btc_avrc_ct_check_cover_art_support(void)
|
||||
{
|
||||
return (btc_rc_cb.rc_features & BTA_AV_FEAT_COVER_ART);
|
||||
}
|
||||
|
||||
bool btc_avrc_tg_init_p(void)
|
||||
{
|
||||
return (s_rc_tg_init == BTC_RC_TG_INIT_MAGIC);
|
||||
@ -181,6 +186,44 @@ bool btc_avrc_ct_connected_p(void)
|
||||
(btc_rc_cb.rc_features & BTA_AV_FEAT_RCTG);
|
||||
}
|
||||
|
||||
void btc_avrc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
btc_avrc_args_t *dst = (btc_avrc_args_t *)p_dest;
|
||||
btc_avrc_args_t *src = (btc_avrc_args_t *)p_src;
|
||||
size_t len;
|
||||
|
||||
switch (msg->act) {
|
||||
case BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT:
|
||||
len = src->ca_get_img.image_descriptor_len;
|
||||
dst->ca_get_img.image_descriptor = (uint8_t *)osi_malloc(len);
|
||||
if (dst->ca_get_img.image_descriptor) {
|
||||
memcpy(dst->ca_get_img.image_descriptor, src->ca_get_img.image_descriptor, len);
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s %d no mem\n", __FUNCTION__, msg->act);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BTC_TRACE_DEBUG("%s Unhandled deep copy %d\n", __FUNCTION__, msg->act);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void btc_avrc_arg_deep_free(btc_msg_t *msg)
|
||||
{
|
||||
btc_avrc_args_t *arg = (btc_avrc_args_t *)msg->arg;
|
||||
|
||||
switch (msg->act) {
|
||||
case BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT:
|
||||
if (arg->ca_get_img.image_descriptor) {
|
||||
osi_free(arg->ca_get_img.image_descriptor);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BTC_TRACE_DEBUG("%s Unhandled deep free %d\n", __FUNCTION__, msg->act);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void btc_avrc_tg_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
btc_avrc_tg_args_t *dst = (btc_avrc_tg_args_t *) p_dest;
|
||||
@ -495,10 +538,12 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
|
||||
}
|
||||
|
||||
tBTA_AV_FEAT rc_features = btc_rc_cb.rc_features;
|
||||
bool cover_art_connected = btc_rc_cb.rc_cover_art_connected;
|
||||
|
||||
// clean up the state
|
||||
btc_rc_cb.rc_handle = 0;
|
||||
btc_rc_cb.rc_connected = FALSE;
|
||||
btc_rc_cb.rc_cover_art_connected = FALSE;
|
||||
|
||||
btc_rc_cb.rc_features = 0;
|
||||
btc_rc_cb.rc_ct_features = 0;
|
||||
@ -507,6 +552,15 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
|
||||
memset(btc_rc_cb.rc_ntf, 0, sizeof(btc_rc_cb.rc_ntf));
|
||||
|
||||
/* report connection state */
|
||||
if (cover_art_connected) {
|
||||
/* if rc disconnect, cover art disconnect too */
|
||||
esp_avrc_ct_cb_param_t param;
|
||||
memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t));
|
||||
param.cover_art_state.state = ESP_AVRC_COVER_ART_DISCONNECTED;
|
||||
param.cover_art_state.reason = BT_STATUS_FAIL;
|
||||
btc_avrc_ct_cb_to_app(ESP_AVRC_CT_COVER_ART_STATE_EVT, ¶m);
|
||||
}
|
||||
|
||||
if (rc_features & BTA_AV_FEAT_RCTG) {
|
||||
esp_avrc_ct_cb_param_t param;
|
||||
memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t));
|
||||
@ -751,7 +805,7 @@ static void btc_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 c
|
||||
|
||||
btc_rc_cb.rc_ntf[event_id - 1].registered = TRUE;
|
||||
btc_rc_cb.rc_ntf[event_id - 1].label = label;
|
||||
BTC_TRACE_EVENT("%s: New registerd notification: event_id:0x%x, label:0x%x",
|
||||
BTC_TRACE_EVENT("%s: New registered notification: event_id:0x%x, label:0x%x",
|
||||
__FUNCTION__, event_id, label);
|
||||
|
||||
// set up callback
|
||||
@ -967,6 +1021,34 @@ void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
|
||||
handle_rc_passthrough_cmd(&p_data->remote_cmd);
|
||||
}
|
||||
break;
|
||||
case BTA_AV_CA_STATUS_EVT: {
|
||||
btc_rc_cb.rc_cover_art_connected = p_data->ca_status.connected;
|
||||
esp_avrc_ct_cb_param_t param;
|
||||
memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t));
|
||||
if (p_data->ca_status.connected) {
|
||||
param.cover_art_state.state = ESP_AVRC_COVER_ART_CONNECTED;
|
||||
}
|
||||
else {
|
||||
param.cover_art_state.state = ESP_AVRC_COVER_ART_DISCONNECTED;
|
||||
}
|
||||
param.cover_art_state.reason = p_data->ca_status.reason;
|
||||
btc_avrc_ct_cb_to_app(ESP_AVRC_CT_COVER_ART_STATE_EVT, ¶m);
|
||||
}
|
||||
break;
|
||||
case BTA_AV_CA_DATA_EVT: {
|
||||
esp_avrc_ct_cb_param_t param;
|
||||
memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t));
|
||||
param.cover_art_data.status = p_data->ca_data.status;
|
||||
param.cover_art_data.final = p_data->ca_data.final;
|
||||
param.cover_art_data.data_len = p_data->ca_data.data_len;
|
||||
param.cover_art_data.p_data = p_data->ca_data.p_data;
|
||||
btc_avrc_ct_cb_to_app(ESP_AVRC_CT_COVER_ART_DATA_EVT, ¶m);
|
||||
/* free the data packet now */
|
||||
if (p_data->ca_data.p_hdr != NULL) {
|
||||
osi_free(p_data->ca_data.p_hdr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BTC_TRACE_DEBUG("Unhandled RC event : 0x%x", event);
|
||||
}
|
||||
@ -1041,7 +1123,7 @@ static void btc_avrc_ct_deinit(void)
|
||||
BTC_TRACE_API("## %s ##", __FUNCTION__);
|
||||
|
||||
if (g_a2dp_on_deinit) {
|
||||
BTC_TRACE_WARNING("A2DP already deinit, AVRC CT shuold deinit in advance of A2DP !!!");
|
||||
BTC_TRACE_WARNING("A2DP already deinit, AVRC CT should deinit in advance of A2DP !!!");
|
||||
}
|
||||
|
||||
if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) {
|
||||
@ -1255,7 +1337,7 @@ static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code
|
||||
BTA_AvRemoteCmd(btc_rc_cb.rc_handle, tl,
|
||||
(tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
|
||||
status = BT_STATUS_SUCCESS;
|
||||
BTC_TRACE_API("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
|
||||
BTC_TRACE_API("%s: successfully sent passthrough command to BTA", __FUNCTION__);
|
||||
} else {
|
||||
status = BT_STATUS_FAIL;
|
||||
BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
|
||||
@ -1267,6 +1349,60 @@ static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code
|
||||
return status;
|
||||
}
|
||||
|
||||
static void btc_avrc_ct_cover_art_connect(UINT16 mtu)
|
||||
{
|
||||
if (!btc_rc_cb.rc_cover_art_connected) {
|
||||
BTA_AvCaOpen(btc_rc_cb.rc_handle, mtu);
|
||||
}
|
||||
else {
|
||||
BTC_TRACE_WARNING("%s: cover art already connected", __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void btc_avrc_ct_cover_art_disconnect(void)
|
||||
{
|
||||
if (btc_rc_cb.rc_cover_art_connected) {
|
||||
BTA_AvCaClose(btc_rc_cb.rc_handle);
|
||||
}
|
||||
else {
|
||||
BTC_TRACE_WARNING("%s: cover art not connected", __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void btc_avrc_ct_cover_art_get_image_properties(UINT8 *image_handle)
|
||||
{
|
||||
if (btc_rc_cb.rc_cover_art_connected) {
|
||||
BTA_AvCaGet(btc_rc_cb.rc_handle, BTA_AV_CA_GET_IMAGE_PROPERTIES, image_handle, NULL, 0);
|
||||
}
|
||||
else {
|
||||
BTC_TRACE_WARNING("%s: cover art not connected", __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void btc_avrc_ct_cover_art_get_image(UINT8 *image_handle, UINT8 *image_descriptor, UINT16 image_descriptor_len)
|
||||
{
|
||||
if (btc_rc_cb.rc_cover_art_connected) {
|
||||
BTA_AvCaGet(btc_rc_cb.rc_handle, BTA_AV_CA_GET_IMAGE, image_handle, image_descriptor, image_descriptor_len);
|
||||
}
|
||||
else {
|
||||
BTC_TRACE_WARNING("%s: cover art not connected", __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void btc_avrc_ct_cover_art_get_linked_thumbnail(UINT8 *image_handle)
|
||||
{
|
||||
if (btc_rc_cb.rc_cover_art_connected) {
|
||||
BTA_AvCaGet(btc_rc_cb.rc_handle, BTA_AV_CA_GET_LINKED_THUMBNAIL, image_handle, NULL, 0);
|
||||
}
|
||||
else {
|
||||
BTC_TRACE_WARNING("%s: cover art not connected", __FUNCTION__);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -1298,7 +1434,7 @@ static void btc_avrc_tg_init(void)
|
||||
}
|
||||
|
||||
if (g_a2dp_on_init) {
|
||||
BTC_TRACE_WARNING("AVRC Taget is expected to be initialized in advance of A2DP !!!");
|
||||
BTC_TRACE_WARNING("AVRC Target is expected to be initialized in advance of A2DP !!!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1320,7 +1456,7 @@ static void btc_avrc_tg_deinit(void)
|
||||
BTC_TRACE_API("## %s ##", __FUNCTION__);
|
||||
|
||||
if (g_a2dp_on_deinit) {
|
||||
BTC_TRACE_WARNING("A2DP already deinit, AVRC TG shuold deinit in advance of A2DP !!!");
|
||||
BTC_TRACE_WARNING("A2DP already deinit, AVRC TG should deinit in advance of A2DP !!!");
|
||||
}
|
||||
|
||||
if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) {
|
||||
@ -1418,6 +1554,26 @@ void btc_avrc_ct_call_handler(btc_msg_t *msg)
|
||||
btc_avrc_ct_send_set_absolute_volume_cmd(arg->set_abs_vol_cmd.tl, arg->set_abs_vol_cmd.volume);
|
||||
break;
|
||||
}
|
||||
case BTC_AVRC_CT_API_COVER_ART_CONNECT_EVT: {
|
||||
btc_avrc_ct_cover_art_connect(arg->ca_conn.mtu);
|
||||
break;
|
||||
}
|
||||
case BTC_AVRC_CT_API_COVER_ART_DISCONNECT_EVT: {
|
||||
btc_avrc_ct_cover_art_disconnect();
|
||||
break;
|
||||
}
|
||||
case BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_PROPERTIES_EVT: {
|
||||
btc_avrc_ct_cover_art_get_image_properties(arg->ca_get_img_prop.image_handle);
|
||||
break;
|
||||
}
|
||||
case BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT: {
|
||||
btc_avrc_ct_cover_art_get_image(arg->ca_get_img.image_handle, arg->ca_get_img.image_descriptor, arg->ca_get_img.image_descriptor_len);
|
||||
break;
|
||||
}
|
||||
case BTC_AVRC_CT_API_COVER_ART_GET_LINKED_THUMBNAIL_EVT: {
|
||||
btc_avrc_ct_cover_art_get_linked_thumbnail(arg->ca_get_lk_thn.image_handle);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act);
|
||||
}
|
||||
|
@ -39,7 +39,12 @@ typedef enum {
|
||||
BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT,
|
||||
BTC_AVRC_NOTIFY_API_SND_REG_NOTIFY_EVT,
|
||||
BTC_AVRC_CTRL_API_SND_SET_PLAYER_SETTING_EVT,
|
||||
BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT
|
||||
BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT,
|
||||
BTC_AVRC_CT_API_COVER_ART_CONNECT_EVT,
|
||||
BTC_AVRC_CT_API_COVER_ART_DISCONNECT_EVT,
|
||||
BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_PROPERTIES_EVT,
|
||||
BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT,
|
||||
BTC_AVRC_CT_API_COVER_ART_GET_LINKED_THUMBNAIL_EVT,
|
||||
} btc_avrc_act_t;
|
||||
|
||||
typedef struct {
|
||||
@ -77,6 +82,24 @@ typedef struct {
|
||||
uint8_t volume;
|
||||
} set_abs_vol_cmd_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t mtu;
|
||||
} ca_conn_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t image_handle[7];
|
||||
} ca_get_img_prop_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t image_handle[7];
|
||||
uint16_t image_descriptor_len;
|
||||
uint8_t *image_descriptor;
|
||||
} ca_get_img_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t image_handle[7];
|
||||
} ca_get_lk_thn_t;
|
||||
|
||||
/* btc_avrc_args_t */
|
||||
typedef union {
|
||||
pt_cmd_t pt_cmd;
|
||||
@ -85,6 +108,10 @@ typedef union {
|
||||
ps_cmd_t ps_cmd;
|
||||
get_caps_cmd_t get_caps_cmd;
|
||||
set_abs_vol_cmd_t set_abs_vol_cmd;
|
||||
ca_conn_t ca_conn;
|
||||
ca_get_img_prop_t ca_get_img_prop;
|
||||
ca_get_img_t ca_get_img;
|
||||
ca_get_lk_thn_t ca_get_lk_thn;
|
||||
} btc_avrc_args_t;
|
||||
|
||||
/* btc_avrc_tg_act_t */
|
||||
@ -124,6 +151,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
BOOLEAN rc_connected;
|
||||
BOOLEAN rc_cover_art_connected;
|
||||
UINT8 rc_handle;
|
||||
tBTA_AV_FEAT rc_features;
|
||||
UINT16 rc_ct_features;
|
||||
@ -162,6 +190,8 @@ BOOLEAN btc_rc_get_connected_peer(BD_ADDR peer_addr);
|
||||
********************************************************************************/
|
||||
void btc_avrc_ct_call_handler(btc_msg_t *msg);
|
||||
void btc_avrc_tg_call_handler(btc_msg_t *msg);
|
||||
void btc_avrc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
void btc_avrc_arg_deep_free(btc_msg_t *msg);
|
||||
void btc_avrc_tg_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
void btc_avrc_tg_arg_deep_free(btc_msg_t *msg);
|
||||
|
||||
@ -179,6 +209,7 @@ uint16_t btc_avrc_tg_get_rn_supported_evt(void);
|
||||
bool btc_avrc_tg_check_rn_supported_evt(uint16_t evt_set);
|
||||
bool btc_avrc_tg_rn_evt_supported(uint8_t event_id);
|
||||
bool btc_avrc_ct_rn_evt_supported(uint8_t event_id);
|
||||
bool btc_avrc_ct_check_cover_art_support(void);
|
||||
|
||||
#endif ///BTC_AV_INCLUDED == TRUE
|
||||
|
||||
|
@ -171,6 +171,9 @@
|
||||
#define BTC_HD_INCLUDED TRUE
|
||||
#endif /* UC_BT_HID_DEVICE_ENABLED */
|
||||
|
||||
#define OBEX_INCLUDED TRUE
|
||||
#define GOEPC_INCLUDED TRUE
|
||||
|
||||
#endif /* UC_BT_CLASSIC_ENABLED */
|
||||
|
||||
/* This is set to enable use of GAP L2CAP connections. */
|
||||
@ -2161,6 +2164,20 @@
|
||||
#define HID_HOST_REPAGE_WIN (2)
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
** Definitions for OBEX
|
||||
*/
|
||||
#ifndef OBEX_INCLUDED
|
||||
#define OBEX_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
** Definitions for OBEX
|
||||
*/
|
||||
#ifndef GOEPC_INCLUDED
|
||||
#define GOEPC_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* A2DP Definitions
|
||||
*/
|
||||
|
@ -316,6 +316,27 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l
|
||||
#define AVRC_TRACE_EVENT(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("BT_AVRC", fmt, ## args);}
|
||||
#define AVRC_TRACE_DEBUG(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("BT_AVRC", fmt, ## args);}
|
||||
|
||||
/* Define tracing for OBEX */
|
||||
#define OBEX_TRACE_ERROR(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVRC, ERROR)) BT_PRINT_E("BT_OBEX", fmt, ## args);}
|
||||
#define OBEX_TRACE_WARNING(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVRC, WARNING)) BT_PRINT_W("BT_OBEX", fmt, ## args);}
|
||||
#define OBEX_TRACE_API(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVRC,API)) BT_PRINT_I("BT_OBEX", fmt, ## args);}
|
||||
#define OBEX_TRACE_EVENT(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("BT_OBEX", fmt, ## args);}
|
||||
#define OBEX_TRACE_DEBUG(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("BT_OBEX", fmt, ## args);}
|
||||
|
||||
/* Define tracing for OBEX_TL_L2CAP */
|
||||
#define OBEX_TL_L2CAP_TRACE_ERROR(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVRC, ERROR)) BT_PRINT_E("OBEX_TL_L2CAP", fmt, ## args);}
|
||||
#define OBEX_TL_L2CAP_TRACE_WARNING(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVRC, WARNING)) BT_PRINT_W("OBEX_TL_L2CAP", fmt, ## args);}
|
||||
#define OBEX_TL_L2CAP_TRACE_API(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVRC,API)) BT_PRINT_I("OBEX_TL_L2CAP", fmt, ## args);}
|
||||
#define OBEX_TL_L2CAP_TRACE_EVENT(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("OBEX_TL_L2CAP", fmt, ## args);}
|
||||
#define OBEX_TL_L2CAP_TRACE_DEBUG(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("OBEX_TL_L2CAP", fmt, ## args);}
|
||||
|
||||
/* Define tracing for GOEPC */
|
||||
#define GOEPC_TRACE_ERROR(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVRC, ERROR)) BT_PRINT_E("BT_GOEPC", fmt, ## args);}
|
||||
#define GOEPC_TRACE_WARNING(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVRC, WARNING)) BT_PRINT_W("BT_GOEPC", fmt, ## args);}
|
||||
#define GOEPC_TRACE_API(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVRC,API)) BT_PRINT_I("BT_GOEPC", fmt, ## args);}
|
||||
#define GOEPC_TRACE_EVENT(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("BT_GOEPC", fmt, ## args);}
|
||||
#define GOEPC_TRACE_DEBUG(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("BT_GOEPC", fmt, ## args);}
|
||||
|
||||
/* MCAP
|
||||
*/
|
||||
#define MCA_TRACE_ERROR(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(MCA, ERROR)) BT_PRINT_E("BT_MCA", fmt, ## args);}
|
||||
@ -484,6 +505,26 @@ extern UINT8 btif_trace_level;
|
||||
#define AVRC_TRACE_DEBUG(fmt, args...)
|
||||
#define AVRC_TRACE_API(fmt, args...)
|
||||
|
||||
/* Define tracing for OBEX */
|
||||
#define OBEX_TRACE_ERROR(fmt, args...)
|
||||
#define OBEX_TRACE_WARNING(fmt, args...)
|
||||
#define OBEX_TRACE_API(fmt, args...)
|
||||
#define OBEX_TRACE_EVENT(fmt, args...)
|
||||
#define OBEX_TRACE_DEBUG(fmt, args...)
|
||||
|
||||
#define OBEX_TL_L2CAP_TRACE_ERROR(fmt, args...)
|
||||
#define OBEX_TL_L2CAP_TRACE_WARNING(fmt, args...)
|
||||
#define OBEX_TL_L2CAP_TRACE_API(fmt, args...)
|
||||
#define OBEX_TL_L2CAP_TRACE_EVENT(fmt, args...)
|
||||
#define OBEX_TL_L2CAP_TRACE_DEBUG(fmt, args...)
|
||||
|
||||
/* Define tracing for GOEPC */
|
||||
#define GOEPC_TRACE_ERROR(fmt, args...)
|
||||
#define GOEPC_TRACE_WARNING(fmt, args...)
|
||||
#define GOEPC_TRACE_API(fmt, args...)
|
||||
#define GOEPC_TRACE_EVENT(fmt, args...)
|
||||
#define GOEPC_TRACE_DEBUG(fmt, args...)
|
||||
|
||||
/* MCAP
|
||||
*/
|
||||
#define MCA_TRACE_ERROR(fmt, args...)
|
||||
|
@ -27,8 +27,8 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Stack Configuation Related Init Definaton
|
||||
* TODO: Now Just Unmask these defination until stack layer is OK
|
||||
/* Stack Configuration Related Init Definaton
|
||||
* TODO: Now Just Unmask these definition until stack layer is OK
|
||||
*/
|
||||
|
||||
#ifndef BTA_INCLUDED
|
||||
@ -91,6 +91,15 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(OBEX_INCLUDED) && OBEX_INCLUDED == TRUE)
|
||||
#include "stack/obex_api.h"
|
||||
#endif
|
||||
|
||||
#if (defined(GOEPC_INCLUDED) && GOEPC_INCLUDED == TRUE)
|
||||
#include "stack/goep_common.h"
|
||||
#include "stack/goepc_api.h"
|
||||
#endif
|
||||
|
||||
//BTA Modules
|
||||
#if BTA_INCLUDED == TRUE && BTA_DYNAMIC_MEMORY == TRUE
|
||||
#include "bta/bta_api.h"
|
||||
@ -267,6 +276,14 @@ void BTE_DeinitStack(void)
|
||||
}
|
||||
#endif // BTA_INCLUDED == TRUE
|
||||
|
||||
#if (defined(GOEPC_INCLUDED) && GOEPC_INCLUDED == TRUE)
|
||||
GOEPC_Deinit();
|
||||
#endif
|
||||
|
||||
#if (defined(OBEX_INCLUDED) && OBEX_INCLUDED == TRUE)
|
||||
OBEX_Deinit();
|
||||
#endif
|
||||
|
||||
#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE)
|
||||
HID_DevDeinit();
|
||||
#endif
|
||||
@ -388,6 +405,18 @@ bt_status_t BTE_InitStack(void)
|
||||
MCA_Init();
|
||||
#endif
|
||||
|
||||
#if (defined(OBEX_INCLUDED) && OBEX_INCLUDED == TRUE)
|
||||
if (OBEX_Init() != OBEX_SUCCESS) {
|
||||
goto error_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(GOEPC_INCLUDED) && GOEPC_INCLUDED == TRUE)
|
||||
if (GOEPC_Init() != GOEP_SUCCESS) {
|
||||
goto error_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
//BTA Modules
|
||||
#if (BTA_INCLUDED == TRUE && BTA_DYNAMIC_MEMORY == TRUE)
|
||||
if ((bta_sys_cb_ptr = (tBTA_SYS_CB *)osi_malloc(sizeof(tBTA_SYS_CB))) == NULL) {
|
||||
|
@ -29,8 +29,8 @@
|
||||
|
||||
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
|
||||
|
||||
#ifndef SDP_AVRCP_1_5
|
||||
#define SDP_AVRCP_1_5 TRUE
|
||||
#ifndef SDP_AVRCP_1_6
|
||||
#define SDP_AVRCP_1_6 TRUE
|
||||
#endif
|
||||
|
||||
#ifndef SDP_AVCTP_1_4
|
||||
@ -52,7 +52,7 @@ const tSDP_PROTOCOL_ELEM avrc_proto_list [] = {
|
||||
#if SDP_AVCTP_1_4 == TRUE
|
||||
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_4, 0} }
|
||||
#else
|
||||
#if (SDP_AVRCP_1_4 == TRUE || SDP_AVRCP_1_5 == TRUE)
|
||||
#if SDP_AVRCP_1_6 == TRUE
|
||||
{UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_3, 0} }
|
||||
#else
|
||||
#if AVRC_METADATA_INCLUDED == TRUE
|
||||
@ -64,7 +64,7 @@ const tSDP_PROTOCOL_ELEM avrc_proto_list [] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#if SDP_AVRCP_1_5 == TRUE
|
||||
#if SDP_AVRCP_1_6 == TRUE
|
||||
const tSDP_PROTO_LIST_ELEM avrc_add_proto_list [] = {
|
||||
{
|
||||
AVRC_NUM_PROTO_ELEMS,
|
||||
@ -251,7 +251,7 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provide
|
||||
|
||||
/* add service class id list */
|
||||
class_list[0] = service_uuid;
|
||||
#if (SDP_AVCTP_1_4 == TRUE || SDP_AVRCP_1_5 == TRUE)
|
||||
#if (SDP_AVCTP_1_4 == TRUE || SDP_AVRCP_1_6 == TRUE)
|
||||
if ( service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL ) {
|
||||
class_list[1] = UUID_SERVCLASS_AV_REM_CTRL_CONTROL;
|
||||
count = 2;
|
||||
@ -263,7 +263,7 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provide
|
||||
result &= SDP_AddProtocolList(sdp_handle, AVRC_NUM_PROTO_ELEMS, (tSDP_PROTOCOL_ELEM *)avrc_proto_list);
|
||||
|
||||
/* add profile descriptor list */
|
||||
#if SDP_AVRCP_1_5 == TRUE
|
||||
#if SDP_AVRCP_1_6 == TRUE
|
||||
if (browsing_en) {
|
||||
add_additional_protocol_list = TRUE;
|
||||
} else if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET &&
|
||||
@ -277,7 +277,7 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provide
|
||||
result &= SDP_AddAdditionProtoLists( sdp_handle, 1, (tSDP_PROTO_LIST_ELEM *)avrc_add_proto_list);
|
||||
}
|
||||
|
||||
result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_5);
|
||||
result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_6);
|
||||
#else
|
||||
#if AVRC_METADATA_INCLUDED == TRUE
|
||||
result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_3);
|
||||
@ -292,6 +292,13 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provide
|
||||
} else if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET && media_player_virtual_filesystem_supported) {
|
||||
supported_feature |= AVRC_SUPF_TG_BROWSE;
|
||||
}
|
||||
|
||||
if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_CONTROL || service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL) {
|
||||
supported_feature |= AVRC_SUPF_CT_COVER_ART_GIP;
|
||||
supported_feature |= AVRC_SUPF_CT_COVER_ART_GI;
|
||||
supported_feature |= AVRC_SUPF_CT_COVER_ART_GLT;
|
||||
}
|
||||
|
||||
/* add supported feature */
|
||||
p = temp;
|
||||
UINT16_TO_BE_STREAM(p, supported_feature);
|
||||
@ -383,7 +390,7 @@ bt_status_t AVRC_Init(void)
|
||||
**
|
||||
** Function AVRC_Deinit
|
||||
**
|
||||
** Description This function is called at stack shotdown to free the
|
||||
** Description This function is called at stack shutdown to free the
|
||||
** control block (if using dynamic memory), and deinitializes the
|
||||
** control block and tracing level.
|
||||
**
|
||||
|
@ -99,6 +99,9 @@
|
||||
#define AVRC_SUPF_CT_CAT3 0x0004 /* Category 3 */
|
||||
#define AVRC_SUPF_CT_CAT4 0x0008 /* Category 4 */
|
||||
#define AVRC_SUPF_CT_BROWSE 0x0040 /* Browsing */
|
||||
#define AVRC_SUPF_CT_COVER_ART_GIP 0x0080 /* Cover Art GetImageProperties */
|
||||
#define AVRC_SUPF_CT_COVER_ART_GI 0x0100 /* Cover Art GetImage */
|
||||
#define AVRC_SUPF_CT_COVER_ART_GLT 0x0200 /* Cover Art GetLinkedThumbnail */
|
||||
|
||||
#define AVRC_SUPF_TG_CAT1 0x0001 /* Category 1 */
|
||||
#define AVRC_SUPF_TG_CAT2 0x0002 /* Category 2 */
|
||||
@ -107,7 +110,8 @@
|
||||
#define AVRC_SUPF_TG_APP_SETTINGS 0x0010 /* Player Application Settings */
|
||||
#define AVRC_SUPF_TG_GROUP_NAVI 0x0020 /* Group Navigation */
|
||||
#define AVRC_SUPF_TG_BROWSE 0x0040 /* Browsing */
|
||||
#define AVRC_SUPF_TG_MULTI_PLAYER 0x0080 /* Muliple Media Player */
|
||||
#define AVRC_SUPF_TG_MULTI_PLAYER 0x0080 /* Multiple Media Player */
|
||||
#define AVRC_SUPF_TG_COVER_ART 0x0100 /* Cover Art */
|
||||
|
||||
#define AVRC_META_SUCCESS AVRC_SUCCESS
|
||||
#define AVRC_META_FAIL AVRC_FAIL
|
||||
@ -561,7 +565,7 @@ extern bt_status_t AVRC_Init(void);
|
||||
**
|
||||
** Function AVRC_Deinit
|
||||
**
|
||||
** Description This function is called at stack shotdown to free the
|
||||
** Description This function is called at stack shutdown to free the
|
||||
** control block (if using dynamic memory), and deinitializes the
|
||||
** control block and tracing level.
|
||||
**
|
||||
|
@ -35,6 +35,7 @@
|
||||
#define AVRC_REV_1_3 0x0103
|
||||
#define AVRC_REV_1_4 0x0104
|
||||
#define AVRC_REV_1_5 0x0105
|
||||
#define AVRC_REV_1_6 0x0106
|
||||
|
||||
#define AVRC_PACKET_LEN 512 /* Per the spec, you must support 512 byte RC packets */
|
||||
|
||||
@ -185,7 +186,7 @@
|
||||
#define AVRC_PKT_END 3
|
||||
#define AVRC_PKT_TYPE_MASK 3
|
||||
|
||||
/* Define the PDUs carried in the vendor dependant data
|
||||
/* Define the PDUs carried in the vendor dependent data
|
||||
*/
|
||||
#define AVRC_PDU_GET_CAPABILITIES 0x10
|
||||
#define AVRC_PDU_LIST_PLAYER_APP_ATTR 0x11
|
||||
@ -297,7 +298,7 @@ typedef UINT8 tAVRC_BATTERY_STATUS;
|
||||
#define AVRC_MEDIA_ATTR_ID_TRACK_NUM 0x00000004
|
||||
#define AVRC_MEDIA_ATTR_ID_NUM_TRACKS 0x00000005
|
||||
#define AVRC_MEDIA_ATTR_ID_GENRE 0x00000006
|
||||
#define AVRC_MEDIA_ATTR_ID_PLAYING_TIME 0x00000007 /* in miliseconds */
|
||||
#define AVRC_MEDIA_ATTR_ID_PLAYING_TIME 0x00000007 /* in milliseconds */
|
||||
#define AVRC_MAX_NUM_MEDIA_ATTR_ID 7
|
||||
|
||||
/* Define the possible values of play state
|
||||
|
@ -45,6 +45,8 @@
|
||||
#define HCRP_DYNAMIC_MEMORY TRUE
|
||||
#define HFP_DYNAMIC_MEMORY TRUE
|
||||
#define HID_DYNAMIC_MEMORY TRUE
|
||||
#define OBEX_DYNAMIC_MEMORY TRUE
|
||||
#define GOEP_DYNAMIC_MEMORY TRUE
|
||||
#define HSP2_DYNAMIC_MEMORY TRUE
|
||||
#define ICP_DYNAMIC_MEMORY TRUE
|
||||
#define OPP_DYNAMIC_MEMORY TRUE
|
||||
@ -79,6 +81,8 @@
|
||||
#define HCRP_DYNAMIC_MEMORY FALSE
|
||||
#define HFP_DYNAMIC_MEMORY FALSE
|
||||
#define HID_DYNAMIC_MEMORY FALSE
|
||||
#define OBEX_DYNAMIC_MEMORY FALSE
|
||||
#define GOEP_DYNAMIC_MEMORY FALSE
|
||||
#define HSP2_DYNAMIC_MEMORY FALSE
|
||||
#define ICP_DYNAMIC_MEMORY FALSE
|
||||
#define OPP_DYNAMIC_MEMORY FALSE
|
||||
@ -191,6 +195,14 @@
|
||||
#define HID_DYNAMIC_MEMORY FALSE
|
||||
#endif
|
||||
|
||||
#ifndef OBEX_DYNAMIC_MEMORY
|
||||
#define OBEX_DYNAMIC_MEMORY FALSE
|
||||
#endif
|
||||
|
||||
#ifndef GOEP_DYNAMIC_MEMORY
|
||||
#define GOEP_DYNAMIC_MEMORY FALSE
|
||||
#endif
|
||||
|
||||
#ifndef HSP2_DYNAMIC_MEMORY
|
||||
#define HSP2_DYNAMIC_MEMORY FALSE
|
||||
#endif
|
||||
|
@ -365,6 +365,20 @@ extern BOOLEAN SDP_FindProtocolListElemInRec (tSDP_DISC_REC *p_rec,
|
||||
UINT16 layer_uuid,
|
||||
tSDP_PROTOCOL_ELEM *p_elem);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SDP_FindProtocolListElem
|
||||
**
|
||||
** Description This function looks at the protocol list for a specific protocol
|
||||
** list element.
|
||||
**
|
||||
** Returns TRUE if found, FALSE if not
|
||||
** If found, the passed protocol list element is filled in.
|
||||
**
|
||||
*******************************************************************************/
|
||||
extern BOOLEAN SDP_FindProtocolListElem (tSDP_DISC_ATTR *p_protocol_list,
|
||||
UINT16 layer_uuid,
|
||||
tSDP_PROTOCOL_ELEM *p_elem);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -409,7 +423,7 @@ extern BOOLEAN SDP_FindProfileVersionInRec (tSDP_DISC_REC *p_rec,
|
||||
**
|
||||
** Description This function is called to create a record in the database.
|
||||
** This would be through the SDP database maintenance API. The
|
||||
** record is created empty, teh application should then call
|
||||
** record is created empty, the application should then call
|
||||
** "add_attribute" to add the record's attributes.
|
||||
**
|
||||
** Returns Record handle if OK, else 0.
|
||||
|
@ -372,7 +372,7 @@ BOOLEAN SDP_FindServiceUUIDInRec(tSDP_DISC_REC *p_rec, tBT_UUID *p_uuid)
|
||||
if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE) {
|
||||
/* Look through data element sequence until no more UUIDs */
|
||||
for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr; p_extra_sattr; p_extra_sattr = p_extra_sattr->p_next_attr) {
|
||||
/* Increment past this to see if the next attribut is UUID */
|
||||
/* Increment past this to see if the next attribute is UUID */
|
||||
if ((SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) == UUID_DESC_TYPE)
|
||||
/* only support 16 bits UUID for now */
|
||||
&& (SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2)) {
|
||||
@ -522,7 +522,7 @@ tSDP_DISC_REC *SDP_FindServiceInDb (tSDP_DISCOVERY_DB *p_db, UINT16 service_uuid
|
||||
if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE) {
|
||||
/* Look through data element sequence until no more UUIDs */
|
||||
for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr; p_extra_sattr; p_extra_sattr = p_extra_sattr->p_next_attr) {
|
||||
/* Increment past this to see if the next attribut is UUID */
|
||||
/* Increment past this to see if the next attribute is UUID */
|
||||
if ((SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) == UUID_DESC_TYPE)
|
||||
&& (SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2)
|
||||
/* for a specific uuid, or any one */
|
||||
@ -768,6 +768,28 @@ BOOLEAN SDP_FindProtocolListElemInRec (tSDP_DISC_REC *p_rec, UINT16 layer_uuid,
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function SDP_FindProtocolListElem
|
||||
**
|
||||
** Description This function looks at the protocol list for a specific protocol
|
||||
** list element.
|
||||
**
|
||||
** Returns TRUE if found, FALSE if not
|
||||
** If found, the passed protocol list element is filled in.
|
||||
**
|
||||
*******************************************************************************/
|
||||
BOOLEAN SDP_FindProtocolListElem (tSDP_DISC_ATTR *p_protocol_list, UINT16 layer_uuid, tSDP_PROTOCOL_ELEM *p_elem)
|
||||
{
|
||||
#if SDP_CLIENT_ENABLED == TRUE
|
||||
/* don't check the input protocol descriptor list id, this api may be use in additional protocol descriptor list */
|
||||
if ((SDP_DISC_ATTR_TYPE(p_protocol_list->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) {
|
||||
return sdp_fill_proto_elem(p_protocol_list, layer_uuid, p_elem);
|
||||
}
|
||||
#endif
|
||||
/* If here, no match found */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
Loading…
Reference in New Issue
Block a user