component/bt: clean up AVRCP API and example code
This commit is contained in:
parent
49b68c38fa
commit
36a74daa0a
4 changed files with 254 additions and 206 deletions
121
components/bt/bluedroid/api/include/esp_avrc_api.h
Executable file
121
components/bt/bluedroid/api/include/esp_avrc_api.h
Executable file
|
@ -0,0 +1,121 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __ESP_AVRC_API_H__
|
||||
#define __ESP_AVRC_API_H__
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_bt_defs.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/// AVRC feature bit mask
|
||||
typedef enum {
|
||||
ESP_AVRC_FEAT_RCTG = 0x0001, /*!< remote control target */
|
||||
ESP_AVRC_FEAT_RCCT = 0x0002, /*!< remote control controller */
|
||||
ESP_AVRC_FEAT_VENDOR = 0x0008, /*!< remote control vendor dependent commands */
|
||||
ESP_AVRC_FEAT_BROWSE = 0x0010, /*!< use browsing channel */
|
||||
ESP_AVRC_FEAT_META_DATA = 0x0040, /*!< remote control metadata transfer command/response */
|
||||
ESP_AVRC_FEAT_ADV_CTRL = 0x0200, /*!< remote control advanced control commmand/response */
|
||||
} esp_avrc_features_t;
|
||||
|
||||
/// AVRC passthrough command code
|
||||
enum {
|
||||
ESP_AVRC_PT_CMD_PLAY = 0x44, /*!< play */
|
||||
ESP_AVRC_PT_CMD_STOP = 0x45, /*!< stop */
|
||||
ESP_AVRC_PT_CMD_PAUSE = 0x46, /*!< pause */
|
||||
ESP_AVRC_PT_CMD_FORWARD = 0x4B, /*!< forward */
|
||||
ESP_AVRC_PT_CMD_BACKWARD = 0x4C /*!< backward */
|
||||
};
|
||||
|
||||
/// AVRC passthrough command state
|
||||
enum {
|
||||
ESP_AVRC_PT_CMD_STATE_PRESSED = 0, /*!< key pressed */
|
||||
ESP_AVRC_PT_CMD_STATE_RELEASED = 1 /*!< key released */
|
||||
};
|
||||
|
||||
/// AVRC Controller callback events
|
||||
typedef enum {
|
||||
ESP_AVRC_CT_CONNECTION_STATE_EVT = 0, /*!< connection state changed event */
|
||||
ESP_AVRC_CT_PASSTHROUGH_RSP_EVT = 1, /*!< passthrough response event */
|
||||
ESP_AVRC_CT_MAX_EVT
|
||||
} esp_avrc_ct_cb_event_t;
|
||||
|
||||
/// AVRC controller callback parameters
|
||||
typedef union {
|
||||
/*< ESP_AVRC_CT_CONNECTION_STATE_EVT */
|
||||
struct avrc_ct_conn_stat_param {
|
||||
bool connected;
|
||||
uint32_t feat_mask;
|
||||
esp_bd_addr_t remote_bda;
|
||||
} conn_stat;
|
||||
|
||||
/*< ESP_AVRC_CT_PASSTHROUGH_RSP_EVT */
|
||||
struct avrc_ct_psth_rsp_param {
|
||||
uint8_t tl; /*!< transaction label, 0 to 15 */
|
||||
uint8_t key_code;
|
||||
uint8_t key_state; /*!< 0 for */
|
||||
} psth_rsp;
|
||||
} esp_avrc_ct_cb_param_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief AVRCP controler callback function type
|
||||
* @param event : Event type
|
||||
* @param param : Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (* esp_avrc_ct_cb_t)(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param);
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function is called to register application callbacks
|
||||
* to AVRCP module; callbacks will provide the upstream events
|
||||
* (type esp_avrc_ct_cb_event_t) and paramters(type esp_avrc_ct_cb_param_t)
|
||||
*
|
||||
* @param[in] callback: A2DP sink event callback function
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_FAIL: others
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_avrc_ct_register_callback(esp_avrc_ct_cb_t callback);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief This function is called to initialize the bluetooth AVRCP controller module
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_FAIL: others
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_avrc_ct_init(void);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief This function is called to deinit AVRCP controller module
|
||||
*
|
||||
*/
|
||||
void esp_avrc_ct_deinit(void);
|
||||
|
||||
|
||||
/**
|
||||
* send pass through command to target
|
||||
*/
|
||||
esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state);
|
||||
|
||||
#endif /* __ESP_AVRC_API_H__ */
|
|
@ -38,6 +38,7 @@
|
|||
#include "btif_av.h"
|
||||
#include "bt_rc.h"
|
||||
#include "uinput.h"
|
||||
#include "esp_avrc_api.h"
|
||||
|
||||
/*****************************************************************************
|
||||
** Constants & Macros
|
||||
|
@ -70,6 +71,14 @@
|
|||
return BT_STATUS_NOT_READY; \
|
||||
}
|
||||
|
||||
#define CHECK_ESP_RC_CONNECTED do { \
|
||||
BTIF_TRACE_DEBUG("## %s ##", __FUNCTION__); \
|
||||
if (btif_rc_cb.rc_connected == FALSE) { \
|
||||
BTIF_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \
|
||||
return ESP_ERR_INVALID_STATE; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FILL_PDU_QUEUE(index, ctype, label, pending) \
|
||||
{ \
|
||||
btif_rc_cb.rc_pdu_info[index].ctype = ctype; \
|
||||
|
@ -187,7 +196,15 @@ static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp,
|
|||
******************************************************************************/
|
||||
static btif_rc_cb_t btif_rc_cb;
|
||||
static btrc_callbacks_t *bt_rc_callbacks = NULL;
|
||||
static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
|
||||
// static btrc_ctrl_callbacks_t *bt_rc_ctrl_callbacks = NULL;
|
||||
static esp_avrc_ct_cb_t bt_rc_ctrl_callback = NULL;
|
||||
|
||||
// TODO: need protection against race
|
||||
#define BTIF_AVRC_CT_CB_TO_APP(_event, _param) do { \
|
||||
if (bt_rc_ctrl_callback) { \
|
||||
bt_rc_ctrl_callback(_event, _param); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*****************************************************************************
|
||||
** Static functions
|
||||
|
@ -372,15 +389,16 @@ void handle_rc_features()
|
|||
}
|
||||
|
||||
BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features);
|
||||
HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
|
||||
|
||||
// todo: uncomment the following line when added the AVRC target role
|
||||
// HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features)
|
||||
|
||||
#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
|
||||
BTIF_TRACE_DEBUG("Checking for feature flags in btif_rc_handler with label %d",
|
||||
btif_rc_cb.rc_vol_label);
|
||||
// Register for volume change on connect
|
||||
if(btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
|
||||
btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
|
||||
{
|
||||
if(btif_rc_cb.rc_features & BTA_AV_FEAT_ADV_CTRL &&
|
||||
btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
|
||||
{
|
||||
rc_transaction_t *p_transaction=NULL;
|
||||
bt_status_t status = BT_STATUS_NOT_READY;
|
||||
if(MAX_LABEL==btif_rc_cb.rc_vol_label)
|
||||
|
@ -405,7 +423,7 @@ void handle_rc_features()
|
|||
btif_rc_cb.rc_vol_label=p_transaction->lbl;
|
||||
register_volumechange(btif_rc_cb.rc_vol_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -461,9 +479,12 @@ void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open)
|
|||
bdcpy(rc_addr.address, btif_rc_cb.rc_addr);
|
||||
/* report connection state if device is AVRCP target */
|
||||
if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG) {
|
||||
if (bt_rc_ctrl_callbacks != NULL) {
|
||||
HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, TRUE, &rc_addr);
|
||||
}
|
||||
esp_avrc_ct_cb_param_t param;
|
||||
memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t));
|
||||
param.conn_stat.connected = true;
|
||||
param.conn_stat.feat_mask = btif_rc_cb.rc_features;
|
||||
memcpy(param.conn_stat.remote_bda, &rc_addr, sizeof(esp_bd_addr_t));
|
||||
BTIF_AVRC_CT_CB_TO_APP(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -518,9 +539,11 @@ void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close)
|
|||
#if (AVRC_CTLR_INCLUDED == TRUE)
|
||||
/* report connection state if device is AVRCP target */
|
||||
if (features & BTA_AV_FEAT_RCTG) {
|
||||
if (bt_rc_ctrl_callbacks != NULL) {
|
||||
HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, FALSE, &rc_addr);
|
||||
}
|
||||
esp_avrc_ct_cb_param_t param;
|
||||
memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t));
|
||||
param.conn_stat.connected = false;
|
||||
memcpy(param.conn_stat.remote_bda, &rc_addr, sizeof(esp_bd_addr_t));
|
||||
BTIF_AVRC_CT_CB_TO_APP(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -663,10 +686,14 @@ void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp)
|
|||
|
||||
BTIF_TRACE_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status);
|
||||
|
||||
release_transaction(p_remote_rsp->label);
|
||||
if (bt_rc_ctrl_callbacks != NULL) {
|
||||
HAL_CBACK(bt_rc_ctrl_callbacks, passthrough_rsp_cb, p_remote_rsp->rc_id, key_state);
|
||||
}
|
||||
do {
|
||||
esp_avrc_ct_cb_param_t param;
|
||||
memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t));
|
||||
param.psth_rsp.tl = p_remote_rsp->label;
|
||||
param.psth_rsp.key_code = p_remote_rsp->rc_id;
|
||||
param.psth_rsp.key_state = key_state;
|
||||
BTIF_AVRC_CT_CB_TO_APP(ESP_AVRC_CT_PASSTHROUGH_RSP_EVT, ¶m);
|
||||
} while (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -784,8 +811,8 @@ void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
|
|||
__FUNCTION__, dump_rc_pdu(avrc_command.cmd.pdu));
|
||||
|
||||
/* Since handle_rc_metamsg_cmd() itself is called from
|
||||
*btif context, no context switching is required. Invoke
|
||||
* btif_rc_upstreams_evt directly from here. */
|
||||
* btif context, no context switching is required. Invoke
|
||||
* btif_rc_upstreams_evt directly from here. */
|
||||
btif_rc_upstreams_evt((uint16_t)avrc_command.cmd.pdu, &avrc_command, pmeta_msg->code,
|
||||
pmeta_msg->label);
|
||||
}
|
||||
|
@ -800,7 +827,7 @@ void handle_rc_metamsg_cmd (tBTA_AV_META_MSG *pmeta_msg)
|
|||
***************************************************************************/
|
||||
void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data)
|
||||
{
|
||||
BTIF_TRACE_EVENT ("%s event:%s", __FUNCTION__, dump_rc_event(event));
|
||||
BTIF_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event));
|
||||
switch (event)
|
||||
{
|
||||
case BTA_AV_RC_OPEN_EVT:
|
||||
|
@ -1267,25 +1294,40 @@ static bt_status_t init(btrc_callbacks_t* callbacks )
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function init_ctrl
|
||||
** Function esp_avrc_ct_register_callback
|
||||
**
|
||||
** Description Register AVRCP controller callback function
|
||||
**
|
||||
** Returns esp_err_t
|
||||
**
|
||||
*******************************************************************************/
|
||||
esp_err_t esp_avrc_ct_register_callback(esp_avrc_ct_cb_t callback)
|
||||
{
|
||||
if (bt_rc_ctrl_callback)
|
||||
return ESP_FAIL;
|
||||
|
||||
bt_rc_ctrl_callback = callback;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function esp_avrc_ct_init
|
||||
**
|
||||
** Description Initializes the AVRC interface
|
||||
**
|
||||
** Returns bt_status_t
|
||||
** Returns esp_err_t
|
||||
**
|
||||
*******************************************************************************/
|
||||
// static bt_status_t init_ctrl(btrc_ctrl_callbacks_t* callbacks )
|
||||
bt_status_t btrc_ctrl_init(btrc_ctrl_callbacks_t *callbacks)
|
||||
esp_err_t esp_avrc_ct_init(void)
|
||||
{
|
||||
BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
|
||||
bt_status_t result = BT_STATUS_SUCCESS;
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
if (bt_rc_ctrl_callbacks)
|
||||
return BT_STATUS_DONE;
|
||||
|
||||
bt_rc_ctrl_callbacks = callbacks;
|
||||
memset (&btif_rc_cb, 0, sizeof(btif_rc_cb));
|
||||
btif_rc_cb.rc_vol_label=MAX_LABEL;
|
||||
btif_rc_cb.rc_volume=MAX_VOLUME;
|
||||
|
@ -1647,56 +1689,54 @@ static void cleanup()
|
|||
** Returns void
|
||||
**
|
||||
***************************************************************************/
|
||||
void btrc_ctrl_cleanup(void)
|
||||
// static void cleanup_ctrl()
|
||||
void esp_avrc_ct_deinit(void)
|
||||
{
|
||||
BTIF_TRACE_EVENT("## %s ##", __FUNCTION__);
|
||||
|
||||
if (bt_rc_ctrl_callbacks)
|
||||
if (bt_rc_ctrl_callback)
|
||||
{
|
||||
bt_rc_ctrl_callbacks = NULL;
|
||||
bt_rc_ctrl_callback = NULL;
|
||||
}
|
||||
memset(&btif_rc_cb, 0, sizeof(btif_rc_cb_t));
|
||||
lbl_destroy();
|
||||
BTIF_TRACE_EVENT("## %s ## completed", __FUNCTION__);
|
||||
}
|
||||
|
||||
bt_status_t btrc_ctrl_send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
|
||||
// static bt_status_t send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state)
|
||||
esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state)
|
||||
{
|
||||
tAVRC_STS status = BT_STATUS_UNSUPPORTED;
|
||||
if (tl >= 16 ||
|
||||
key_state > ESP_AVRC_PT_CMD_STATE_RELEASED) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#if (AVRC_CTLR_INCLUDED == TRUE)
|
||||
CHECK_RC_CONNECTED
|
||||
rc_transaction_t *p_transaction=NULL;
|
||||
CHECK_ESP_RC_CONNECTED;
|
||||
BTIF_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__,
|
||||
key_code, key_state);
|
||||
if (btif_rc_cb.rc_features & BTA_AV_FEAT_RCTG)
|
||||
{
|
||||
bt_status_t tran_status = get_transaction(&p_transaction);
|
||||
if(BT_STATUS_SUCCESS == tran_status && NULL != p_transaction)
|
||||
{
|
||||
BTA_AvRemoteCmd(btif_rc_cb.rc_handle, p_transaction->lbl,
|
||||
(tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
|
||||
status = BT_STATUS_SUCCESS;
|
||||
BTIF_TRACE_DEBUG("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = BT_STATUS_FAIL;
|
||||
BTIF_TRACE_DEBUG("%s: error in fetching transaction", __FUNCTION__);
|
||||
}
|
||||
BTA_AvRemoteCmd(btif_rc_cb.rc_handle, tl,
|
||||
(tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state);
|
||||
status = BT_STATUS_SUCCESS;
|
||||
BTIF_TRACE_EVENT("%s: succesfully sent passthrough command to BTA", __FUNCTION__);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = BT_STATUS_FAIL;
|
||||
status = BT_STATUS_FAIL;
|
||||
BTIF_TRACE_DEBUG("%s: feature not supported", __FUNCTION__);
|
||||
}
|
||||
#else
|
||||
BTIF_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__);
|
||||
#endif
|
||||
return status;
|
||||
|
||||
switch (status) {
|
||||
case BT_STATUS_SUCCESS: return ESP_OK;
|
||||
case BT_STATUS_UNSUPPORTED: return ESP_ERR_NOT_SUPPORTED;
|
||||
default: return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const btrc_interface_t bt_rc_interface = {
|
||||
sizeof(bt_rc_interface),
|
||||
init,
|
||||
|
@ -1713,14 +1753,6 @@ static const btrc_interface_t bt_rc_interface = {
|
|||
cleanup,
|
||||
};
|
||||
|
||||
#if 0
|
||||
static const btrc_ctrl_interface_t bt_rc_ctrl_interface = {
|
||||
sizeof(bt_rc_ctrl_interface),
|
||||
init_ctrl,
|
||||
send_passthrough_cmd,
|
||||
cleanup_ctrl,
|
||||
};
|
||||
#endif
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btif_rc_get_interface
|
||||
|
@ -1736,22 +1768,8 @@ const btrc_interface_t *btif_rc_get_interface(void)
|
|||
return &bt_rc_interface;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btif_rc_ctrl_get_interface
|
||||
**
|
||||
** Description Get the AVRCP Controller callback interface
|
||||
**
|
||||
** Returns btav_interface_t
|
||||
**
|
||||
*******************************************************************************/
|
||||
#if 0
|
||||
const btrc_ctrl_interface_t *btif_rc_ctrl_get_interface(void)
|
||||
{
|
||||
BTIF_TRACE_EVENT("%s", __FUNCTION__);
|
||||
return &bt_rc_ctrl_interface;
|
||||
}
|
||||
#endif
|
||||
#endif /* #if 0*/
|
||||
|
||||
/*******************************************************************************
|
||||
** Function initialize_transaction
|
||||
**
|
||||
|
|
|
@ -276,34 +276,4 @@ typedef struct {
|
|||
btrc_connection_state_callback connection_state_cb;
|
||||
} btrc_ctrl_callbacks_t;
|
||||
|
||||
#if 0
|
||||
/** Represents the standard BT-RC AVRCP Controller interface. */
|
||||
typedef struct {
|
||||
|
||||
/** set to sizeof(BtRcInterface) */
|
||||
size_t size;
|
||||
/**
|
||||
* Register the BtRc callbacks
|
||||
*/
|
||||
bt_status_t (*init)( btrc_ctrl_callbacks_t* callbacks );
|
||||
|
||||
/** send pass through command to target */
|
||||
bt_status_t (*send_pass_through_cmd) ( bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state );
|
||||
|
||||
/** Closes the interface. */
|
||||
void (*cleanup)( void );
|
||||
} btrc_ctrl_interface_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Register the BtRc callbacks
|
||||
*/
|
||||
bt_status_t btrc_ctrl_init(btrc_ctrl_callbacks_t *callbacks);
|
||||
|
||||
/** send pass through command to target */
|
||||
bt_status_t btrc_ctrl_send_passthrough_cmd(bt_bdaddr_t *bd_addr, uint8_t key_code, uint8_t key_state);
|
||||
|
||||
/** Closes the interface. */
|
||||
void btrc_ctrl_cleanup(void);
|
||||
|
||||
#endif /* __BT_RC_H__ */
|
||||
|
|
|
@ -15,77 +15,24 @@
|
|||
#include "esp_bt_stack_manager.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_a2dp_api.h"
|
||||
|
||||
#include "bt_rc.h"
|
||||
#include "esp_avrc_api.h"
|
||||
|
||||
typedef enum {
|
||||
BT_APP_EVT_STACK_ON = 0xa0,
|
||||
BT_APP_EVT_MAX
|
||||
} bt_app_evt_t;
|
||||
|
||||
typedef struct {
|
||||
bool state;
|
||||
bt_bdaddr_t bd_addr;
|
||||
} esp_avrc_conn_state_t;
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int key_state;
|
||||
} esp_avrc_passthrough_rsp_t;
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
int key_state;
|
||||
} esp_avrc_key_state_t;
|
||||
|
||||
typedef union {
|
||||
esp_a2d_cb_param_t a2d;
|
||||
esp_avrc_conn_state_t avrc_state;
|
||||
esp_avrc_passthrough_rsp_t avrc_passthrough_rsp;
|
||||
esp_avrc_key_state_t avrc_key;
|
||||
esp_avrc_ct_cb_event_t rc;
|
||||
} bt_app_evt_arg;
|
||||
|
||||
/// AVRC callback events
|
||||
typedef enum {
|
||||
ESP_AVRC_CONNECTION_STATE_EVT = 5, /*!< connection state changed event */
|
||||
ESP_AVRC_PASSTHROUGH_RSP_EVT, /*!< AVRC PASSTHROUGH commands */
|
||||
ESP_AVRC_KEY_STATE_TO
|
||||
} esp_avrc_cb_event_t;
|
||||
|
||||
static esp_a2d_audio_state_t m_audio_state = ESP_A2D_AUDIO_STATE_STOPPED;
|
||||
static TimerHandle_t m_key_tmr = 0;
|
||||
static int m_key_state = 1; // 0 for pressed, 1 for released
|
||||
static xTaskHandle xKeyTaskHandle = 0;
|
||||
|
||||
static void bt_app_handle_evt(uint16_t event, void *p_param);
|
||||
|
||||
static void key_press_task_handler(void *arg)
|
||||
{
|
||||
int key_id = 0x48; // rewind
|
||||
for(;;) {
|
||||
if (m_audio_state != ESP_A2D_AUDIO_STATE_STARTED) {
|
||||
BT_APP_TRACE_EVENT("-----key_tmr_hdlr, return, audio state: %d\n", m_audio_state);
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
bt_app_evt_arg param;
|
||||
memset(¶m, 0, sizeof(bt_app_evt_arg));
|
||||
if (m_key_state == 1) {
|
||||
param.avrc_key.key_state = 1;
|
||||
m_key_state = 0;
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
} else {
|
||||
param.avrc_key.key_state = 0;
|
||||
m_key_state = 1;
|
||||
vTaskDelay(30 / portTICK_PERIOD_MS);
|
||||
}
|
||||
param.avrc_key.id = key_id; // 0x41 volume up, 0x4b FORWARD
|
||||
|
||||
BT_APP_TRACE_EVENT("-----key_task_hdlr: %d, key_id %d---\n", m_key_state, param.avrc_key.id);
|
||||
bt_app_transfer_context(bt_app_handle_evt, ESP_AVRC_KEY_STATE_TO, ¶m, sizeof(bt_app_evt_arg), NULL);
|
||||
}
|
||||
}
|
||||
static void bt_app_handle_rc_evt(uint16_t event, void *p_param);
|
||||
|
||||
static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
|
||||
{
|
||||
|
@ -103,35 +50,25 @@ static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
|
|||
}
|
||||
}
|
||||
|
||||
static void btrc_passthrough_rsp_cb(int id, int key_state)
|
||||
{
|
||||
bt_app_evt_arg param;
|
||||
memset(¶m, 0, sizeof(bt_app_evt_arg));
|
||||
param.avrc_passthrough_rsp.id = id;
|
||||
param.avrc_passthrough_rsp.key_state = key_state;
|
||||
bt_app_transfer_context(bt_app_handle_evt, ESP_AVRC_PASSTHROUGH_RSP_EVT, ¶m, sizeof(bt_app_evt_arg), NULL);
|
||||
}
|
||||
|
||||
static void btrc_conn_state_cb(bool state, bt_bdaddr_t *bd_addr)
|
||||
{
|
||||
bt_app_evt_arg param;
|
||||
memset(¶m, 0, sizeof(bt_app_evt_arg));
|
||||
param.avrc_state.state = state;
|
||||
memcpy(¶m.avrc_state.bd_addr, bd_addr, sizeof(bt_bdaddr_t));
|
||||
bt_app_transfer_context(bt_app_handle_evt, ESP_AVRC_CONNECTION_STATE_EVT, ¶m, sizeof(bt_app_evt_arg), NULL);
|
||||
}
|
||||
|
||||
static btrc_ctrl_callbacks_t btrc_ctrl_cb = {
|
||||
sizeof(btrc_ctrl_callbacks_t),
|
||||
btrc_passthrough_rsp_cb,
|
||||
btrc_conn_state_cb
|
||||
};
|
||||
|
||||
static void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len)
|
||||
{
|
||||
// EspAudioPlayerStreamWrite((uint8_t *)data, len, 10);
|
||||
}
|
||||
|
||||
|
||||
static void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param)
|
||||
{
|
||||
switch (event) {
|
||||
case ESP_AVRC_CT_CONNECTION_STATE_EVT:
|
||||
case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: {
|
||||
bt_app_transfer_context(bt_app_handle_rc_evt, event, param, sizeof(bt_app_evt_arg), NULL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BT_APP_TRACE_ERROR("===a2dp invalid cb event: %d\n", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_app_handle_evt(uint16_t event, void *p_param)
|
||||
{
|
||||
BT_APP_TRACE_DEBUG("bt_app_handle_evt 0x%x\n", event);
|
||||
|
@ -145,8 +82,10 @@ static void bt_app_handle_evt(uint16_t event, void *p_param)
|
|||
esp_a2d_register_data_callback(bt_app_a2d_data_cb);
|
||||
|
||||
esp_a2d_sink_init();
|
||||
|
||||
btrc_ctrl_init(&btrc_ctrl_cb);
|
||||
|
||||
esp_avrc_ct_init();
|
||||
esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
|
||||
|
||||
esp_bt_gap_set_scan_mode(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||
break;
|
||||
}
|
||||
|
@ -157,13 +96,8 @@ static void bt_app_handle_evt(uint16_t event, void *p_param)
|
|||
}
|
||||
case ESP_A2D_AUDIO_STATE_EVT: {
|
||||
a2d = (esp_a2d_cb_param_t *)(p_param);
|
||||
BT_APP_TRACE_EVENT("===a2dp audio_state_cb %d, %d===\n", a2d->audio_stat.state, (int)m_key_tmr);
|
||||
BT_APP_TRACE_EVENT("===a2dp audio_state_cb %d===\n", a2d->audio_stat.state);
|
||||
m_audio_state = a2d->audio_stat.state;
|
||||
if (m_audio_state == ESP_A2D_AUDIO_STATE_STARTED &&
|
||||
m_key_tmr == 0) {
|
||||
BT_APP_TRACE_EVENT("mm1\n");
|
||||
xTaskCreate(key_press_task_handler, "keyT", 2048, NULL, 10, &xKeyTaskHandle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_A2D_AUDIO_CFG_EVT: {
|
||||
|
@ -178,27 +112,32 @@ static void bt_app_handle_evt(uint16_t event, void *p_param)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ESP_AVRC_CONNECTION_STATE_EVT: {
|
||||
esp_avrc_conn_state_t *conn_state = (esp_avrc_conn_state_t *)(p_param);
|
||||
BT_APP_TRACE_EVENT("===avrc conn_state evt %d ===\n", conn_state->state);
|
||||
default:
|
||||
BT_APP_TRACE_ERROR("===application invalid event: %d\n", event);
|
||||
break;
|
||||
}
|
||||
case ESP_AVRC_PASSTHROUGH_RSP_EVT: {
|
||||
esp_avrc_passthrough_rsp_t *passthrough_rsp = (esp_avrc_passthrough_rsp_t *)(p_param);
|
||||
BT_APP_TRACE_EVENT("===avrc passthrough evt id 0x%x, key_state %d===\n", passthrough_rsp->id, passthrough_rsp->key_state);
|
||||
|
||||
}
|
||||
|
||||
void bt_app_handle_rc_evt(uint16_t event, void *p_param)
|
||||
{
|
||||
BT_APP_TRACE_DEBUG("bt_app_handle_avrc_evt 0x%x\n", event);
|
||||
esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(p_param);
|
||||
switch (event) {
|
||||
case ESP_AVRC_CT_CONNECTION_STATE_EVT: {
|
||||
uint8_t *bda = rc->conn_stat.remote_bda;
|
||||
BT_APP_TRACE_EVENT("===avrc conn_state evt: state %d, feature 0x%x, [%02x:%02x:%02x:%02x:%02x:%02x]===\n",
|
||||
rc->conn_stat.connected, rc->conn_stat.feat_mask, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
|
||||
break;
|
||||
}
|
||||
case ESP_AVRC_KEY_STATE_TO: {
|
||||
esp_avrc_key_state_t *key_s = (esp_avrc_key_state_t *)(p_param);
|
||||
BT_APP_TRACE_EVENT("===avrc send key id 0x%x, state %d\n", key_s->id, key_s->key_state);
|
||||
btrc_ctrl_send_passthrough_cmd(NULL, key_s->id, key_s->key_state);
|
||||
case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: {
|
||||
BT_APP_TRACE_EVENT("===avrc passthrough rsp: key_code 0x%x, key_state %d===\n", rc->psth_rsp.key_code, rc->psth_rsp.key_state);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BT_APP_TRACE_ERROR("===application invalid event: %d\n", event);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void app_main_entry(void)
|
||||
|
|
Loading…
Reference in a new issue