]> granicus.if.org Git - esp-idf/commitdiff
Merge branch 'master' into feature/btdm_avrc
authorwangmengyang <wangmengyang@espressif.com>
Tue, 17 Jan 2017 02:36:26 +0000 (10:36 +0800)
committerwangmengyang <wangmengyang@espressif.com>
Tue, 17 Jan 2017 02:36:26 +0000 (10:36 +0800)
# Conflicts:
# components/bt/bluedroid/hci/packet_fragmenter.c
# components/bt/bluedroid/stack/include/gatt_api.h

1  2 
components/bt/bluedroid/api/include/esp_a2dp_api.h
components/bt/bluedroid/btif/btif_avk.c
components/bt/bluedroid/btif/btif_core.c
components/bt/bluedroid/btif/btif_media_task.c
components/bt/bluedroid/hci/hci_hal_h4.c
components/bt/bluedroid/hci/hci_layer.c
components/bt/bluedroid/stack/btu/btu_task.c
components/bt/bluedroid/stack/include/gatt_api.h
components/bt/component.mk
examples/09_a2dp/components/bluedroid_demos/app_project/SampleAV.c
examples/09_a2dp/main/demo_main.c

index 8ff1a0cc6afdaa750426431d1db1e213243e7d40,0000000000000000000000000000000000000000..c8cc53e86a39d42f87a1c4355440900fcb0770f5
mode 100644,000000..100644
--- /dev/null
@@@ -1,190 -1,0 +1,197 @@@
- esp_err_t esp_a2d_register_callback(esp_profile_cb_t callback);
 +// 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_A2DP_API_H__
 +#define __ESP_A2DP_API_H__
 +
 +#include "esp_err.h"
 +#include "esp_bt_defs.h"
 +
 +/// Media codec types supported by A2DP
 +#define ESP_A2D_MCT_SBC         (0)             /*!< SBC */
 +#define ESP_A2D_MCT_M12         (0x01)          /*!< MPEG-1, 2 Audio */
 +#define ESP_A2D_MCT_M24         (0x02)          /*!< MPEG-2, 4 AAC */
 +#define ESP_A2D_MCT_ATRAC       (0x04)          /*!< ATRAC family */
 +#define ESP_A2D_MCT_NON_A2DP    (0xff)
 +typedef uint8_t esp_a2d_mct_t;
 +
 +/**
 + * @brief Codec specific information elements as defined in A2DP spec.
 + */
 +
 +/**
 + * @brief SBC codec specific information
 + */
 +typedef struct {
 +#define ESP_A2D_CIE_LEN_SBC          (4)
 +    uint8_t oct[ESP_A2D_CIE_LEN_SBC];
 +} esp_a2d_cie_sbc_t;
 +
 +/**
 + * @brief MPEG-1,2 Audio codec specific information
 + */
 +typedef struct {
 +#define ESP_A2D_CIE_LEN_M12          (4)
 +    uint8_t oct[ESP_A2D_CIE_LEN_M12];
 +} esp_a2d_cie_m12_t;
 +
 +/**
 + * @brief MPEG-2,4 AAC codec specific information
 + */
 +typedef struct {
 +#define ESP_A2D_CIE_LEN_M24          (6)
 +    uint8_t oct[ESP_A2D_CIE_LEN_M24];
 +} esp_a2d_cie_m24_t;
 +
 +/**
 + * @brief ATRAC family codec specific information
 + */
 +typedef struct {
 +#define ESP_A2D_CIE_LEN_ATRAC        (7)
 +    uint8_t oct[ESP_A2D_CIE_LEN_ATRAC];
 +} esp_a2d_cie_atrac_t;
 +
 +/**
 + * @brief A2DP media codec capabilities union
 + */
 +typedef struct {
 +    esp_a2d_mct_t type;         /*!< A2DP media codec type */
 +    union {
 +        esp_a2d_cie_sbc_t sbc;
 +        esp_a2d_cie_m12_t m12;
 +        esp_a2d_cie_m24_t m24;
 +        esp_a2d_cie_atrac_t atrac;
 +    } cie;
 +} esp_a2d_mcc_t;
 +
 +/// Bluetooth A2DP connection states
 +typedef enum {
 +    ESP_A2D_CONNECTION_STATE_DISCONNECTED = 0,
 +    ESP_A2D_CONNECTION_STATE_CONNECTING,
 +    ESP_A2D_CONNECTION_STATE_CONNECTED,
 +    ESP_A2D_CONNECTION_STATE_DISCONNECTING
 +} esp_a2d_connection_state_t;
 +
 +/// Bluetooth A2DP datapath states
 +typedef enum {
 +    ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND = 0,
 +    ESP_A2D_AUDIO_STATE_STOPPED,
 +    ESP_A2D_AUDIO_STATE_STARTED,
 +} esp_a2d_audio_state_t;
 +
 +/// A2DP callback events
 +typedef enum {
 +    ESP_A2D_CONNECTION_STATE_EVT = 0,           /*!< connection state changed event */
 +    ESP_A2D_AUDIO_STATE_EVT = 1,                /*!< audio stream transmission state changed event */
 +    ESP_A2D_AUDIO_CFG_EVT = 2                   /*!< audio codec configuration received */
 +} esp_a2d_cb_event_t;
 +
 +/// A2DP state callback parameters
 +typedef union {
 +    /*< ESP_A2D_CONNECTION_STATE_EVT */
 +    struct a2d_conn_stat_param {
 +        esp_a2d_connection_state_t state;       /*!< one of values from esp_a2d_connection_state_t */
 +        esp_bd_addr_t remote_bda;
 +    } conn_stat;
 +    
 +    /*< ESP_A2D_AUDIO_STATE_EVT */
 +    struct a2d_audio_stat_param {
 +        esp_a2d_audio_state_t state;            /*!< one of the values from esp_a2d_audio_state_t */
 +        esp_bd_addr_t remote_bda;
 +    } audio_stat;
 +    
 +    /*< ESP_A2D_AUDIO_CFG_EVT */
 +    struct a2d_audio_cfg_param {
 +        esp_bd_addr_t remote_bda;
 +        esp_a2d_mcc_t mcc;                      /*!< A2DP media codec capability information */
 +    } audio_cfg;
 +} esp_a2d_cb_param_t;
 +
++/**
++ * @brief           A2DP profile callback function, data is ou
++ * @param           event : Event type
++ * @param           param : Point to callback parameter
++ */
++typedef void (* esp_a2d_cb_t)(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param);
++
 +/**
 + * @brief           A2DP profile data callback function, data is ou
 + *                 
 + * @param[in]       buf: data received and decoded to PCM format, buf points to a static memory
 + *                  and can be overwritten in later times
 + * @param[in]       len: size(in bytes) in buf
 + *
 + */
 +typedef void (* esp_a2d_data_cb_t)(const uint8_t *buf, uint32_t len);
 +
 +
 +/**
 + * @brief           This function is called to register application callbacks
 + *                  with A2DP module; callbacks will provide the upstream events
 + *                  (type esp_a2d_cb_event_t) and paramters(type esp_a2d_cb_param_t)
 + *                  
 + * @param[in]       callback: A2DP sink event callback function
 + *
 + * @return
 + *                  - ESP_OK: success
 + *
 + */
++esp_err_t esp_a2d_register_callback(esp_a2d_cb_t callback);
 +
 +
 +/**
 + * @brief           This function is called to register A2DP sink data output function
 + *                  for now only supports SBC codec, and the output is PCM data stream
 + *                  
 + * @param[in]       callback: A2DP data callback function
 + *
 + * @return
 + *                  - ESP_OK: success
 + *
 + */
 +esp_err_t esp_a2d_register_data_callback(esp_a2d_data_cb_t cb);
 +
 +
 +/**
 + *
 + * @brief           This function is called to initialize the bluetooth A2DP sink module
 + *
 + * @return          
 + *                  - ESP_OK: success
 + *                  - ESP_FAIL: others
 + *
 + */
 +esp_err_t esp_a2d_sink_init(void);
 +
 +
 +/**
 + *
 + * @brief           This function is called to deinit and free the resources for A2DP sink module
 + *
 + */
 +void esp_a2d_sink_deinit(void);
 +
 +
 +/**
 + *
 + * @brief           This function is called to disconnect with the remote bluetooth device
 + *
 + * @return          
 + *                  - ESP_OK: disconnect request is sent to lower layer
 + *                  - ESP_FAIL: others
 + *
 + */
 +esp_err_t esp_a2d_sink_disconnect(esp_bd_addr_t remote_bda);
 +
 +#endif /* __ESP_A2DP_API_H__ */
index d09e261ba70ed01483332c4407fe07d9781f3ea1,0000000000000000000000000000000000000000..06315f7e32c206b7d0d5f5154759d9132d2e8761
mode 100644,000000..100644
--- /dev/null
@@@ -1,1250 -1,0 +1,1250 @@@
- static esp_profile_cb_t bt_av_sink_callback = NULL;
 +/******************************************************************************
 + *
 + *  Copyright (C) 2009-2012 Broadcom Corporation
 + *
 + *  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.
 + *
 + ******************************************************************************/
 +
 +
 +/*****************************************************************************
 + *
 + *  Filename:      btif_av.c
 + *
 + *  Description:   Bluedroid AV implementation
 + *
 + *****************************************************************************/
 +
 +#include "bt_trace.h"
 +#include <string.h>
 +
 +#include "bt_defs.h"
 +#include "esp_bt_defs.h"
 +#include "esp_a2dp_api.h"
 +#include "allocator.h"
 +
 +#define LOG_TAG "bt_btif_av"
 +
 +#include "btif_av.h"
 +#include "btif_util.h"
 +#include "btif_profile_queue.h"
 +#include "bta_api.h"
 +#include "btif_media.h"
 +#include "bta_av_api.h"
 +#include "gki.h"
 +#include "btu.h"
 +#include "bt_utils.h"
 +
 +/*****************************************************************************
 +**  Constants & Macros
 +******************************************************************************/
 +#define BTIF_AV_SERVICE_NAME "Advanced Audio"
 +
 +#define BTIF_TIMEOUT_AV_OPEN_ON_RC_SECS  2
 +
 +typedef enum {
 +    BTIF_AV_STATE_IDLE = 0x0,
 +    BTIF_AV_STATE_OPENING,
 +    BTIF_AV_STATE_OPENED,
 +    BTIF_AV_STATE_STARTED,
 +    BTIF_AV_STATE_CLOSING
 +} btif_av_state_t;
 +
 +/* Should not need dedicated suspend state as actual actions are no
 +   different than open state. Suspend flags are needed however to prevent
 +   media task from trying to restart stream during remote suspend or while
 +   we are in the process of a local suspend */
 +
 +#define BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING 0x1
 +#define BTIF_AV_FLAG_REMOTE_SUSPEND        0x2
 +#define BTIF_AV_FLAG_PENDING_START         0x4
 +#define BTIF_AV_FLAG_PENDING_STOP          0x8
 +
 +/*****************************************************************************
 +**  Local type definitions
 +******************************************************************************/
 +
 +typedef struct {
 +    tBTA_AV_HNDL bta_handle;
 +    bt_bdaddr_t peer_bda;
 +    btif_sm_handle_t sm_handle;
 +    UINT8 flags;
 +    tBTA_AV_EDR edr;
 +    UINT8   peer_sep;  /* sep type of peer device */
 +} btif_av_cb_t;
 +
 +typedef struct {
 +    bt_bdaddr_t *target_bda;
 +    uint16_t uuid;
 +} btif_av_connect_req_t;
 +
 +/*****************************************************************************
 +**  Static variables
 +******************************************************************************/
 +
- esp_err_t esp_a2d_register_callback(esp_profile_cb_t callback)
++static esp_a2d_cb_t bt_av_sink_callback = NULL;
 +
 +static btif_av_cb_t btif_av_cb = {0};
 +static TIMER_LIST_ENT tle_av_open_on_rc;
 +
 +// TODO: need protection against race
 +#define BTIF_A2D_CB_TO_APP(_event, _param)    do { \
 +      if (bt_av_sink_callback) { \
 +          bt_av_sink_callback(_event, _param); \
 +      } \
 +    } while (0)
 +
 +/* both interface and media task needs to be ready to alloc incoming request */
 +#define CHECK_BTAV_INIT() if (btif_av_cb.sm_handle == NULL)\
 +{\
 +     BTIF_TRACE_WARNING("%s: BTAV not initialized\n", __FUNCTION__);\
 +     return ESP_ERR_INVALID_STATE;\
 +}\
 +else\
 +{\
 +     BTIF_TRACE_EVENT("%s\n", __FUNCTION__);\
 +}
 +
 +/* Helper macro to avoid code duplication in the state machine handlers */
 +#define CHECK_RC_EVENT(e, d) \
 +    case BTA_AV_RC_OPEN_EVT: \
 +    case BTA_AV_RC_CLOSE_EVT: \
 +    case BTA_AV_REMOTE_CMD_EVT: \
 +    case BTA_AV_VENDOR_CMD_EVT: \
 +    case BTA_AV_META_MSG_EVT: \
 +    case BTA_AV_RC_FEAT_EVT: \
 +    case BTA_AV_REMOTE_RSP_EVT: \
 +    { \
 +         btif_rc_handler(e, d);\
 +    }break; \
 +
 +static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *data);
 +static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *data);
 +static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *data);
 +static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *data);
 +static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *data);
 +
 +static const btif_sm_handler_t btif_av_state_handlers[] = {
 +    btif_av_state_idle_handler,
 +    btif_av_state_opening_handler,
 +    btif_av_state_opened_handler,
 +    btif_av_state_started_handler,
 +    btif_av_state_closing_handler
 +};
 +
 +static void btif_av_event_free_data(btif_sm_event_t event, void *p_data);
 +
 +/*************************************************************************
 +** Extern functions
 +*************************************************************************/
 +extern void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data);
 +extern BOOLEAN btif_rc_get_connected_peer(BD_ADDR peer_addr);
 +extern void btif_rc_check_handle_pending_play (BD_ADDR peer_addr, BOOLEAN bSendToApp);
 +
 +extern tBTA_AV_CO_FUNCTS bta_av_a2d_cos;
 +/*****************************************************************************
 +** Local helper functions
 +******************************************************************************/
 +
 +const char *dump_av_sm_state_name(btif_av_state_t state)
 +{
 +    switch (state) {
 +        CASE_RETURN_STR(BTIF_AV_STATE_IDLE)
 +        CASE_RETURN_STR(BTIF_AV_STATE_OPENING)
 +        CASE_RETURN_STR(BTIF_AV_STATE_OPENED)
 +        CASE_RETURN_STR(BTIF_AV_STATE_STARTED)
 +        CASE_RETURN_STR(BTIF_AV_STATE_CLOSING)
 +    default: return "UNKNOWN_STATE";
 +    }
 +}
 +
 +const char *dump_av_sm_event_name(btif_av_sm_event_t event)
 +{
 +    switch ((int)event) {
 +        CASE_RETURN_STR(BTA_AV_ENABLE_EVT)
 +        CASE_RETURN_STR(BTA_AV_REGISTER_EVT)
 +        CASE_RETURN_STR(BTA_AV_OPEN_EVT)
 +        CASE_RETURN_STR(BTA_AV_CLOSE_EVT)
 +        CASE_RETURN_STR(BTA_AV_START_EVT)
 +        CASE_RETURN_STR(BTA_AV_STOP_EVT)
 +        CASE_RETURN_STR(BTA_AV_PROTECT_REQ_EVT)
 +        CASE_RETURN_STR(BTA_AV_PROTECT_RSP_EVT)
 +        CASE_RETURN_STR(BTA_AV_RC_OPEN_EVT)
 +        CASE_RETURN_STR(BTA_AV_RC_CLOSE_EVT)
 +        CASE_RETURN_STR(BTA_AV_REMOTE_CMD_EVT)
 +        CASE_RETURN_STR(BTA_AV_REMOTE_RSP_EVT)
 +        CASE_RETURN_STR(BTA_AV_VENDOR_CMD_EVT)
 +        CASE_RETURN_STR(BTA_AV_VENDOR_RSP_EVT)
 +        CASE_RETURN_STR(BTA_AV_RECONFIG_EVT)
 +        CASE_RETURN_STR(BTA_AV_SUSPEND_EVT)
 +        CASE_RETURN_STR(BTA_AV_PENDING_EVT)
 +        CASE_RETURN_STR(BTA_AV_META_MSG_EVT)
 +        CASE_RETURN_STR(BTA_AV_REJECT_EVT)
 +        CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT)
 +        CASE_RETURN_STR(BTIF_SM_ENTER_EVT)
 +        CASE_RETURN_STR(BTIF_SM_EXIT_EVT)
 +        CASE_RETURN_STR(BTIF_AV_CONNECT_REQ_EVT)
 +        CASE_RETURN_STR(BTIF_AV_DISCONNECT_REQ_EVT)
 +        CASE_RETURN_STR(BTIF_AV_START_STREAM_REQ_EVT)
 +        CASE_RETURN_STR(BTIF_AV_STOP_STREAM_REQ_EVT)
 +        CASE_RETURN_STR(BTIF_AV_SUSPEND_STREAM_REQ_EVT)
 +        CASE_RETURN_STR(BTIF_AV_SINK_CONFIG_REQ_EVT)
 +    default: return "UNKNOWN_EVENT";
 +    }
 +}
 +
 +/****************************************************************************
 +**  Local helper functions
 +*****************************************************************************/
 +/*******************************************************************************
 +**
 +** Function         btif_initiate_av_open_tmr_hdlr
 +**
 +** Description      Timer to trigger AV open if the remote headset establishes
 +**                  RC connection w/o AV connection. The timer is needed to IOP
 +**                  with headsets that do establish AV after RC connection.
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +static void btif_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle)
 +{
 +    BD_ADDR peer_addr;
 +    UNUSED(tle);
 +    btif_av_connect_req_t connect_req;
 +    UNUSED(tle);
 +    /* is there at least one RC connection - There should be */
 +    if (btif_rc_get_connected_peer(peer_addr)) {
 +        BTIF_TRACE_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__);
 +        /* In case of AVRCP connection request, we will initiate SRC connection */
 +        connect_req.target_bda = (bt_bdaddr_t *)&peer_addr;
 +        connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE;
 +        btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char *)&connect_req);
 +    } else {
 +        BTIF_TRACE_ERROR("%s No connected RC peers", __FUNCTION__);
 +    }
 +}
 +
 +/*****************************************************************************
 +**  Static functions
 +******************************************************************************/
 +static void btif_report_connection_state(esp_a2d_connection_state_t state, bt_bdaddr_t *bd_addr)
 +{
 +    esp_a2d_cb_param_t param;
 +    memset(&param, 0, sizeof(esp_a2d_cb_param_t));
 +    
 +    param.conn_stat.state = state;
 +    if (bd_addr) {
 +        memcpy(param.conn_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t));
 +    }
 +    BTIF_A2D_CB_TO_APP(ESP_A2D_CONNECTION_STATE_EVT, &param);
 +}
 +
 +static void btif_report_audio_state(esp_a2d_audio_state_t state, bt_bdaddr_t *bd_addr)
 +{
 +    esp_a2d_cb_param_t param;
 +    memset(&param, 0, sizeof(esp_a2d_cb_param_t));
 +
 +    param.audio_stat.state = state;
 +    if (bd_addr) {
 +        memcpy(param.audio_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t));
 +    }
 +    BTIF_A2D_CB_TO_APP(ESP_A2D_AUDIO_STATE_EVT, &param);
 +}
 +
 +/*****************************************************************************
 +**
 +** Function     btif_av_state_idle_handler
 +**
 +** Description  State managing disconnected AV link
 +**
 +** Returns      TRUE if event was processed, FALSE otherwise
 +**
 +*******************************************************************************/
 +
 +static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data)
 +{
 +    BTIF_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
 +                     dump_av_sm_event_name(event), btif_av_cb.flags);
 +
 +    switch (event) {
 +    case BTIF_SM_ENTER_EVT:
 +        /* clear the peer_bda */
 +        memset(&btif_av_cb.peer_bda, 0, sizeof(bt_bdaddr_t));
 +        btif_av_cb.flags = 0;
 +        btif_av_cb.edr = 0;
 +        btif_a2dp_on_idle();
 +        break;
 +
 +    case BTIF_SM_EXIT_EVT:
 +        break;
 +
 +    case BTA_AV_ENABLE_EVT:
 +        break;
 +
 +    case BTA_AV_REGISTER_EVT:
 +        btif_av_cb.bta_handle = ((tBTA_AV *)p_data)->registr.hndl;
 +        break;
 +
 +    case BTA_AV_PENDING_EVT:
 +    case BTIF_AV_CONNECT_REQ_EVT: {
 +        if (event == BTIF_AV_CONNECT_REQ_EVT) {
 +            memcpy(&btif_av_cb.peer_bda, ((btif_av_connect_req_t *)p_data)->target_bda,
 +                   sizeof(bt_bdaddr_t));
 +            BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
 +                       TRUE, BTA_SEC_AUTHENTICATE, ((btif_av_connect_req_t *)p_data)->uuid);
 +        } else if (event == BTA_AV_PENDING_EVT) {
 +            bdcpy(btif_av_cb.peer_bda.address, ((tBTA_AV *)p_data)->pend.bd_addr);
 +            BTA_AvOpen(btif_av_cb.peer_bda.address, btif_av_cb.bta_handle,
 +                       TRUE, BTA_SEC_AUTHENTICATE, UUID_SERVCLASS_AUDIO_SOURCE);
 +        }
 +        btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING);
 +    } break;
 +
 +    case BTA_AV_RC_OPEN_EVT:
 +        /* IOP_FIX: Jabra 620 only does RC open without AV open whenever it connects. So
 +         * as per the AV WP, an AVRC connection cannot exist without an AV connection. Therefore,
 +         * we initiate an AV connection if an RC_OPEN_EVT is received when we are in AV_CLOSED state.
 +         * We initiate the AV connection after a small 3s timeout to avoid any collisions from the
 +         * headsets, as some headsets initiate the AVRC connection first and then
 +         * immediately initiate the AV connection
 +         *
 +         * TODO: We may need to do this only on an AVRCP Play. FixMe
 +         */
 +
 +        BTIF_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
 +        memset(&tle_av_open_on_rc, 0, sizeof(tle_av_open_on_rc));
 +        tle_av_open_on_rc.param = (UINT32)btif_initiate_av_open_tmr_hdlr;
 +        btu_start_timer(&tle_av_open_on_rc, BTU_TTYPE_USER_FUNC,
 +                        BTIF_TIMEOUT_AV_OPEN_ON_RC_SECS);
 +        btif_rc_handler(event, p_data);
 +        break;
 +
 +    case BTA_AV_REMOTE_CMD_EVT:
 +    case BTA_AV_VENDOR_CMD_EVT:
 +    case BTA_AV_META_MSG_EVT:
 +    case BTA_AV_RC_FEAT_EVT:
 +    case BTA_AV_REMOTE_RSP_EVT:
 +        btif_rc_handler(event, (tBTA_AV *)p_data);
 +        break;
 +
 +    case BTA_AV_RC_CLOSE_EVT:
 +        if (tle_av_open_on_rc.in_use) {
 +            BTIF_TRACE_DEBUG("BTA_AV_RC_CLOSE_EVT: Stopping AV timer.");
 +            btu_stop_timer(&tle_av_open_on_rc);
 +        }
 +        btif_rc_handler(event, p_data);
 +        break;
 +
 +    default:
 +        BTIF_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
 +                           dump_av_sm_event_name(event));
 +        return FALSE;
 +
 +    }
 +
 +    return TRUE;
 +}
 +/*****************************************************************************
 +**
 +** Function        btif_av_state_opening_handler
 +**
 +** Description     Intermediate state managing events during establishment
 +**                 of avdtp channel
 +**
 +** Returns         TRUE if event was processed, FALSE otherwise
 +**
 +*******************************************************************************/
 +
 +static BOOLEAN btif_av_state_opening_handler(btif_sm_event_t event, void *p_data)
 +{
 +    BTIF_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
 +                     dump_av_sm_event_name(event), btif_av_cb.flags);
 +
 +    switch (event) {
 +    case BTIF_SM_ENTER_EVT:
 +        /* inform the application that we are entering connecting state */
 +        btif_report_connection_state(ESP_A2D_CONNECTION_STATE_CONNECTING, &(btif_av_cb.peer_bda));
 +        break;
 +
 +    case BTIF_SM_EXIT_EVT:
 +        break;
 +
 +    case BTA_AV_REJECT_EVT:
 +        BTIF_TRACE_DEBUG(" Received  BTA_AV_REJECT_EVT \n");
 +        btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
 +        btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
 +        break;
 +
 +    case BTA_AV_OPEN_EVT: {
 +        tBTA_AV *p_bta_data = (tBTA_AV *)p_data;
 +        esp_a2d_connection_state_t state;
 +        btif_sm_state_t av_state;
 +        BTIF_TRACE_DEBUG("status:%d, edr 0x%x\n", p_bta_data->open.status,
 +                         p_bta_data->open.edr);
 +
 +        if (p_bta_data->open.status == BTA_AV_SUCCESS) {
 +            state = ESP_A2D_CONNECTION_STATE_CONNECTED;
 +            av_state = BTIF_AV_STATE_OPENED;
 +            btif_av_cb.edr = p_bta_data->open.edr;
 +
 +            btif_av_cb.peer_sep = p_bta_data->open.sep;
 +            btif_a2dp_set_peer_sep(p_bta_data->open.sep);
 +        } else {
 +            BTIF_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d\n",
 +                               p_bta_data->open.status );
 +            state = ESP_A2D_CONNECTION_STATE_DISCONNECTED;
 +            av_state  = BTIF_AV_STATE_IDLE;
 +        }
 +
 +        /* inform the application of the event */
 +        btif_report_connection_state(state, &(btif_av_cb.peer_bda));
 +        /* change state to open/idle based on the status */
 +        btif_sm_change_state(btif_av_cb.sm_handle, av_state);
 +        if (btif_av_cb.peer_sep == AVDT_TSEP_SNK) {
 +            /* if queued PLAY command,  send it now */
 +            btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr,
 +                                              (p_bta_data->open.status == BTA_AV_SUCCESS));
 +        } else if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
 +            /* if queued PLAY command,  send it now */
 +            btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE);
 +            /* Bring up AVRCP connection too */
 +            BTA_AvOpenRc(btif_av_cb.bta_handle);
 +        }
 +        btif_queue_advance();
 +    } break;
 +
 +    case BTIF_AV_SINK_CONFIG_REQ_EVT: {
 +        if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
 +            esp_a2d_cb_param_t param;
 +            memcpy(param.audio_cfg.remote_bda, &btif_av_cb.peer_bda, sizeof(esp_bd_addr_t));
 +            memcpy(&param.audio_cfg.mcc, p_data, sizeof(esp_a2d_mcc_t));
 +            BTIF_A2D_CB_TO_APP(ESP_A2D_AUDIO_CFG_EVT, &param);
 +        }
 +    } break;
 +
 +    case BTIF_AV_CONNECT_REQ_EVT:
 +        // Check for device, if same device which moved to opening then ignore callback
 +        if (memcmp ((bt_bdaddr_t *)p_data, &(btif_av_cb.peer_bda),
 +                    sizeof(btif_av_cb.peer_bda)) == 0) {
 +            BTIF_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Connect Req\n", __func__);
 +            btif_queue_advance();
 +            break;
 +        } else {
 +            BTIF_TRACE_DEBUG("%s: Moved from idle by Incoming Connection request\n", __func__);
 +            btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data);
 +            btif_queue_advance();
 +            break;
 +        }
 +
 +    case BTA_AV_PENDING_EVT:
 +        // Check for device, if same device which moved to opening then ignore callback
 +        if (memcmp (((tBTA_AV *)p_data)->pend.bd_addr, &(btif_av_cb.peer_bda),
 +                    sizeof(btif_av_cb.peer_bda)) == 0) {
 +            BTIF_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Pending Req\n", __func__);
 +            break;
 +        } else {
 +            BTIF_TRACE_DEBUG("%s: Moved from idle by outgoing Connection request\n", __func__);
 +            BTA_AvDisconnect(((tBTA_AV *)p_data)->pend.bd_addr);
 +            break;
 +        }
 +
 +        CHECK_RC_EVENT(event, p_data);
 +
 +    default:
 +        BTIF_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
 +                           dump_av_sm_event_name(event));
 +        return FALSE;
 +
 +    }
 +    return TRUE;
 +}
 +
 +
 +/*****************************************************************************
 +**
 +** Function        btif_av_state_closing_handler
 +**
 +** Description     Intermediate state managing events during closing
 +**                 of avdtp channel
 +**
 +** Returns         TRUE if event was processed, FALSE otherwise
 +**
 +*******************************************************************************/
 +
 +static BOOLEAN btif_av_state_closing_handler(btif_sm_event_t event, void *p_data)
 +{
 +    BTIF_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
 +                     dump_av_sm_event_name(event), btif_av_cb.flags);
 +
 +    switch (event) {
 +    case BTIF_SM_ENTER_EVT:
 +        if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
 +            btif_a2dp_set_rx_flush(TRUE);
 +        }
 +        break;
 +
 +    case BTA_AV_STOP_EVT:
 +    case BTIF_AV_STOP_STREAM_REQ_EVT:
 +        if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
 +            btif_a2dp_set_rx_flush(TRUE);
 +        }
 +
 +        btif_a2dp_on_stopped(NULL);
 +        break;
 +
 +    case BTIF_SM_EXIT_EVT:
 +        break;
 +
 +    case BTA_AV_CLOSE_EVT:
 +
 +        /* inform the application that we are disconnecting */
 +        btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
 +
 +        btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
 +        break;
 +
 +    /* Handle the RC_CLOSE event for the cleanup */
 +    case BTA_AV_RC_CLOSE_EVT:
 +        btif_rc_handler(event, (tBTA_AV *)p_data);
 +        break;
 +
 +    default:
 +        BTIF_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
 +                           dump_av_sm_event_name(event));
 +        return FALSE;
 +    }
 +    return TRUE;
 +}
 +
 +
 +/*****************************************************************************
 +**
 +** Function     btif_av_state_opened_handler
 +**
 +** Description  Handles AV events while AVDTP is in OPEN state
 +**
 +** Returns      TRUE if event was processed, FALSE otherwise
 +**
 +*******************************************************************************/
 +
 +static BOOLEAN btif_av_state_opened_handler(btif_sm_event_t event, void *p_data)
 +{
 +    tBTA_AV *p_av = (tBTA_AV *)p_data;
 +
 +    BTIF_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
 +                     dump_av_sm_event_name(event), btif_av_cb.flags);
 +
 +    if ( (event == BTA_AV_REMOTE_CMD_EVT) && (btif_av_cb.flags & BTIF_AV_FLAG_REMOTE_SUSPEND) &&
 +            (p_av->remote_cmd.rc_id == BTA_AV_RC_PLAY) ) {
 +        BTIF_TRACE_EVENT("%s: Resetting remote suspend flag on RC PLAY\n", __FUNCTION__);
 +        btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
 +    }
 +
 +    switch (event) {
 +    case BTIF_SM_ENTER_EVT:
 +        btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_STOP;
 +        btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
 +        break;
 +
 +    case BTIF_SM_EXIT_EVT:
 +        btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
 +        break;
 +
 +    case BTIF_AV_START_STREAM_REQ_EVT:
 +        BTA_AvStart();
 +        btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_START;
 +        break;
 +
 +    case BTA_AV_START_EVT: {
 +        BTIF_TRACE_EVENT("BTA_AV_START_EVT status %d, suspending %d, init %d\n",
 +                         p_av->start.status, p_av->start.suspending, p_av->start.initiator);
 +
 +        if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE)) {
 +            return TRUE;
 +        }
 +
 +        /* remain in open state if status failed */
 +        if (p_av->start.status != BTA_AV_SUCCESS) {
 +            return FALSE;
 +        }
 +
 +        if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
 +            btif_a2dp_set_rx_flush(FALSE); /*  remove flush state, ready for streaming*/
 +        }
 +
 +        /* change state to started, send acknowledgement if start is pending */
 +        if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
 +
 +            /* pending start flag will be cleared when exit current state */
 +        }
 +        btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_STARTED);
 +
 +    } break;
 +
 +    case BTIF_AV_DISCONNECT_REQ_EVT:
 +        BTA_AvClose(btif_av_cb.bta_handle);
 +        if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
 +            BTA_AvCloseRc(btif_av_cb.bta_handle);
 +        }
 +
 +        /* inform the application that we are disconnecting */
 +        btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
 +        break;
 +
 +    case BTA_AV_CLOSE_EVT:
 +        /* avdtp link is closed */
 +        btif_a2dp_on_stopped(NULL);
 +
 +        /* inform the application that we are disconnected */
 +        btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
 +
 +        /* change state to idle, send acknowledgement if start is pending */
 +        if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
 +            /* pending start flag will be cleared when exit current state */
 +        }
 +        btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
 +        break;
 +
 +    case BTA_AV_RECONFIG_EVT:
 +        if ((btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) &&
 +                (p_av->reconfig.status == BTA_AV_SUCCESS)) {
 +            APPL_TRACE_WARNING("reconfig done BTA_AVstart()\n");
 +            BTA_AvStart();
 +        } else if (btif_av_cb.flags & BTIF_AV_FLAG_PENDING_START) {
 +            btif_av_cb.flags &= ~BTIF_AV_FLAG_PENDING_START;
 +        }
 +        break;
 +
 +    case BTIF_AV_CONNECT_REQ_EVT:
 +        if (memcmp ((bt_bdaddr_t *)p_data, &(btif_av_cb.peer_bda),
 +                    sizeof(btif_av_cb.peer_bda)) == 0) {
 +            BTIF_TRACE_DEBUG("%s: Ignore BTIF_AV_CONNECT_REQ_EVT for same device\n", __func__);
 +        } else {
 +            BTIF_TRACE_DEBUG("%s: Moved to opened by Other Incoming Conn req\n", __func__);
 +            btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED,
 +                                         (bt_bdaddr_t *)p_data);
 +        }
 +        btif_queue_advance();
 +        break;
 +
 +        CHECK_RC_EVENT(event, p_data);
 +
 +    default:
 +        BTIF_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
 +                           dump_av_sm_event_name(event));
 +        return FALSE;
 +
 +    }
 +    return TRUE;
 +}
 +
 +/*****************************************************************************
 +**
 +** Function     btif_av_state_started_handler
 +**
 +** Description  Handles AV events while A2DP stream is started
 +**
 +** Returns      TRUE if event was processed, FALSE otherwise
 +**
 +*******************************************************************************/
 +
 +static BOOLEAN btif_av_state_started_handler(btif_sm_event_t event, void *p_data)
 +{
 +    tBTA_AV *p_av = (tBTA_AV *)p_data;
 +
 +    BTIF_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__,
 +                     dump_av_sm_event_name(event), btif_av_cb.flags);
 +
 +    switch (event) {
 +    case BTIF_SM_ENTER_EVT:
 +
 +        /* we are again in started state, clear any remote suspend flags */
 +        btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
 +
 +        btif_report_audio_state(ESP_A2D_AUDIO_STATE_STARTED, &(btif_av_cb.peer_bda));
 +
 +        /* increase the a2dp consumer task priority temporarily when start
 +        ** audio playing, to avoid overflow the audio packet queue. */
 +        adjust_priority_a2dp(TRUE);
 +
 +        break;
 +
 +    case BTIF_SM_EXIT_EVT:
 +        /* restore the a2dp consumer task priority when stop audio playing. */
 +        adjust_priority_a2dp(FALSE);
 +
 +        break;
 +
 +    case BTIF_AV_START_STREAM_REQ_EVT:
 +        break;
 +
 +    /* fixme -- use suspend = true always to work around issue with BTA AV */
 +    case BTIF_AV_STOP_STREAM_REQ_EVT:
 +    case BTIF_AV_SUSPEND_STREAM_REQ_EVT:
 +
 +        /* set pending flag to ensure btif task is not trying to restart
 +           stream while suspend is in progress */
 +        btif_av_cb.flags |= BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
 +
 +        /* if we were remotely suspended but suspend locally, local suspend
 +           always overrides */
 +        btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
 +
 +        if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
 +            btif_a2dp_set_rx_flush(TRUE);
 +            btif_a2dp_on_stopped(NULL);
 +        }
 +
 +        BTA_AvStop(TRUE);
 +        break;
 +
 +    case BTIF_AV_DISCONNECT_REQ_EVT:
 +
 +        /* request avdtp to close */
 +        BTA_AvClose(btif_av_cb.bta_handle);
 +        if (btif_av_cb.peer_sep == AVDT_TSEP_SRC) {
 +            BTA_AvCloseRc(btif_av_cb.bta_handle);
 +        }
 +
 +        /* inform the application that we are disconnecting */
 +        btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btif_av_cb.peer_bda));
 +
 +        /* wait in closing state until fully closed */
 +        btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_CLOSING);
 +        break;
 +
 +    case BTA_AV_SUSPEND_EVT:
 +
 +        BTIF_TRACE_EVENT("BTA_AV_SUSPEND_EVT status %d, init %d\n",
 +                         p_av->suspend.status, p_av->suspend.initiator);
 +
 +        /* a2dp suspended, stop media task until resumed */
 +        btif_a2dp_on_suspended(&p_av->suspend);
 +
 +        /* if not successful, remain in current state */
 +        if (p_av->suspend.status != BTA_AV_SUCCESS) {
 +            btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
 +
 +            return FALSE;
 +        }
 +
 +        if (p_av->suspend.initiator != TRUE) {
 +            /* remote suspend, notify HAL and await audioflinger to
 +               suspend/stop stream */
 +
 +            /* set remote suspend flag to block media task from restarting
 +               stream only if we did not already initiate a local suspend */
 +            if ((btif_av_cb.flags & BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING) == 0) {
 +                btif_av_cb.flags |= BTIF_AV_FLAG_REMOTE_SUSPEND;
 +            }
 +
 +            btif_report_audio_state(ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND, &(btif_av_cb.peer_bda));
 +        } else {
 +            btif_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda));
 +        }
 +
 +        btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
 +
 +        /* suspend completed and state changed, clear pending status */
 +        btif_av_cb.flags &= ~BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING;
 +        break;
 +
 +    case BTA_AV_STOP_EVT:
 +
 +        btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
 +        btif_a2dp_on_stopped(&p_av->suspend);
 +
 +        btif_report_audio_state(ESP_A2D_AUDIO_STATE_STOPPED, &(btif_av_cb.peer_bda));
 +
 +        /* if stop was successful, change state to open */
 +        if (p_av->suspend.status == BTA_AV_SUCCESS) {
 +            btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENED);
 +        }
 +
 +        break;
 +
 +    case BTA_AV_CLOSE_EVT:
 +
 +        btif_av_cb.flags |= BTIF_AV_FLAG_PENDING_STOP;
 +
 +        /* avdtp link is closed */
 +        btif_a2dp_on_stopped(NULL);
 +
 +        /* inform the application that we are disconnected */
 +        btif_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btif_av_cb.peer_bda));
 +
 +        btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_IDLE);
 +        break;
 +
 +        CHECK_RC_EVENT(event, p_data);
 +
 +    default:
 +        BTIF_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__,
 +                           dump_av_sm_event_name(event));
 +        return FALSE;
 +
 +    }
 +    return TRUE;
 +}
 +
 +/*****************************************************************************
 +**  Local event handlers
 +******************************************************************************/
 +
 +static void btif_av_handle_event(UINT16 event, char *p_param)
 +{
 +    btif_sm_dispatch(btif_av_cb.sm_handle, event, (void *)p_param);
 +    btif_av_event_free_data(event, p_param);
 +}
 +
 +void btif_av_event_deep_copy(UINT16 event, char *p_dest, char *p_src)
 +{
 +    tBTA_AV *av_src = (tBTA_AV *)p_src;
 +    tBTA_AV *av_dest = (tBTA_AV *)p_dest;
 +
 +    // First copy the structure
 +    memcpy(p_dest, p_src, sizeof(tBTA_AV));
 +
 +    switch (event) {
 +    case BTA_AV_META_MSG_EVT:
 +        if (av_src->meta_msg.p_data && av_src->meta_msg.len) {
 +            av_dest->meta_msg.p_data = osi_calloc(av_src->meta_msg.len);
 +            assert(av_dest->meta_msg.p_data);
 +            memcpy(av_dest->meta_msg.p_data, av_src->meta_msg.p_data, av_src->meta_msg.len);
 +        }
 +
 +        if (av_src->meta_msg.p_msg) {
 +            av_dest->meta_msg.p_msg = osi_calloc(sizeof(tAVRC_MSG));
 +            assert(av_dest->meta_msg.p_msg);
 +            memcpy(av_dest->meta_msg.p_msg, av_src->meta_msg.p_msg, sizeof(tAVRC_MSG));
 +
 +            if (av_src->meta_msg.p_msg->vendor.p_vendor_data &&
 +                    av_src->meta_msg.p_msg->vendor.vendor_len) {
 +                av_dest->meta_msg.p_msg->vendor.p_vendor_data = osi_calloc(
 +                            av_src->meta_msg.p_msg->vendor.vendor_len);
 +                assert(av_dest->meta_msg.p_msg->vendor.p_vendor_data);
 +                memcpy(av_dest->meta_msg.p_msg->vendor.p_vendor_data,
 +                       av_src->meta_msg.p_msg->vendor.p_vendor_data,
 +                       av_src->meta_msg.p_msg->vendor.vendor_len);
 +            }
 +        }
 +        break;
 +
 +    default:
 +        break;
 +    }
 +}
 +
 +static void btif_av_event_free_data(btif_sm_event_t event, void *p_data)
 +{
 +    switch (event) {
 +    case BTA_AV_META_MSG_EVT: {
 +        tBTA_AV *av = (tBTA_AV *)p_data;
 +        if (av->meta_msg.p_data) {
 +            osi_free(av->meta_msg.p_data);
 +        }
 +
 +        if (av->meta_msg.p_msg) {
 +            if (av->meta_msg.p_msg->vendor.p_vendor_data) {
 +                osi_free(av->meta_msg.p_msg->vendor.p_vendor_data);
 +            }
 +            osi_free(av->meta_msg.p_msg);
 +        }
 +    }
 +    break;
 +
 +    default:
 +        break;
 +    }
 +}
 +
 +static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data)
 +{
 +    btif_transfer_context(btif_av_handle_event, event,
 +                          (char *)p_data, sizeof(tBTA_AV), btif_av_event_deep_copy);
 +}
 +
 +static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data)
 +{
 +    btif_sm_state_t state;
 +    UINT8 que_len;
 +    tA2D_STATUS a2d_status;
 +    tA2D_SBC_CIE sbc_cie;
 +    esp_a2d_mcc_t mcc;
 +
 +    if (event == BTA_AV_MEDIA_DATA_EVT) { /* Switch to BTIF_MEDIA context */
 +        state = btif_sm_get_state(btif_av_cb.sm_handle);
 +        if ( (state == BTIF_AV_STATE_STARTED) || /* send SBC packets only in Started State */
 +                (state == BTIF_AV_STATE_OPENED) ) {
 +            que_len = btif_media_sink_enque_buf((BT_HDR *)p_data);
 +            BTIF_TRACE_DEBUG(" Packets in Que %d\n", que_len);
 +        } else {
 +            return;
 +        }
 +    }
 +
 +    if (event == BTA_AV_MEDIA_SINK_CFG_EVT) {
 +        /* send a command to BT Media Task */
 +        btif_reset_decoder((UINT8 *)p_data);
 +
 +      /* currently only supportes SBC */
 +        a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE);
 +        if (a2d_status == A2D_SUCCESS) {
 +            mcc.type = ESP_A2D_MCT_SBC;
 +            memcpy(&mcc.cie, (uint8_t *)p_data + 3, ESP_A2D_CIE_LEN_SBC);
 +            /* Switch to BTIF context */
 +            btif_transfer_context(btif_av_handle_event, BTIF_AV_SINK_CONFIG_REQ_EVT,
 +                                  (char *)&mcc, sizeof(mcc), NULL);
 +        } else {
 +            APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status);
 +        }
 +    }
 +}
 +/*******************************************************************************
 +**
 +** Function         btif_av_init
 +**
 +** Description      Initializes btif AV if not already done
 +**
 +** Returns          bt_status_t
 +**
 +*******************************************************************************/
 +
 +bt_status_t btif_av_init()
 +{
 +    if (btif_av_cb.sm_handle == NULL) {
 +        if (!btif_a2dp_start_media_task()) {
 +            return BT_STATUS_FAIL;
 +        }
 +
 +        /* Also initialize the AV state machine */
 +        btif_av_cb.sm_handle =
 +            btif_sm_init((const btif_sm_handler_t *)btif_av_state_handlers, BTIF_AV_STATE_IDLE);
 +
 +        btif_enable_service(BTA_A2DP_SOURCE_SERVICE_ID);
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +        btif_enable_service(BTA_A2DP_SINK_SERVICE_ID);
 +#endif
 +
 +        btif_a2dp_on_init();
 +    }
 +
 +    return BT_STATUS_SUCCESS;
 +}
 +
 +/**
 + *
 + * Function         register A2DP callback
 + *
 + * Description      Initializes the AV interface for sink mode
 + *
 + * Returns          bt_status_t
 + *
 + */
++esp_err_t esp_a2d_register_callback(esp_a2d_cb_t callback)
 +{
 +    // TODO: need protection against race
 +    bt_av_sink_callback = callback;
 +    return ESP_OK;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         init_sink
 +**
 +** Description      Initializes the AV interface for sink mode
 +**
 +** Returns          bt_status_t
 +**
 +*******************************************************************************/
 +esp_err_t esp_a2d_sink_init(void)
 +{
 +    BTIF_TRACE_EVENT("%s()\n", __func__);
 +
 +    bt_status_t status = btif_av_init();
 +
 +    return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         connect
 +**
 +** Description      Establishes the AV signalling channel with the remote headset
 +**
 +** Returns          bt_status_t
 +**
 +*******************************************************************************/
 +
 +static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid)
 +{
 +    btif_av_connect_req_t connect_req;
 +    connect_req.target_bda = bd_addr;
 +    connect_req.uuid = uuid;
 +    BTIF_TRACE_EVENT("%s\n", __FUNCTION__);
 +
 +    btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char *)&connect_req);
 +
 +    return BT_STATUS_SUCCESS;
 +}
 +
 +esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda)
 +{
 +    BTIF_TRACE_EVENT("%s\n", __FUNCTION__);
 +    CHECK_BTAV_INIT();
 +
 +    bt_status_t stat;
 +    bt_bdaddr_t bd_addr;
 +    memcpy(&bd_addr, remote_bda, sizeof(bt_bdaddr_t));
 +
 +    stat = btif_queue_connect(UUID_SERVCLASS_AUDIO_SINK, &bd_addr, connect_int);
 +    return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
 +}
 +
 +esp_err_t esp_a2d_sink_disconnect(esp_bd_addr_t remote_bda)
 +{
 +    bt_status_t stat;
 +    bt_bdaddr_t bd_addr;
 +    BTIF_TRACE_EVENT("%s\n", __FUNCTION__);
 +    CHECK_BTAV_INIT();
 +    memcpy(&bd_addr, remote_bda, sizeof(bt_bdaddr_t));
 +    /* Switch to BTIF context */
 +    stat = btif_transfer_context(btif_av_handle_event, BTIF_AV_DISCONNECT_REQ_EVT,
 +                                 (char *)(&bd_addr), sizeof(bt_bdaddr_t), NULL);
 +    return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
 +}
 +/*******************************************************************************
 +**
 +** Function         cleanup
 +**
 +** Description      Shuts down the AV interface and does the cleanup
 +**
 +** Returns          None
 +**
 +*******************************************************************************/
 +static void cleanup(void)
 +{
 +    BTIF_TRACE_EVENT("%s\n", __FUNCTION__);
 +
 +    btif_a2dp_stop_media_task();
 +
 +    btif_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +    btif_disable_service(BTA_A2DP_SINK_SERVICE_ID);
 +#endif
 +
 +    /* Also shut down the AV state machine */
 +    btif_sm_shutdown(btif_av_cb.sm_handle);
 +    btif_av_cb.sm_handle = NULL;
 +}
 +
 +void esp_a2d_sink_deinit(void)
 +{
 +    BTIF_TRACE_EVENT("%s\n", __FUNCTION__);
 +
 +    if (bt_av_sink_callback) {
 +        bt_av_sink_callback = NULL;
 +        cleanup();
 +    }
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_av_get_sm_handle
 +**
 +** Description      Fetches current av SM handle
 +**
 +** Returns          None
 +**
 +*******************************************************************************/
 +
 +btif_sm_handle_t btif_av_get_sm_handle(void)
 +{
 +    return btif_av_cb.sm_handle;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_av_stream_ready
 +**
 +** Description      Checks whether AV is ready for starting a stream
 +**
 +** Returns          None
 +**
 +*******************************************************************************/
 +
 +BOOLEAN btif_av_stream_ready(void)
 +{
 +    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
 +
 +    BTIF_TRACE_DEBUG("btif_av_stream_ready : sm hdl %d, state %d, flags %x\n",
 +                     (int)btif_av_cb.sm_handle, state, btif_av_cb.flags);
 +
 +    /* also make sure main adapter is enabled */
 +    if (btif_is_enabled() == 0) {
 +        BTIF_TRACE_EVENT("main adapter not enabled");
 +        return FALSE;
 +    }
 +
 +    /* check if we are remotely suspended or stop is pending */
 +    if (btif_av_cb.flags & (BTIF_AV_FLAG_REMOTE_SUSPEND | BTIF_AV_FLAG_PENDING_STOP)) {
 +        return FALSE;
 +    }
 +
 +    return (state == BTIF_AV_STATE_OPENED);
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_av_stream_started_ready
 +**
 +** Description      Checks whether AV ready for media start in streaming state
 +**
 +** Returns          None
 +**
 +*******************************************************************************/
 +
 +BOOLEAN btif_av_stream_started_ready(void)
 +{
 +    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
 +
 +    BTIF_TRACE_DEBUG("btif_av_stream_started : sm hdl %d, state %d, flags %x\n",
 +                     (int)btif_av_cb.sm_handle, state, btif_av_cb.flags);
 +
 +    /* disallow media task to start if we have pending actions */
 +    if (btif_av_cb.flags & (BTIF_AV_FLAG_LOCAL_SUSPEND_PENDING | BTIF_AV_FLAG_REMOTE_SUSPEND
 +                            | BTIF_AV_FLAG_PENDING_STOP)) {
 +        return FALSE;
 +    }
 +
 +    return (state == BTIF_AV_STATE_STARTED);
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_dispatch_sm_event
 +**
 +** Description      Send event to AV statemachine
 +**
 +** Returns          None
 +**
 +*******************************************************************************/
 +
 +/* used to pass events to AV statemachine from other tasks */
 +void btif_dispatch_sm_event(btif_av_sm_event_t event, void *p_data, int len)
 +{
 +    /* Switch to BTIF context */
 +    btif_transfer_context(btif_av_handle_event, event,
 +                          (char *)p_data, len, NULL);
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_av_execute_service
 +**
 +** Description      Initializes/Shuts down the service
 +**
 +** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
 +**
 +*******************************************************************************/
 +bt_status_t btif_av_execute_service(BOOLEAN b_enable)
 +{
 +    if (b_enable) {
 +        /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not
 +         * handle this request in order to allow incoming connections to succeed.
 +         * We need to put this back once support for this is added */
 +
 +        /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not
 +         * auto-suspend av streaming on AG events(SCO or Call). The suspend shall
 +         * be initiated by the app/audioflinger layers */
 +        BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_NO_SCO_SSPD)
 +                   // | BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR
 +                   | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL,
 +                     bte_av_callback);
 +        BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos);
 +    } else {
 +        BTA_AvDeregister(btif_av_cb.bta_handle);
 +        BTA_AvDisable();
 +    }
 +    return BT_STATUS_SUCCESS;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_av_sink_execute_service
 +**
 +** Description      Initializes/Shuts down the service
 +**
 +** Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise
 +**
 +*******************************************************************************/
 +bt_status_t btif_av_sink_execute_service(BOOLEAN b_enable)
 +{
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +    BTA_AvEnable_Sink(b_enable);
 +#endif
 +    return BT_STATUS_SUCCESS;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_av_is_connected
 +**
 +** Description      Checks if av has a connected sink
 +**
 +** Returns          BOOLEAN
 +**
 +*******************************************************************************/
 +BOOLEAN btif_av_is_connected(void)
 +{
 +    btif_sm_state_t state = btif_sm_get_state(btif_av_cb.sm_handle);
 +    return ((state == BTIF_AV_STATE_OPENED) || (state ==  BTIF_AV_STATE_STARTED));
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_av_is_peer_edr
 +**
 +** Description      Check if the connected a2dp device supports
 +**                  EDR or not. Only when connected this function
 +**                  will accurately provide a true capability of
 +**                  remote peer. If not connected it will always be false.
 +**
 +** Returns          TRUE if remote device is capable of EDR
 +**
 +*******************************************************************************/
 +BOOLEAN btif_av_is_peer_edr(void)
 +{
 +    ASSERTC(btif_av_is_connected(), "No active a2dp connection\n", 0);
 +
 +    if (btif_av_cb.edr) {
 +        return TRUE;
 +    } else {
 +        return FALSE;
 +    }
 +}
 +
 +/******************************************************************************
 +**
 +** Function        btif_av_clear_remote_suspend_flag
 +**
 +** Description     Clears btif_av_cd.flags if BTIF_AV_FLAG_REMOTE_SUSPEND is set
 +**
 +** Returns          void
 +******************************************************************************/
 +void btif_av_clear_remote_suspend_flag(void)
 +{
 +    BTIF_TRACE_DEBUG("%s: flag :%x\n", __func__, btif_av_cb.flags);
 +    btif_av_cb.flags &= ~BTIF_AV_FLAG_REMOTE_SUSPEND;
 +}
index b2ff5ccd6cac16520cf45d9752f94f376dd12403,0000000000000000000000000000000000000000..f9d3a05739abd2bd2dbfc80c5ac48939eb1ecc4f
mode 100644,000000..100644
--- /dev/null
@@@ -1,481 -1,0 +1,481 @@@
-     xTaskCreate(btif_task_thread_handler, "BtifT", 2048, NULL, configMAX_PRIORITIES - 1, &xBtifTaskHandle);
 +/******************************************************************************
 + *
 + *  Copyright (C) 2014 The Android Open Source Project
 + *  Copyright (C) 2009-2012 Broadcom Corporation
 + *
 + *  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.
 + *
 + ******************************************************************************/
 +
 +/************************************************************************************
 + *
 + *  Filename:      btif_core.c
 + *
 + *  Description:   Contains core functionality related to interfacing between
 + *                 Bluetooth HAL and BTE core stack.
 + *
 + ***********************************************************************************/
 +
 +#include <ctype.h>
 +// #include <cutils/properties.h>
 +// #include <dirent.h>
 +// #include <fcntl.h>
 +// #include <hardware/bluetooth.h>
 +#include <stdlib.h>
 +#include <string.h>
 +// #include <sys/stat.h>
 +// #include <sys/types.h>
 +
 +#define LOG_TAG "bt_btif_core"
 +// #include "btcore/include/bdaddr.h"
 +
 +#include "bdaddr.h"
 +// #include "bt_utils.h"
 +#include "bta_api.h"
 +#include "bte.h"
 +#include "btif_api.h"
 +// #include "btif_av.h"
 +// #include "btif_config.h"
 +// #include "btif_pan.h"
 +// #include "btif_profile_queue.h"
 +// #include "btif_config.h"
 +// #include "btif_sock.h"
 +// #include "btif_storage.h"
 +#include "btif_util.h"
 +#include "btu.h"
 +#include "controller.h"
 +#include "fixed_queue.h"
 +#include "future.h"
 +#include "gki.h"
 +#include "osi.h"
 +// #include "osi/include/log.h"
 +#include "stack_manager.h"
 +#include "thread.h"
 +#include "btif_common.h"
 +#include "btif_dm.h"
 +/************************************************************************************
 +**  Constants & Macros
 +************************************************************************************/
 +
 +/************************************************************************************
 +**  Local type definitions
 +************************************************************************************/
 +
 +/************************************************************************************
 +**  Static variables
 +************************************************************************************/
 +
 +static tBTA_SERVICE_MASK btif_enabled_services = 0;
 +
 +static fixed_queue_t *btif_msg_queue = NULL;
 +static xTaskHandle  xBtifTaskHandle = NULL;
 +
 +/************************************************************************************
 +**  Static functions
 +************************************************************************************/
 +
 +/* sends message to btif task */
 +static void btif_sendmsg(void *p_msg);
 +static void btif_thread_post(uint32_t sig);
 +/************************************************************************************
 +**  Externs
 +************************************************************************************/
 +static fixed_queue_t *xBtifQueue = NULL;
 +
 +/** TODO: Move these to _common.h */
 +void bte_main_boot_entry(void *);
 +void bte_main_disable(void);
 +void bte_main_shutdown(void);
 +void btif_dm_execute_service_request(UINT16 event, char *p_param);
 +
 +/*******************************************************************************
 +**
 +** Function         btif_context_switched
 +**
 +** Description      Callback used to execute transferred context callback
 +**
 +**                  p_msg : message to be executed in btif context
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +
 +static void btif_context_switched(void *p_msg)
 +{
 +
 +    BTIF_TRACE_VERBOSE("btif_context_switched");
 +
 +    tBTIF_CONTEXT_SWITCH_CBACK *p = (tBTIF_CONTEXT_SWITCH_CBACK *) p_msg;
 +
 +    /* each callback knows how to parse the data */
 +    if (p->p_cb) {
 +        p->p_cb(p->event, p->p_param);
 +    }
 +}
 +
 +
 +/*******************************************************************************
 +**
 +** Function         btif_transfer_context
 +**
 +** Description      This function switches context to btif task
 +**
 +**                  p_cback   : callback used to process message in btif context
 +**                  event     : event id of message
 +**                  p_params  : parameter area passed to callback (copied)
 +**                  param_len : length of parameter area
 +**                  p_copy_cback : If set this function will be invoked for deep copy
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +
 +bt_status_t btif_transfer_context (tBTIF_CBACK *p_cback, UINT16 event, char *p_params, int param_len, tBTIF_COPY_CBACK *p_copy_cback)
 +{
 +    tBTIF_CONTEXT_SWITCH_CBACK *p_msg;
 +
 +    BTIF_TRACE_VERBOSE("btif_transfer_context event %d, len %d", event, param_len);
 +
 +    /* allocate and send message that will be executed in btif context */
 +    if ((p_msg = (tBTIF_CONTEXT_SWITCH_CBACK *) GKI_getbuf(sizeof(tBTIF_CONTEXT_SWITCH_CBACK) + param_len)) != NULL) {
 +        p_msg->hdr.event = BT_EVT_CONTEXT_SWITCH_EVT; /* internal event */
 +        p_msg->p_cb = p_cback;
 +
 +        p_msg->event = event;                         /* callback event */
 +
 +        /* check if caller has provided a copy callback to do the deep copy */
 +        if (p_copy_cback) {
 +            p_copy_cback(event, p_msg->p_param, p_params);
 +        } else if (p_params) {
 +            memcpy(p_msg->p_param, p_params, param_len);  /* callback parameter data */
 +        }
 +
 +        btif_sendmsg(p_msg);
 +        return BT_STATUS_SUCCESS;
 +    } else {
 +        /* let caller deal with a failed allocation */
 +        return BT_STATUS_NOMEM;
 +    }
 +}
 +
 +int btif_is_enabled(void)
 +{
 +    return (stack_manager_is_stack_running());
 +}
 +
 +void btif_init_ok(void)
 +{
 +    BTIF_TRACE_DEBUG("btif_task: received trigger stack init event");
 +    future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS);
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_enable_bluetooth_evt
 +**
 +** Description      Event indicating bluetooth enable is completed
 +**                  Notifies HAL user with updated adapter state
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +
 +void btif_enable_bluetooth_evt(tBTA_STATUS status)
 +{
 +    if (status == BTA_SUCCESS) {
 +        future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS);
 +    } else {
 +        future_ready(stack_manager_get_hack_future(), FUTURE_FAIL);
 +    }
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_disable_bluetooth_evt
 +**
 +** Description      Event notifying BT disable is now complete.
 +**                  Terminates main stack tasks and notifies HAL
 +**                  user with updated BT state.
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +
 +void btif_disable_bluetooth_evt(void)
 +{
 +    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
 +
 +    /* callback to HAL */
 +    future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS);
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_task
 +**
 +** Description      BTIF task handler managing all messages being passed
 +**                  Bluetooth HAL and BTA.
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +static void bt_jni_msg_ready(fixed_queue_t *queue)
 +{
 +    BT_HDR *p_msg;
 +    while (!fixed_queue_is_empty(queue)) {
 +        p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
 +        BTIF_TRACE_VERBOSE("btif task fetched event %x", p_msg->event);
 +        switch (p_msg->event) {
 +        case BT_EVT_CONTEXT_SWITCH_EVT:
 +            btif_context_switched(p_msg);
 +            break;
 +        default:
 +            BTIF_TRACE_ERROR("unhandled btif event (%d)", p_msg->event & BT_EVT_MASK);                      break;
 +        }
 +        GKI_freebuf(p_msg);
 +    }
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_sendmsg
 +**
 +** Description      Sends msg to BTIF task
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +
 +void btif_sendmsg(void *p_msg)
 +{
 +    fixed_queue_enqueue(btif_msg_queue, p_msg);
 +    btif_thread_post(SIG_BTIF_WORK);
 +}
 +
 +static void btif_thread_post(uint32_t sig)
 +{
 +    BtTaskEvt_t *evt = (BtTaskEvt_t *)osi_malloc(sizeof(BtTaskEvt_t));
 +    if (evt == NULL) {
 +        return;
 +    }
 +
 +    evt->sig = sig;
 +    evt->par = 0;
 +
 +    if (xQueueSend(xBtifQueue, &evt, 10 / portTICK_RATE_MS) != pdTRUE) {
 +        ets_printf("xBtifQueue failed\n");
 +    }
 +}
 +
 +/*****************************************************************************
 +**
 +** Function         btif_task_thread_handler
 +**
 +** Description      Process BTif Task Thread.
 +******************************************************************************/
 +void btif_task_thread_handler(void *arg)
 +{
 +    BtTaskEvt_t *e;
 +    for (;;) {
 +        if (pdTRUE == xQueueReceive(xBtifQueue, &e, (portTickType)portMAX_DELAY)) {
 +            if (e->sig == SIG_BTIF_WORK) {
 +                fixed_queue_process(btif_msg_queue);
 +            }
 +            osi_free(e);
 +        }
 +    }
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_init_bluetooth
 +**
 +** Description      Creates BTIF task and prepares BT scheduler for startup
 +**
 +** Returns          bt_status_t
 +**
 +*******************************************************************************/
 +bt_status_t btif_init_bluetooth(void)
 +{
 +    bte_main_boot_entry(btif_init_ok);
 +
 +    btif_msg_queue = fixed_queue_new(SIZE_MAX);
 +    if (btif_msg_queue == NULL) {
 +        goto error_exit;
 +    }
 +    xBtifQueue = xQueueCreate(60, sizeof(void *));
++    xTaskCreatePinnedToCore(btif_task_thread_handler, "BtifT", 2048, NULL, configMAX_PRIORITIES - 1, &xBtifTaskHandle, 0);
 +    fixed_queue_register_dequeue(btif_msg_queue, bt_jni_msg_ready);
 +
 +    return BT_STATUS_SUCCESS;
 +
 +error_exit:;
 +    btif_shutdown_bluetooth();
 +
 +    return BT_STATUS_FAIL;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_enable_bluetooth
 +**
 +** Description      Inititates shutdown of Bluetooth system.
 +**                  Any active links will be dropped and device entering
 +**                  non connectable/discoverable mode
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +bt_status_t btif_enable_bluetooth(void)
 +{
 +    BTIF_TRACE_DEBUG("BTIF ENABLE BLUETOOTH");
 +
 +    BTA_EnableBluetooth(bte_dm_evt);
 +
 +    return BT_STATUS_SUCCESS;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_disable_bluetooth
 +**
 +** Description      Inititates shutdown of Bluetooth system.
 +**                  Any active links will be dropped and device entering
 +**                  non connectable/discoverable mode
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +bt_status_t btif_disable_bluetooth(void)
 +{
 +    BTIF_TRACE_DEBUG("BTIF DISABLE BLUETOOTH");
 +
 +    // btif_dm_on_disable();
 +    /* cleanup rfcomm & l2cap api */
 +    // btif_sock_cleanup();
 +    // btif_pan_cleanup();
 +    BTA_DisableBluetooth();
 +
 +    return BT_STATUS_SUCCESS;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_shutdown_bluetooth
 +**
 +** Description      Finalizes BT scheduler shutdown and terminates BTIF
 +**                  task.
 +**
 +** Returns          void
 +**
 +*******************************************************************************/
 +
 +bt_status_t btif_shutdown_bluetooth(void)
 +{
 +    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
 +
 +    fixed_queue_unregister_dequeue(btif_msg_queue);
 +    fixed_queue_free(btif_msg_queue, NULL);
 +    btif_msg_queue = NULL;
 +
 +    vTaskDelete(xBtifTaskHandle);
 +    xBtifTaskHandle = NULL;
 +
 +    vQueueDelete(xBtifQueue);
 +    xBtifQueue = NULL;
 +
 +    bte_main_shutdown();
 +
 +    return BT_STATUS_SUCCESS;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_get_enabled_services_mask
 +**
 +** Description      Fetches currently enabled services
 +**
 +** Returns          tBTA_SERVICE_MASK
 +**
 +*******************************************************************************/
 +
 +tBTA_SERVICE_MASK btif_get_enabled_services_mask(void)
 +{
 +    return btif_enabled_services;
 +}
 +
 +/*******************************************************************************
 +**
 +** Function         btif_enable_service
 +**
 +** Description      Enables the service 'service_ID' to the service_mask.
 +**                  Upon BT enable, BTIF core shall invoke the BTA APIs to
 +**                  enable the profiles
 +**
 +** Returns          bt_status_t
 +**
 +*******************************************************************************/
 +bt_status_t btif_enable_service(tBTA_SERVICE_ID service_id)
 +{
 +    tBTA_SERVICE_ID *p_id = &service_id;
 +
 +    /* If BT is enabled, we need to switch to BTIF context and trigger the
 +     * enable for that profile
 +     *
 +     * Otherwise, we just set the flag. On BT_Enable, the DM will trigger
 +     * enable for the profiles that have been enabled */
 +
 +    btif_enabled_services |= (1 << service_id);
 +
 +    BTIF_TRACE_DEBUG("%s: current services:0x%x", __FUNCTION__, btif_enabled_services);
 +
 +    if (btif_is_enabled()) {
 +        btif_transfer_context(btif_dm_execute_service_request,
 +                              BTIF_DM_ENABLE_SERVICE,
 +                              (char *)p_id, sizeof(tBTA_SERVICE_ID), NULL);
 +    }
 +
 +    return BT_STATUS_SUCCESS;
 +}
 +/*******************************************************************************
 +**
 +** Function         btif_disable_service
 +**
 +** Description      Disables the service 'service_ID' to the service_mask.
 +**                  Upon BT disable, BTIF core shall invoke the BTA APIs to
 +**                  disable the profiles
 +**
 +** Returns          bt_status_t
 +**
 +*******************************************************************************/
 +bt_status_t btif_disable_service(tBTA_SERVICE_ID service_id)
 +{
 +    tBTA_SERVICE_ID *p_id = &service_id;
 +
 +    /* If BT is enabled, we need to switch to BTIF context and trigger the
 +     * disable for that profile so that the appropriate uuid_property_changed will
 +     * be triggerred. Otherwise, we just need to clear the service_id in the mask
 +     */
 +
 +    btif_enabled_services &=  (tBTA_SERVICE_MASK)(~(1 << service_id));
 +
 +    BTIF_TRACE_DEBUG("%s: Current Services:0x%x", __FUNCTION__, btif_enabled_services);
 +
 +    if (btif_is_enabled()) {
 +        btif_transfer_context(btif_dm_execute_service_request,
 +                              BTIF_DM_DISABLE_SERVICE,
 +                              (char *)p_id, sizeof(tBTA_SERVICE_ID), NULL);
 +    }
 +
 +    return BT_STATUS_SUCCESS;
 +}
index 992a324b10c47bfeceffba18eaea0004752aa4f1,0000000000000000000000000000000000000000..87189b250d85385c5110d3a7d5432aafa27dc3ac
mode 100644,000000..100644
--- /dev/null
@@@ -1,1213 -1,0 +1,1213 @@@
-     xTaskCreate(btif_media_task_handler, "BtifMediaT\n", 2048, NULL, configMAX_PRIORITIES - 1, &xBtifMediaTaskHandle);
 +/******************************************************************************
 + *
 + *  Copyright (C) 2009-2012 Broadcom Corporation
 + *
 + *  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.
 + *
 + ******************************************************************************/
 +
 +/******************************************************************************
 + **
 + **  Name:          btif_media_task.c
 + **
 + **  Description:   This is the multimedia module for the BTIF system.  It
 + **                 contains task implementations AV, HS and HF profiles
 + **                 audio & video processing
 + **
 + ******************************************************************************/
 +
 +#define LOG_TAG "bt_btif_media"
 +
 +#include "bt_trace.h"
 +#include <string.h>
 +#include <stdio.h>
 +#include <stdint.h>
 +
 +#include "bt_target.h"
 +#include "fixed_queue.h"
 +#include "gki.h"
 +#include "bta_api.h"
 +#include "btu.h"
 +#include "bta_sys.h"
 +#include "bta_sys_int.h"
 +
 +#include "bta_av_api.h"
 +#include "a2d_api.h"
 +#include "a2d_sbc.h"
 +#include "a2d_int.h"
 +#include "bta_av_sbc.h"
 +#include "bta_av_ci.h"
 +#include "l2c_api.h"
 +
 +#include "btif_av_co.h"
 +#include "btif_media.h"
 +
 +#include "alarm.h"
 +#include "bt_trace.h"
 +#include "thread.h"
 +
 +#include "bt_defs.h"
 +#include "btif_av.h"
 +#include "btif_sm.h"
 +#include "btif_util.h"
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +#include "oi_codec_sbc.h"
 +#include "oi_status.h"
 +#endif
 +#include "stdio.h"
 +
 +#include "btif_media.h"
 +#include "allocator.h"
 +#include "bt_utils.h"
 +#include "esp_a2dp_api.h"
 +
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +OI_CODEC_SBC_DECODER_CONTEXT context;
 +OI_UINT32 contextData[CODEC_DATA_WORDS(2, SBC_CODEC_FAST_FILTER_BUFFERS)];
 +OI_INT16 pcmData[15 * SBC_MAX_SAMPLES_PER_FRAME * SBC_MAX_CHANNELS];
 +#endif
 +
 +
 +/*****************************************************************************
 + **  Constants
 + *****************************************************************************/
 +
 +#ifndef AUDIO_CHANNEL_OUT_MONO
 +#define AUDIO_CHANNEL_OUT_MONO 0x01
 +#endif
 +
 +#ifndef AUDIO_CHANNEL_OUT_STEREO
 +#define AUDIO_CHANNEL_OUT_STEREO 0x03
 +#endif
 +
 +/* BTIF media cmd event definition : BTIF_MEDIA_TASK_CMD */
 +enum {
 +    BTIF_MEDIA_START_AA_TX = 1,
 +    BTIF_MEDIA_STOP_AA_TX,
 +    BTIF_MEDIA_AA_RX_RDY,
 +    BTIF_MEDIA_UIPC_RX_RDY,
 +    BTIF_MEDIA_SBC_ENC_INIT,
 +    BTIF_MEDIA_SBC_ENC_UPDATE,
 +    BTIF_MEDIA_SBC_DEC_INIT,
 +    BTIF_MEDIA_VIDEO_DEC_INIT,
 +    BTIF_MEDIA_FLUSH_AA_TX,
 +    BTIF_MEDIA_FLUSH_AA_RX,
 +    BTIF_MEDIA_AUDIO_FEEDING_INIT,
 +    BTIF_MEDIA_AUDIO_RECEIVING_INIT,
 +    BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE,
 +    BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK
 +};
 +
 +enum {
 +    MEDIA_TASK_STATE_OFF = 0,
 +    MEDIA_TASK_STATE_ON = 1,
 +    MEDIA_TASK_STATE_SHUTTING_DOWN = 2
 +};
 +
 +enum {
 +    SIG_MEDIA_TASK_INIT = 0xf0,
 +    SIG_MEDIA_TASK_CLEAN_UP = 0xf1,
 +    SIG_MEDIA_TASK_AVK_ALARM_TO = 0xf2,
 +    SIG_MEDIA_TASK_AA_ALARM_TO = 0xf3,
 +    SIG_MEDIA_TASK_CMD_READY = 0xf4
 +};
 +
 +/* Macro to multiply the media task tick */
 +#ifndef BTIF_MEDIA_NUM_TICK
 +#define BTIF_MEDIA_NUM_TICK      1
 +#endif
 +
 +/* Media task tick in milliseconds, must be set to multiple of
 +   (1000/TICKS_PER_SEC) (10) */
 +
 +#define BTIF_MEDIA_TIME_TICK                     (20 * BTIF_MEDIA_NUM_TICK)
 +#define A2DP_DATA_READ_POLL_MS    (BTIF_MEDIA_TIME_TICK / 2)
 +#define BTIF_SINK_MEDIA_TIME_TICK                (20 * BTIF_MEDIA_NUM_TICK)
 +
 +
 +/* buffer pool */
 +#define BTIF_MEDIA_AA_POOL_ID GKI_POOL_ID_3
 +#define BTIF_MEDIA_AA_BUF_SIZE GKI_BUF3_SIZE
 +
 +/* offset */
 +#if (BTA_AV_CO_CP_SCMS_T == TRUE)
 +#define BTIF_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE + 1)
 +#else
 +#define BTIF_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE)
 +#endif
 +
 +/* Define the bitrate step when trying to match bitpool value */
 +#ifndef BTIF_MEDIA_BITRATE_STEP
 +#define BTIF_MEDIA_BITRATE_STEP 5
 +#endif
 +
 +/* Middle quality quality setting @ 44.1 khz */
 +#define DEFAULT_SBC_BITRATE 328
 +
 +#ifndef BTIF_A2DP_NON_EDR_MAX_RATE
 +#define BTIF_A2DP_NON_EDR_MAX_RATE 229
 +#endif
 +
 +#define USEC_PER_SEC 1000000L
 +#define TPUT_STATS_INTERVAL_US (3000*1000)
 +
 +/*
 + * CONGESTION COMPENSATION CTRL ::
 + *
 + * Thus setting controls how many buffers we will hold in media task
 + * during temp link congestion. Together with the stack buffer queues
 + * it controls much temporary a2dp link congestion we can
 + * compensate for. It however also depends on the default run level of sinks
 + * jitterbuffers. Depending on type of sink this would vary.
 + * Ideally the (SRC) max tx buffer capacity should equal the sinks
 + * jitterbuffer runlevel including any intermediate buffers on the way
 + * towards the sinks codec.
 + */
 +
 +/* fixme -- define this in pcm time instead of buffer count */
 +
 +/* The typical runlevel of the tx queue size is ~1 buffer
 +   but due to link flow control or thread preemption in lower
 +   layers we might need to temporarily buffer up data */
 +
 +/* 18 frames is equivalent to 6.89*18*2.9 ~= 360 ms @ 44.1 khz, 20 ms mediatick */
 +#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ 18
 +
 +#ifndef MAX_PCM_FRAME_NUM_PER_TICK
 +#define MAX_PCM_FRAME_NUM_PER_TICK     14
 +#endif
 +
 +/* In case of A2DP SINK, we will delay start by 5 AVDTP Packets*/
 +#define MAX_A2DP_DELAYED_START_FRAME_COUNT 5
 +#define PACKET_PLAYED_PER_TICK_48 8
 +#define PACKET_PLAYED_PER_TICK_44 7
 +#define PACKET_PLAYED_PER_TICK_32 5
 +#define PACKET_PLAYED_PER_TICK_16 3
 +
 +typedef struct {
 +    UINT16 num_frames_to_be_processed;
 +    UINT16 len;
 +    UINT16 offset;
 +    UINT16 layer_specific;
 +} tBT_SBC_HDR;
 +
 +typedef struct {
 +    UINT32 aa_frame_counter;
 +    INT32  aa_feed_counter;
 +    INT32  aa_feed_residue;
 +    UINT32 counter;
 +    UINT32 bytes_per_tick;  /* pcm bytes read each media task tick */
 +} tBTIF_AV_MEDIA_FEEDINGS_PCM_STATE;
 +
 +typedef union {
 +    tBTIF_AV_MEDIA_FEEDINGS_PCM_STATE pcm;
 +} tBTIF_AV_MEDIA_FEEDINGS_STATE;
 +
 +typedef struct {
 +#if (BTA_AV_INCLUDED == TRUE)
 +    BUFFER_Q RxSbcQ;
 +    BOOLEAN is_tx_timer;
 +    BOOLEAN is_rx_timer;
 +    UINT8 busy_level;
 +    void *av_sm_hdl;
 +    UINT8 a2dp_cmd_pending; /* we can have max one command pending */
 +    BOOLEAN rx_flush; /* discards any incoming data when true */
 +    UINT8 peer_sep;
 +    BOOLEAN data_channel_open;
 +    UINT8   frames_to_process;
 +
 +    UINT32  sample_rate;
 +    UINT8   channel_count;
 +    osi_alarm_t *decode_alarm;
 +#endif
 +
 +} tBTIF_MEDIA_CB;
 +
 +typedef struct {
 +    long long rx;
 +    long long rx_tot;
 +    long long tx;
 +    long long tx_tot;
 +    long long ts_prev_us;
 +} t_stat;
 +
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +extern OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context,
 +        const OI_BYTE **frameData,
 +        unsigned long *frameBytes,
 +        OI_INT16 *pcmData,
 +        unsigned long *pcmBytes);
 +extern OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context,
 +        unsigned long *decoderData,
 +        unsigned long decoderDataBytes,
 +        OI_UINT8 maxChannels,
 +        OI_UINT8 pcmStride,
 +        OI_BOOL enhanced);
 +#endif
 +static void btif_media_flush_q(BUFFER_Q *p_q);
 +static void btif_media_task_aa_handle_stop_decoding(void );
 +static void btif_media_task_aa_rx_flush(void);
 +
 +static const char *dump_media_event(UINT16 event);
 +static void btif_media_thread_handle_cmd(fixed_queue_t *queue);
 +
 +/* Handle incoming media packets A2DP SINK streaming*/
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +static void btif_media_task_handle_inc_media(tBT_SBC_HDR *p_msg);
 +#endif
 +
 +#if (BTA_AV_INCLUDED == TRUE)
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +static void btif_media_task_aa_handle_decoder_reset(BT_HDR *p_msg);
 +static void btif_media_task_aa_handle_clear_track(void);
 +#endif
 +static void btif_media_task_aa_handle_start_decoding(void);
 +#endif
 +BOOLEAN btif_media_task_clear_track(void);
 +static void btif_media_task_handler(void *arg);
 +
 +static void btif_media_task_avk_handle_timer(UNUSED_ATTR void *context);
 +static void btif_media_thread_init(UNUSED_ATTR void *context);
 +static void btif_media_thread_cleanup(UNUSED_ATTR void *context);
 +extern BOOLEAN btif_hf_is_call_idle();
 +
 +static tBTIF_MEDIA_CB btif_media_cb;
 +static int media_task_running = MEDIA_TASK_STATE_OFF;
 +
 +static fixed_queue_t *btif_media_cmd_msg_queue = NULL;
 +static xTaskHandle  xBtifMediaTaskHandle = NULL;
 +static QueueHandle_t xBtifMediaQueue = NULL;
 +
 +static esp_a2d_data_cb_t bt_av_sink_data_callback = NULL;
 +
 +esp_err_t esp_a2d_register_data_callback(esp_a2d_data_cb_t cb)
 +{
 +    // TODO: need protection against race
 +    bt_av_sink_data_callback = cb;
 +    return ESP_OK;
 +}
 +
 +// TODO: need protection against race
 +#define BTIF_A2D_DATA_CB_TO_APP(data, len)    do { \
 +      if (bt_av_sink_data_callback) { \
 +          bt_av_sink_data_callback(data, len); \
 +      } \
 +    } while (0)
 +
 +/*****************************************************************************
 + **  temporary hacked functions. TODO: port these functions or remove them?
 + *****************************************************************************/
 +BOOLEAN btif_hf_is_call_idle(void)
 +{
 +    return FALSE;
 +}
 +
 +/*****************************************************************************
 + **  Misc helper functions
 + *****************************************************************************/
 +
 +UNUSED_ATTR static const char *dump_media_event(UINT16 event)
 +{
 +    switch (event) {
 +        CASE_RETURN_STR(BTIF_MEDIA_START_AA_TX)
 +        CASE_RETURN_STR(BTIF_MEDIA_STOP_AA_TX)
 +        CASE_RETURN_STR(BTIF_MEDIA_AA_RX_RDY)
 +        CASE_RETURN_STR(BTIF_MEDIA_UIPC_RX_RDY)
 +        CASE_RETURN_STR(BTIF_MEDIA_SBC_ENC_INIT)
 +        CASE_RETURN_STR(BTIF_MEDIA_SBC_ENC_UPDATE)
 +        CASE_RETURN_STR(BTIF_MEDIA_SBC_DEC_INIT)
 +        CASE_RETURN_STR(BTIF_MEDIA_VIDEO_DEC_INIT)
 +        CASE_RETURN_STR(BTIF_MEDIA_FLUSH_AA_TX)
 +        CASE_RETURN_STR(BTIF_MEDIA_FLUSH_AA_RX)
 +        CASE_RETURN_STR(BTIF_MEDIA_AUDIO_FEEDING_INIT)
 +        CASE_RETURN_STR(BTIF_MEDIA_AUDIO_RECEIVING_INIT)
 +        CASE_RETURN_STR(BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE)
 +        CASE_RETURN_STR(BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK)
 +
 +    default:
 +        return "UNKNOWN MEDIA EVENT";
 +    }
 +}
 +
 +/*****************************************************************************
 + **  A2DP CTRL PATH
 + *****************************************************************************/
 +#if 0
 +// TODO: consider the necessity to add an API based on this function
 +static void btif_audiopath_detached(void)
 +{
 +    APPL_TRACE_EVENT("## AUDIO PATH DETACHED ##");
 +
 +    /*  send stop request only if we are actively streaming and haven't received
 +        a stop request. Potentially audioflinger detached abnormally */
 +    if (btif_media_cb.is_tx_timer) {
 +        /* post stop event and wait for audio path to stop */
 +        btif_dispatch_sm_event(BTIF_AV_STOP_STREAM_REQ_EVT, NULL, 0);
 +    }
 +}
 +#endif
 +
 +/*****************************************************************************
 + **  BTIF ADAPTATION
 + *****************************************************************************/
 +
 +static void btif_media_task_post(uint32_t sig)
 +{
 +    BtTaskEvt_t *evt = (BtTaskEvt_t *)osi_malloc(sizeof(BtTaskEvt_t));
 +    if (evt == NULL) {
 +        return;
 +    }
 +
 +    evt->sig = sig;
 +    evt->par = 0;
 +
 +    if (xQueueSend(xBtifMediaQueue, &evt, 10 / portTICK_RATE_MS) != pdTRUE) {
 +        APPL_TRACE_ERROR("xBtifMediaQueue failed\n");
 +    }
 +}
 +
 +static void btif_media_task_handler(void *arg)
 +{
 +    BtTaskEvt_t *e;
 +    for (;;) {
 +        if (pdTRUE == xQueueReceive(xBtifMediaQueue, &e, (portTickType)portMAX_DELAY)) {
 +            // LOG_ERROR("med evt %d\n", e->sig);
 +            switch (e->sig) {
 +            case SIG_MEDIA_TASK_AVK_ALARM_TO:
 +                btif_media_task_avk_handle_timer(NULL);
 +                break;
 +            case SIG_MEDIA_TASK_CMD_READY:
 +                fixed_queue_process(btif_media_cmd_msg_queue);
 +                break;
 +            case SIG_MEDIA_TASK_INIT:
 +                btif_media_thread_init(NULL);
 +                break;
 +            case SIG_MEDIA_TASK_CLEAN_UP:
 +                btif_media_thread_cleanup(NULL);
 +                break;
 +            default:
 +                APPL_TRACE_ERROR("media task unhandled evt: 0x%x\n", e->sig);
 +            }
 +        }
 +        osi_free(e);
 +    }
 +}
 +
 +bool btif_a2dp_start_media_task(void)
 +{
 +    if (media_task_running != MEDIA_TASK_STATE_OFF) {
 +        APPL_TRACE_ERROR("warning : media task already running");
 +        return false;
 +    }
 +
 +    APPL_TRACE_EVENT("## A2DP START MEDIA THREAD ##");
 +
 +    btif_media_cmd_msg_queue = fixed_queue_new(SIZE_MAX);
 +    if (btif_media_cmd_msg_queue == NULL) {
 +        goto error_exit;
 +    }
 +
 +    xBtifMediaQueue = xQueueCreate(60, sizeof(void *));
 +    if (xBtifMediaQueue == 0) {
 +        goto error_exit;
 +    }
++    xTaskCreatePinnedToCore(btif_media_task_handler, "BtifMediaT\n", 2048, NULL, configMAX_PRIORITIES - 1, &xBtifMediaTaskHandle, 0);
 +    if (xBtifMediaTaskHandle == NULL) {
 +        goto error_exit;
 +    }
 +    fixed_queue_register_dequeue(btif_media_cmd_msg_queue, btif_media_thread_handle_cmd);
 +    btif_media_task_post(SIG_MEDIA_TASK_INIT);
 +
 +    APPL_TRACE_EVENT("## A2DP MEDIA THREAD STARTED ##\n");
 +
 +    return true;
 +
 +error_exit:;
 +    APPL_TRACE_ERROR("%s unable to start up media thread\n", __func__);
 +
 +    if (xBtifMediaTaskHandle != NULL) {
 +        vTaskDelete(xBtifMediaTaskHandle);
 +        xBtifMediaTaskHandle = NULL;
 +    }
 +
 +    if (xBtifMediaQueue != 0) {
 +        vQueueDelete(xBtifMediaQueue);
 +        xBtifMediaQueue = 0;
 +    }
 +    fixed_queue_free(btif_media_cmd_msg_queue, NULL);
 +    btif_media_cmd_msg_queue = NULL;
 +    return false;
 +}
 +
 +void btif_a2dp_stop_media_task(void)
 +{
 +    APPL_TRACE_EVENT("## A2DP STOP MEDIA THREAD ##\n");
 +
 +    // Exit thread
 +    btif_media_task_post(SIG_MEDIA_TASK_CLEAN_UP);
 +    // TODO: wait until CLEAN up is done, then do task delete
 +    vTaskDelete(xBtifMediaTaskHandle);
 +    xBtifMediaTaskHandle = NULL;
 +    vQueueDelete(xBtifMediaQueue);
 +    xBtifMediaQueue = NULL;
 +
 +    fixed_queue_free(btif_media_cmd_msg_queue, NULL);
 +    btif_media_cmd_msg_queue = NULL;
 +}
 +
 +/*****************************************************************************
 +**
 +** Function        btif_a2dp_on_init
 +**
 +** Description
 +**
 +** Returns
 +**
 +*******************************************************************************/
 +
 +void btif_a2dp_on_init(void)
 +{
 +    //tput_mon(1, 0, 1);
 +}
 +
 +
 +/*****************************************************************************
 +**
 +** Function        btif_a2dp_setup_codec
 +**
 +** Description
 +**
 +** Returns
 +**
 +*******************************************************************************/
 +
 +void btif_a2dp_setup_codec(void)
 +{
 +    tBTIF_AV_MEDIA_FEEDINGS media_feeding;
 +    tBTIF_STATUS status;
 +
 +    APPL_TRACE_EVENT("## A2DP SETUP CODEC ##\n");
 +
 +    GKI_disable();
 +
 +    /* for now hardcode 44.1 khz 16 bit stereo PCM format */
 +    media_feeding.cfg.pcm.sampling_freq = 44100;
 +    media_feeding.cfg.pcm.bit_per_sample = 16;
 +    media_feeding.cfg.pcm.num_channel = 2;
 +    media_feeding.format = BTIF_AV_CODEC_PCM;
 +
 +    bta_av_co_audio_set_codec(&media_feeding, &status);
 +
 +    GKI_enable();
 +}
 +
 +
 +/*****************************************************************************
 +**
 +** Function        btif_a2dp_on_idle
 +**
 +** Description
 +**
 +** Returns
 +**
 +*******************************************************************************/
 +
 +void btif_a2dp_on_idle(void)
 +{
 +    APPL_TRACE_EVENT("## ON A2DP IDLE ##\n");
 +
 +    bta_av_co_init();
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +    if (btif_media_cb.peer_sep == AVDT_TSEP_SRC) {
 +        btif_media_cb.rx_flush = TRUE;
 +        btif_media_task_aa_rx_flush_req();
 +        btif_media_task_aa_handle_stop_decoding();
 +        btif_media_task_clear_track();
 +        APPL_TRACE_DEBUG("Stopped BT track");
 +    }
 +#endif
 +}
 +
 +/*******************************************************************************
 + **
 + ** Function         btif_media_task_clear_track
 + **
 + ** Description
 + **
 + ** Returns          TRUE is success
 + **
 + *******************************************************************************/
 +BOOLEAN btif_media_task_clear_track(void)
 +{
 +    BT_HDR *p_buf;
 +
 +    if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR)))) {
 +        return FALSE;
 +    }
 +
 +    p_buf->event = BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK;
 +
 +    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 +    btif_media_task_post(SIG_MEDIA_TASK_CMD_READY);
 +    return TRUE;
 +}
 +
 +/*****************************************************************************
 +**
 +** Function        btif_reset_decoder
 +**
 +** Description
 +**
 +** Returns
 +**
 +*******************************************************************************/
 +
 +void btif_reset_decoder(UINT8 *p_av)
 +{
 +    APPL_TRACE_EVENT("btif_reset_decoder");
 +    APPL_TRACE_DEBUG("btif_reset_decoder p_codec_info[%x:%x:%x:%x:%x:%x]\n",
 +            p_av[1], p_av[2], p_av[3],
 +            p_av[4], p_av[5], p_av[6]);
 +
 +    tBTIF_MEDIA_SINK_CFG_UPDATE *p_buf;
 +    if (NULL == (p_buf = GKI_getbuf(sizeof(tBTIF_MEDIA_SINK_CFG_UPDATE)))) {
 +        APPL_TRACE_ERROR("btif_reset_decoder No Buffer ");
 +        return;
 +    }
 +
 +    memcpy(p_buf->codec_info, p_av, AVDT_CODEC_SIZE);
 +    p_buf->hdr.event = BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE;
 +
 +    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 +    btif_media_task_post(SIG_MEDIA_TASK_CMD_READY);
 +}
 +
 +/*****************************************************************************
 +**
 +** Function        btif_a2dp_on_stopped
 +**
 +** Description
 +**
 +** Returns
 +**
 +*******************************************************************************/
 +
 +void btif_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av)
 +{
 +    APPL_TRACE_EVENT("## ON A2DP STOPPED ##\n");
 +    if (btif_media_cb.peer_sep == AVDT_TSEP_SRC) { /*  Handling for A2DP SINK cases*/
 +        btif_media_cb.rx_flush = TRUE;
 +        btif_media_task_aa_rx_flush_req();
 +        btif_media_task_aa_handle_stop_decoding();
 +        btif_media_cb.data_channel_open = FALSE;
 +        return;
 +    }
 +}
 +
 +
 +/*****************************************************************************
 +**
 +** Function        btif_a2dp_on_suspended
 +**
 +** Description
 +**
 +** Returns
 +**
 +*******************************************************************************/
 +
 +void btif_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av)
 +{
 +    APPL_TRACE_EVENT("## ON A2DP SUSPENDED ##\n");
 +    if (btif_media_cb.peer_sep == AVDT_TSEP_SRC) {
 +        btif_media_cb.rx_flush = TRUE;
 +        btif_media_task_aa_rx_flush_req();
 +        btif_media_task_aa_handle_stop_decoding();
 +        return;
 +    }
 +}
 +
 +/* when true media task discards any rx frames */
 +void btif_a2dp_set_rx_flush(BOOLEAN enable)
 +{
 +    APPL_TRACE_EVENT("## DROP RX %d ##\n", enable);
 +    btif_media_cb.rx_flush = enable;
 +}
 +
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +static void btif_media_task_avk_handle_timer(UNUSED_ATTR void *context)
 +{
 +    UINT8 count;
 +    tBT_SBC_HDR *p_msg;
 +    int num_sbc_frames;
 +    int num_frames_to_process;
 +
 +    count = btif_media_cb.RxSbcQ._count;
 +    if (0 == count) {
 +        APPL_TRACE_DEBUG("  QUE  EMPTY ");
 +    } else {
 +        if (btif_media_cb.rx_flush == TRUE) {
 +            btif_media_flush_q(&(btif_media_cb.RxSbcQ));
 +            return;
 +        }
 +
 +        num_frames_to_process = btif_media_cb.frames_to_process;
 +        APPL_TRACE_DEBUG(" Process Frames + ");
 +        do {
 +            p_msg = (tBT_SBC_HDR *)GKI_getfirst(&(btif_media_cb.RxSbcQ));
 +            if (p_msg == NULL) {
 +                return;
 +            }
 +            num_sbc_frames  = p_msg->num_frames_to_be_processed; /* num of frames in Que Packets */
 +            APPL_TRACE_DEBUG(" Frames left in topmost packet %d\n", num_sbc_frames);
 +            APPL_TRACE_DEBUG(" Remaining frames to process in tick %d\n", num_frames_to_process);
 +            APPL_TRACE_DEBUG(" Num of Packets in Que %d\n", btif_media_cb.RxSbcQ._count);
 +
 +            if ( num_sbc_frames > num_frames_to_process) { /*  Que Packet has more frames*/
 +                p_msg->num_frames_to_be_processed = num_frames_to_process;
 +                btif_media_task_handle_inc_media(p_msg);
 +                p_msg->num_frames_to_be_processed = num_sbc_frames - num_frames_to_process;
 +                num_frames_to_process = 0;
 +                break;
 +            } else {                                    /*  Que packet has less frames */
 +                btif_media_task_handle_inc_media(p_msg);
 +                p_msg = (tBT_SBC_HDR *)GKI_dequeue(&(btif_media_cb.RxSbcQ));
 +                if ( p_msg == NULL ) {
 +                    APPL_TRACE_ERROR("Insufficient data in que ");
 +                    break;
 +                }
 +                num_frames_to_process = num_frames_to_process - p_msg->num_frames_to_be_processed;
 +                GKI_freebuf(p_msg);
 +            }
 +        } while (num_frames_to_process > 0);
 +
 +        APPL_TRACE_DEBUG(" Process Frames - ");
 +    }
 +}
 +#else
 +static void btif_media_task_avk_handle_timer(UNUSED_ATTR void *context) {}
 +#endif
 +
 +static void btif_media_thread_init(UNUSED_ATTR void *context)
 +{
 +    memset(&btif_media_cb, 0, sizeof(btif_media_cb));
 +    LOG_INFO("media thread init\n");
 +    btif_media_cb.av_sm_hdl = btif_av_get_sm_handle();
 +    raise_priority_a2dp(TASK_HIGH_MEDIA);
 +    media_task_running = MEDIA_TASK_STATE_ON;
 +}
 +
 +static void btif_media_thread_cleanup(UNUSED_ATTR void *context)
 +{
 +    /* make sure no channels are restarted while shutting down */
 +    media_task_running = MEDIA_TASK_STATE_SHUTTING_DOWN;
 +
 +    btif_media_cb.data_channel_open = FALSE;
 +    /* Clear media task flag */
 +    media_task_running = MEDIA_TASK_STATE_OFF;
 +}
 +
 +/*******************************************************************************
 + **
 + ** Function         btif_media_flush_q
 + **
 + ** Description
 + **
 + ** Returns          void
 + **
 + *******************************************************************************/
 +static void btif_media_flush_q(BUFFER_Q *p_q)
 +{
 +    while (!GKI_queue_is_empty(p_q)) {
 +        GKI_freebuf(GKI_dequeue(p_q));
 +    }
 +}
 +
 +static void btif_media_thread_handle_cmd(fixed_queue_t *queue)
 +{
 +    BT_HDR *p_msg;
 +    while (!fixed_queue_is_empty(queue)) {
 +        p_msg = (BT_HDR *)fixed_queue_dequeue(queue);
 +        LOG_VERBOSE("btif_media_thread_handle_cmd : %d %s\n", p_msg->event,
 +                    dump_media_event(p_msg->event));
 +
 +        switch (p_msg->event) {
 +#if (BTA_AV_INCLUDED == TRUE)
 +        case BTIF_MEDIA_AUDIO_SINK_CFG_UPDATE:
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +            btif_media_task_aa_handle_decoder_reset(p_msg);
 +#endif
 +            break;
 +        case BTIF_MEDIA_AUDIO_SINK_CLEAR_TRACK:
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +            btif_media_task_aa_handle_clear_track();
 +#endif
 +            break;
 +        case BTIF_MEDIA_FLUSH_AA_RX:
 +            btif_media_task_aa_rx_flush();
 +            break;
 +#endif
 +        default:
 +            APPL_TRACE_ERROR("ERROR in %s unknown event %d\n", __func__, p_msg->event);
 +        }
 +        GKI_freebuf(p_msg);
 +        LOG_VERBOSE("%s: %s DONE\n", __func__, dump_media_event(p_msg->event));
 +    }
 +}
 +
 +
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +/*******************************************************************************
 + **
 + ** Function         btif_media_task_handle_inc_media
 + **
 + ** Description
 + **
 + ** Returns          void
 + **
 + *******************************************************************************/
 +static void btif_media_task_handle_inc_media(tBT_SBC_HDR *p_msg)
 +{
 +    UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1);
 +    int count;
 +    UINT32 pcmBytes, availPcmBytes;
 +    OI_INT16 *pcmDataPointer = pcmData; /*Will be overwritten on next packet receipt*/
 +    OI_STATUS status;
 +    int num_sbc_frames = p_msg->num_frames_to_be_processed;
 +    UINT32 sbc_frame_len = p_msg->len - 1;
 +    availPcmBytes = 2 * sizeof(pcmData);
 +
 +    if ((btif_media_cb.peer_sep == AVDT_TSEP_SNK) || (btif_media_cb.rx_flush)) {
 +        APPL_TRACE_DEBUG(" State Changed happened in this tick ");
 +        return;
 +    }
 +
 +    // ignore data if no one is listening
 +    if (!btif_media_cb.data_channel_open) {
 +        return;
 +    }
 +
 +    APPL_TRACE_DEBUG("Number of sbc frames %d, frame_len %d\n", num_sbc_frames, sbc_frame_len);
 +    // LOG_ERROR("Number of sbc frames %d, frame_len %d\n", num_sbc_frames, sbc_frame_len);
 +    for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++) {
 +        pcmBytes = availPcmBytes;
 +        status = OI_CODEC_SBC_DecodeFrame(&context, (const OI_BYTE **)&sbc_start_frame,
 +                                          (OI_UINT32 *)&sbc_frame_len,
 +                                          (OI_INT16 *)pcmDataPointer,
 +                                          (OI_UINT32 *)&pcmBytes);
 +        if (!OI_SUCCESS(status)) {
 +            APPL_TRACE_ERROR("Decoding failure: %d\n", status);
 +            break;
 +        }
 +        availPcmBytes -= pcmBytes;
 +        pcmDataPointer += pcmBytes / 2;
 +        p_msg->offset += (p_msg->len - 1) - sbc_frame_len;
 +        p_msg->len = sbc_frame_len + 1;
 +    }
 +    // LOG_ERROR("pre-send: %d\n", availPcmBytes);
 +
 +    // UIPC_Send(UIPC_CH_ID_AV_AUDIO, 0, (UINT8 *)pcmData, (2 * sizeof(pcmData) - availPcmBytes));
 +    BTIF_A2D_DATA_CB_TO_APP((const uint8_t *)pcmData, (2 * sizeof(pcmData) - availPcmBytes));
 +
 +}
 +#endif
 +
 +#if (BTA_AV_INCLUDED == TRUE)
 +
 +/*******************************************************************************
 + **
 + ** Function         btif_media_task_aa_rx_flush_req
 + **
 + ** Description
 + **
 + ** Returns          TRUE is success
 + **
 + *******************************************************************************/
 +BOOLEAN btif_media_task_aa_rx_flush_req(void)
 +{
 +    BT_HDR *p_buf;
 +
 +    if (GKI_queue_is_empty(&(btif_media_cb.RxSbcQ)) == TRUE) { /*  Que is already empty */
 +        return TRUE;
 +    }
 +
 +    if (NULL == (p_buf = GKI_getbuf(sizeof(BT_HDR)))) {
 +        return FALSE;
 +    }
 +
 +    p_buf->event = BTIF_MEDIA_FLUSH_AA_RX;
 +
 +    fixed_queue_enqueue(btif_media_cmd_msg_queue, p_buf);
 +    btif_media_task_post(SIG_MEDIA_TASK_CMD_READY);
 +    return TRUE;
 +}
 +
 +/*******************************************************************************
 + **
 + ** Function         btif_media_task_aa_rx_flush
 + **
 + ** Description
 + **
 + ** Returns          void
 + **
 + *******************************************************************************/
 +static void btif_media_task_aa_rx_flush(void)
 +{
 +    /* Flush all enqueued GKI SBC  buffers (encoded) */
 +    APPL_TRACE_DEBUG("btif_media_task_aa_rx_flush");
 +
 +    btif_media_flush_q(&(btif_media_cb.RxSbcQ));
 +}
 +
 +int btif_a2dp_get_track_frequency(UINT8 frequency)
 +{
 +    int freq = 48000;
 +    switch (frequency) {
 +    case A2D_SBC_IE_SAMP_FREQ_16:
 +        freq = 16000;
 +        break;
 +    case A2D_SBC_IE_SAMP_FREQ_32:
 +        freq = 32000;
 +        break;
 +    case A2D_SBC_IE_SAMP_FREQ_44:
 +        freq = 44100;
 +        break;
 +    case A2D_SBC_IE_SAMP_FREQ_48:
 +        freq = 48000;
 +        break;
 +    }
 +    return freq;
 +}
 +
 +int btif_a2dp_get_track_channel_count(UINT8 channeltype)
 +{
 +    int count = 1;
 +    switch (channeltype) {
 +    case A2D_SBC_IE_CH_MD_MONO:
 +        count = 1;
 +        break;
 +    case A2D_SBC_IE_CH_MD_DUAL:
 +    case A2D_SBC_IE_CH_MD_STEREO:
 +    case A2D_SBC_IE_CH_MD_JOINT:
 +        count = 2;
 +        break;
 +    }
 +    return count;
 +}
 +
 +void btif_a2dp_set_peer_sep(UINT8 sep)
 +{
 +    btif_media_cb.peer_sep = sep;
 +}
 +
 +static void btif_decode_alarm_cb(UNUSED_ATTR void *context)
 +{
 +    btif_media_task_post(SIG_MEDIA_TASK_AVK_ALARM_TO);
 +}
 +
 +static void btif_media_task_aa_handle_stop_decoding(void)
 +{
 +    osi_alarm_free(btif_media_cb.decode_alarm);
 +    btif_media_cb.decode_alarm = NULL;
 +}
 +
 +static void btif_media_task_aa_handle_start_decoding(void)
 +{
 +    if (btif_media_cb.decode_alarm) {
 +        return;
 +    }
 +
 +    btif_media_cb.decode_alarm = osi_alarm_new("dec_timer\n", btif_decode_alarm_cb, NULL, BTIF_SINK_MEDIA_TIME_TICK, true);
 +    if (!btif_media_cb.decode_alarm) {
 +        APPL_TRACE_ERROR("%s unable to allocate decode alarm.\n", __func__);
 +        return;
 +    }
 +    osi_alarm_set(btif_media_cb.decode_alarm, BTIF_SINK_MEDIA_TIME_TICK);
 +}
 +
 +#if (BTA_AV_SINK_INCLUDED == TRUE)
 +
 +static void btif_media_task_aa_handle_clear_track (void)
 +{
 +    APPL_TRACE_DEBUG("btif_media_task_aa_handle_clear_track");
 +}
 +
 +/*******************************************************************************
 + **
 + ** Function         btif_media_task_aa_handle_decoder_reset
 + **
 + ** Description
 + **
 + ** Returns          void
 + **
 + *******************************************************************************/
 +static void btif_media_task_aa_handle_decoder_reset(BT_HDR *p_msg)
 +{
 +    tBTIF_MEDIA_SINK_CFG_UPDATE *p_buf = (tBTIF_MEDIA_SINK_CFG_UPDATE *) p_msg;
 +    tA2D_STATUS a2d_status;
 +    tA2D_SBC_CIE sbc_cie;
 +    OI_STATUS       status;
 +    UINT32          freq_multiple = 48 * 20; /* frequency multiple for 20ms of data , initialize with 48K*/
 +    UINT32          num_blocks = 16;
 +    UINT32          num_subbands = 8;
 +
 +    APPL_TRACE_EVENT("btif_media_task_aa_handle_decoder_reset p_codec_info[%x:%x:%x:%x:%x:%x]\n",
 +              p_buf->codec_info[1], p_buf->codec_info[2], p_buf->codec_info[3],
 +              p_buf->codec_info[4], p_buf->codec_info[5], p_buf->codec_info[6]);
 +
 +    a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_buf->codec_info, FALSE);
 +    if (a2d_status != A2D_SUCCESS) {
 +        APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status);
 +        return;
 +    }
 +
 +    btif_media_cb.sample_rate = btif_a2dp_get_track_frequency(sbc_cie.samp_freq);
 +    btif_media_cb.channel_count = btif_a2dp_get_track_channel_count(sbc_cie.ch_mode);
 +
 +    btif_media_cb.rx_flush = FALSE;
 +    APPL_TRACE_EVENT("Reset to sink role");
 +    status = OI_CODEC_SBC_DecoderReset(&context, contextData, sizeof(contextData), 2, 2, FALSE);
 +    if (!OI_SUCCESS(status)) {
 +        APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status);
 +    }
 +
 +    btif_media_cb.data_channel_open = TRUE;
 +
 +    switch (sbc_cie.samp_freq) {
 +    case A2D_SBC_IE_SAMP_FREQ_16:
 +        APPL_TRACE_DEBUG("\tsamp_freq:%d (16000)\n", sbc_cie.samp_freq);
 +        freq_multiple = 16 * 20;
 +        break;
 +    case A2D_SBC_IE_SAMP_FREQ_32:
 +        APPL_TRACE_DEBUG("\tsamp_freq:%d (32000)\n", sbc_cie.samp_freq);
 +        freq_multiple = 32 * 20;
 +        break;
 +    case A2D_SBC_IE_SAMP_FREQ_44:
 +        APPL_TRACE_DEBUG("\tsamp_freq:%d (44100)\n", sbc_cie.samp_freq);
 +        freq_multiple = 441 * 2;
 +        break;
 +    case A2D_SBC_IE_SAMP_FREQ_48:
 +        APPL_TRACE_DEBUG("\tsamp_freq:%d (48000)\n", sbc_cie.samp_freq);
 +        freq_multiple = 48 * 20;
 +        break;
 +    default:
 +        APPL_TRACE_DEBUG(" Unknown Frequency ");
 +        break;
 +    }
 +
 +    switch (sbc_cie.ch_mode) {
 +    case A2D_SBC_IE_CH_MD_MONO:
 +        APPL_TRACE_DEBUG("\tch_mode:%d (Mono)\n", sbc_cie.ch_mode);
 +        break;
 +    case A2D_SBC_IE_CH_MD_DUAL:
 +        APPL_TRACE_DEBUG("\tch_mode:%d (DUAL)\n", sbc_cie.ch_mode);
 +        break;
 +    case A2D_SBC_IE_CH_MD_STEREO:
 +        APPL_TRACE_DEBUG("\tch_mode:%d (STEREO)\n", sbc_cie.ch_mode);
 +        break;
 +    case A2D_SBC_IE_CH_MD_JOINT:
 +        APPL_TRACE_DEBUG("\tch_mode:%d (JOINT)\n", sbc_cie.ch_mode);
 +        break;
 +    default:
 +        APPL_TRACE_DEBUG(" Unknown Mode ");
 +        break;
 +    }
 +
 +    switch (sbc_cie.block_len) {
 +    case A2D_SBC_IE_BLOCKS_4:
 +        APPL_TRACE_DEBUG("\tblock_len:%d (4)\n", sbc_cie.block_len);
 +        num_blocks = 4;
 +        break;
 +    case A2D_SBC_IE_BLOCKS_8:
 +        APPL_TRACE_DEBUG("\tblock_len:%d (8)\n", sbc_cie.block_len);
 +        num_blocks = 8;
 +        break;
 +    case A2D_SBC_IE_BLOCKS_12:
 +        APPL_TRACE_DEBUG("\tblock_len:%d (12)\n", sbc_cie.block_len);
 +        num_blocks = 12;
 +        break;
 +    case A2D_SBC_IE_BLOCKS_16:
 +        APPL_TRACE_DEBUG("\tblock_len:%d (16)\n", sbc_cie.block_len);
 +        num_blocks = 16;
 +        break;
 +    default:
 +        APPL_TRACE_DEBUG(" Unknown BlockLen ");
 +        break;
 +    }
 +
 +    switch (sbc_cie.num_subbands) {
 +    case A2D_SBC_IE_SUBBAND_4:
 +        APPL_TRACE_DEBUG("\tnum_subbands:%d (4)\n", sbc_cie.num_subbands);
 +        num_subbands = 4;
 +        break;
 +    case A2D_SBC_IE_SUBBAND_8:
 +        APPL_TRACE_DEBUG("\tnum_subbands:%d (8)\n", sbc_cie.num_subbands);
 +        num_subbands = 8;
 +        break;
 +    default:
 +        APPL_TRACE_DEBUG(" Unknown SubBands ");
 +        break;
 +    }
 +
 +    switch (sbc_cie.alloc_mthd) {
 +    case A2D_SBC_IE_ALLOC_MD_S:
 +        APPL_TRACE_DEBUG("\talloc_mthd:%d (SNR)\n", sbc_cie.alloc_mthd);
 +        break;
 +    case A2D_SBC_IE_ALLOC_MD_L:
 +        APPL_TRACE_DEBUG("\talloc_mthd:%d (Loudness)\n", sbc_cie.alloc_mthd);
 +        break;
 +    default:
 +        APPL_TRACE_DEBUG(" Unknown Allocation Method");
 +        break;
 +    }
 +
 +    APPL_TRACE_EVENT("\tBit pool Min:%d Max:%d\n", sbc_cie.min_bitpool, sbc_cie.max_bitpool);
 +
 +    btif_media_cb.frames_to_process = ((freq_multiple) / (num_blocks * num_subbands)) + 1;
 +    APPL_TRACE_EVENT(" Frames to be processed in 20 ms %d\n", btif_media_cb.frames_to_process);
 +}
 +#endif
 +
 +/*******************************************************************************
 + **
 + ** Function         btif_media_sink_enque_buf
 + **
 + ** Description      This function is called by the av_co to fill A2DP Sink Queue
 + **
 + **
 + ** Returns          size of the queue
 + *******************************************************************************/
 +UINT8 btif_media_sink_enque_buf(BT_HDR *p_pkt)
 +{
 +    tBT_SBC_HDR *p_msg;
 +
 +    if (btif_media_cb.rx_flush == TRUE) { /* Flush enabled, do not enque*/
 +        return GKI_queue_length(&btif_media_cb.RxSbcQ);
 +    }
 +    if (GKI_queue_length(&btif_media_cb.RxSbcQ) == MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ) {
 +        GKI_freebuf(GKI_dequeue(&(btif_media_cb.RxSbcQ)));
 +    }
 +
 +    BTIF_TRACE_VERBOSE("btif_media_sink_enque_buf + ");
 +
 +    /* allocate and Queue this buffer */
 +    if ((p_msg = (tBT_SBC_HDR *) GKI_getbuf(sizeof(tBT_SBC_HDR) +
 +                                            p_pkt->offset + p_pkt->len)) != NULL) {
 +        memcpy(p_msg, p_pkt, (sizeof(BT_HDR) + p_pkt->offset + p_pkt->len));
 +        p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f;
 +        BTIF_TRACE_VERBOSE("btif_media_sink_enque_buf %d + \n", p_msg->num_frames_to_be_processed);
 +        // LOG_ERROR("sink enq %d\n", p_msg->num_frames_to_be_processed);
 +        GKI_enqueue(&(btif_media_cb.RxSbcQ), p_msg);
 +        if (GKI_queue_length(&btif_media_cb.RxSbcQ) == MAX_A2DP_DELAYED_START_FRAME_COUNT) {
 +            BTIF_TRACE_DEBUG(" Initiate Decoding ");
 +            btif_media_task_aa_handle_start_decoding();
 +        }
 +    } else {
 +        /* let caller deal with a failed allocation */
 +        BTIF_TRACE_VERBOSE("btif_media_sink_enque_buf No Buffer left - ");
 +    }
 +    return GKI_queue_length(&btif_media_cb.RxSbcQ);
 +}
 +
 +
 +/*******************************************************************************
 + **
 + ** Function         btif_media_aa_readbuf
 + **
 + ** Description      This function is called by the av_co to get the next buffer to send
 + **
 + **
 + ** Returns          void
 + *******************************************************************************/
 +BT_HDR *btif_media_aa_readbuf(void)
 +{
 +    return NULL;
 +}
 +
 +#endif /* BTA_AV_INCLUDED == TRUE */
 +/*******************************************************************************
 + **
 + ** Function         dump_codec_info
 + **
 + ** Description      Decode and display codec_info (for debug)
 + **
 + ** Returns          void
 + **
 + *******************************************************************************/
 +void dump_codec_info(unsigned char *p_codec)
 +{
 +    tA2D_STATUS a2d_status;
 +    tA2D_SBC_CIE sbc_cie;
 +
 +    a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec, FALSE);
 +    if (a2d_status != A2D_SUCCESS) {
 +        APPL_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status);
 +        return;
 +    }
 +
 +    APPL_TRACE_DEBUG("dump_codec_info");
 +
 +    if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_16) {
 +        APPL_TRACE_DEBUG("\tsamp_freq:%d (16000)\n", sbc_cie.samp_freq);
 +    } else  if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_32) {
 +        APPL_TRACE_DEBUG("\tsamp_freq:%d (32000)\n", sbc_cie.samp_freq);
 +    } else  if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_44) {
 +        APPL_TRACE_DEBUG("\tsamp_freq:%d (44.100)\n", sbc_cie.samp_freq);
 +    } else  if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_48) {
 +        APPL_TRACE_DEBUG("\tsamp_freq:%d (48000)\n", sbc_cie.samp_freq);
 +    } else {
 +        APPL_TRACE_DEBUG("\tBAD samp_freq:%d\n", sbc_cie.samp_freq);
 +    }
 +
 +    if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_MONO) {
 +        APPL_TRACE_DEBUG("\tch_mode:%d (Mono)\n", sbc_cie.ch_mode);
 +    } else  if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_DUAL) {
 +        APPL_TRACE_DEBUG("\tch_mode:%d (Dual)\n", sbc_cie.ch_mode);
 +    } else  if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_STEREO) {
 +        APPL_TRACE_DEBUG("\tch_mode:%d (Stereo)\n", sbc_cie.ch_mode);
 +    } else  if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_JOINT) {
 +        APPL_TRACE_DEBUG("\tch_mode:%d (Joint)\n", sbc_cie.ch_mode);
 +    } else {
 +        APPL_TRACE_DEBUG("\tBAD ch_mode:%d\n", sbc_cie.ch_mode);
 +    }
 +
 +    if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_4) {
 +        APPL_TRACE_DEBUG("\tblock_len:%d (4)\n", sbc_cie.block_len);
 +    } else  if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_8) {
 +        APPL_TRACE_DEBUG("\tblock_len:%d (8)\n", sbc_cie.block_len);
 +    } else  if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_12) {
 +        APPL_TRACE_DEBUG("\tblock_len:%d (12)\n", sbc_cie.block_len);
 +    } else  if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_16) {
 +        APPL_TRACE_DEBUG("\tblock_len:%d (16)\n", sbc_cie.block_len);
 +    } else {
 +        APPL_TRACE_DEBUG("\tBAD block_len:%d\n", sbc_cie.block_len);
 +    }
 +
 +    if (sbc_cie.num_subbands == A2D_SBC_IE_SUBBAND_4) {
 +        APPL_TRACE_DEBUG("\tnum_subbands:%d (4)\n", sbc_cie.num_subbands);
 +    } else  if (sbc_cie.num_subbands == A2D_SBC_IE_SUBBAND_8) {
 +        APPL_TRACE_DEBUG("\tnum_subbands:%d (8)\n", sbc_cie.num_subbands);
 +    } else {
 +        APPL_TRACE_DEBUG("\tBAD num_subbands:%d\n", sbc_cie.num_subbands);
 +    }
 +
 +    if (sbc_cie.alloc_mthd == A2D_SBC_IE_ALLOC_MD_S) {
 +        APPL_TRACE_DEBUG("\talloc_mthd:%d (SNR)\n", sbc_cie.alloc_mthd);
 +    } else  if (sbc_cie.alloc_mthd == A2D_SBC_IE_ALLOC_MD_L) {
 +        APPL_TRACE_DEBUG("\talloc_mthd:%d (Loundess)\n", sbc_cie.alloc_mthd);
 +    } else {
 +        APPL_TRACE_DEBUG("\tBAD alloc_mthd:%d\n", sbc_cie.alloc_mthd);
 +    }
 +
 +    APPL_TRACE_DEBUG("\tBit pool Min:%d Max:%d\n", sbc_cie.min_bitpool, sbc_cie.max_bitpool);
 +
 +}
index eb61903578d1e984287b20744afe4ec99dedd0ba,e621450423ff60086431772597df1a2de07d1e1d..5d4824d9b0360183ba5ad8018ebc66a666b6bc4a
@@@ -102,11 -102,12 +102,11 @@@ static bool hal_open(const hci_hal_call
      hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, SIZE_MAX);
  
      xHciH4Queue = xQueueCreate(HCI_H4_QUEUE_NUM, sizeof(BtTaskEvt_t));
-     xTaskCreate(hci_hal_h4_rx_handler, HCI_H4_TASK_NAME, HCI_H4_TASK_STACK_SIZE, NULL, HCI_H4_TASK_PRIO, &xHciH4TaskHandle);
+     xTaskCreatePinnedToCore(hci_hal_h4_rx_handler, HCI_H4_TASK_NAME, HCI_H4_TASK_STACK_SIZE, NULL, HCI_H4_TASK_PRIO, &xHciH4TaskHandle, 0);
  
      //register vhci host cb
-     API_vhci_host_register_callback(&vhci_host_cb);
+     esp_vhci_host_register_callback(&vhci_host_cb);
  
 -
      return true;
  }
  
index cafd79494263a77c6f41e49b1f4f65fafc50868d,14a36eac813c75fce15583edfb85f0afa4a018d1..f39c06caedb61c50a7ec7a67e94304c3ec6e77bb
@@@ -223,10 -223,12 +223,10 @@@ static void hci_host_thread_handler(voi
       */
  
      BtTaskEvt_t e;
 -
      for (;;) {
          if (pdTRUE == xQueueReceive(xHciHostQueue, &e, (portTickType)portMAX_DELAY)) {
 -
              if (e.sig == 0xff) {
-                 if (API_vhci_host_check_send_available()) {
+                 if (esp_vhci_host_check_send_available()) {
                      /*Now Target only allowed one packet per TX*/
                      BT_HDR *pkt = packet_fragmenter->fragment_current_packet();
                      if (pkt != NULL) {
index 8eea25cee7d4a548466b6cad419fe5e742c20bcc,9360d4fbf359de57a18d048423e27335672f557b..fc8da23221834c5d66075196fd6478c2c92790ca
@@@ -132,14 -134,14 +134,14 @@@ typedef UINT16 tGATT_DISCONN_REASON
  
  /* invalid connection ID
  */
- #define GATT_INVALID_CONN_ID        0xFFFF
+ #define GATT_INVALID_CONN_ID                0xFFFF
  
  #ifndef GATT_CL_MAX_LCB
-     #define GATT_CL_MAX_LCB     4 // 22
 -#define GATT_CL_MAX_LCB                     12 // 22
++#define GATT_CL_MAX_LCB                     4 // 22
  #endif
  
  #ifndef GATT_MAX_SCCB
-     #define GATT_MAX_SCCB       4
 -#define GATT_MAX_SCCB                       10
++#define GATT_MAX_SCCB                       4
  #endif
  
  
Simple merge
index 49f25362b06659be23dd6e52508abd40bb8ed712,0000000000000000000000000000000000000000..de2f1573b8e5b0e264b71fe881d87a6dfbd9374b
mode 100644,000000..100644
--- /dev/null
@@@ -1,246 -1,0 +1,218 @@@
- #include "EspAudio.h"
- #include "EspAudioCom.h"
 +#include <stdint.h>
 +#include <stdbool.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +#include "freertos/FreeRTOS.h"
 +#include "freertos/task.h"
 +#include "freertos/timers.h"
 +
 +#include "esp_system.h"
- static void key_tmr_handler(TimerHandle_t xTimer)
- {
-     if (m_audio_state != ESP_A2D_AUDIO_STATE_STARTED) {
-         BT_APP_TRACE_EVENT("-----key_tmr_hdlr, return, audio state: %d\n", m_audio_state);
-         return;
-     }
-             
-     bt_app_evt_arg param;
-     memset(&param, 0, sizeof(bt_app_evt_arg));
-     if (m_key_state == 1) {
-         param.avrc_key.key_state = 1;
-         m_key_state = 0;
-     } else {
-         param.avrc_key.key_state = 0;
-         m_key_state = 1;
-     }
-     param.avrc_key.id = 0x41; // volume up
-     BT_APP_TRACE_EVENT("-----key_tmr_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, &param, sizeof(bt_app_evt_arg), NULL);
- }
- static void bt_app_a2d_cb(uint32_t event, void *param)
++// #include "EspAudio.h"
++// #include "EspAudioCom.h"
 +
 +#include "bt_app_common.h"
 +#include "esp_bt_stack_manager.h"
 +#include "esp_gap_bt_api.h"
 +#include "esp_a2dp_api.h"
 +
 +#include "bt_rc.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;
 +} 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(&param, 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, &param, sizeof(bt_app_evt_arg), NULL);
 +    }
 +}
 +
-     EspAudioPlayerStreamWrite((uint8_t *)data, len, 10);
++static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
 +{
 +    switch (event) {
 +    case ESP_A2D_CONNECTION_STATE_EVT:
 +    case ESP_A2D_AUDIO_STATE_EVT:
 +    case ESP_A2D_AUDIO_CFG_EVT:
 +    {
 +      bt_app_transfer_context(bt_app_handle_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 btrc_passthrough_rsp_cb(int id, int key_state)
 +{
 +    bt_app_evt_arg param;
 +    memset(&param, 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, &param, 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(&param, 0, sizeof(bt_app_evt_arg));
 +    param.avrc_state.state = state;
 +    memcpy(&param.avrc_state.bd_addr, bd_addr, sizeof(bt_bdaddr_t));
 +    bt_app_transfer_context(bt_app_handle_evt, ESP_AVRC_CONNECTION_STATE_EVT, &param, 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)
 +{
-         esp_a2d_register_callback(bt_app_a2d_cb);
++    // EspAudioPlayerStreamWrite((uint8_t *)data, len, 10);
 +}
 +                          
 +static void bt_app_handle_evt(uint16_t event, void *p_param)
 +{
 +    BT_APP_TRACE_DEBUG("bt_app_handle_evt 0x%x\n", event);
 +    esp_a2d_cb_param_t *a2d = NULL;
 +    switch (event) {
 +    case BT_APP_EVT_STACK_ON: {
 +        char *dev_name = "ESP_SPEAKER";
 +      esp_bt_gap_set_device_name(dev_name);
 +
-             #if 0
-             int32_t key_tmr_id = 10;
-             m_key_tmr = xTimerCreate("appKeyTmr", 3000 / portTICK_PERIOD_MS, pdTRUE, (void *) key_tmr_id, key_tmr_handler);
-             if (xTimerStart(m_key_tmr, 10 / portTICK_PERIOD_MS) != pdTRUE) {
-                 BT_APP_TRACE_EVENT(" timer start failed\n");
-             }
-             #endif
++        esp_a2d_register_callback(&bt_app_a2d_cb);
 +        esp_a2d_register_data_callback(bt_app_a2d_data_cb);
 +
 +        esp_a2d_sink_init();
 +      
 +      btrc_ctrl_init(&btrc_ctrl_cb);
 +        esp_bt_gap_set_scan_mode(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
 +        break;
 +    }
 +    case ESP_A2D_CONNECTION_STATE_EVT: {
 +        a2d = (esp_a2d_cb_param_t *)(p_param);
 +        BT_APP_TRACE_EVENT("===a2dp conn_state_cb %d ===\n", a2d->conn_stat.state);
 +        break;
 +    }
 +    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);
 +        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);
-             EspAudioPlayerStreamCfg(StreamSampleRate_44k, 2, StreamBitLen_16BIT);
-             EspAudio_SetupStream("stream.pcm", InputSrcType_Stream);
-             EspAudio_SetVolume(99);
 +        }
 +        break;
 +    }
 +    case ESP_A2D_AUDIO_CFG_EVT: {
 +        a2d = (esp_a2d_cb_param_t *)(p_param);
 +        BT_APP_TRACE_EVENT("===a2dp audio_cfg_cb type %d ===\n", a2d->audio_cfg.mcc.type);
 +        if (a2d->audio_cfg.mcc.type == ESP_A2D_MCT_SBC) {
 +            // temporarily hardcoded the PCM configuaration
 +            BT_APP_TRACE_EVENT("configure audio player\n");
++            // EspAudioPlayerStreamCfg(StreamSampleRate_44k, 2, StreamBitLen_16BIT);
++            // EspAudio_SetupStream("stream.pcm", InputSrcType_Stream);
++            // EspAudio_SetVolume(99);
 +        }
 +        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);
 +        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);
 +        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);
 +        break;
 +    }
 +    default:
 +        BT_APP_TRACE_ERROR("===application invalid event: %d\n", event);
 +        break;
 +    }
 +    
 +}
 +
 +void app_main_entry(void)
 +{
 +    esp_err_t init, enable;
 +    init = esp_bt_init_stack();
 +    if (init != ESP_OK) {
 +        return;
 +    }
 +
 +    enable = esp_bt_enable_stack();
 +    if (enable != ESP_OK) {
 +        return;
 +    }
 +
 +    bt_app_transfer_context(bt_app_handle_evt, BT_APP_EVT_STACK_ON, NULL, 0, NULL);
 +}
index 7d7bf118b2e0bbc1a22a334a67e06e727df2ea91,0000000000000000000000000000000000000000..9a4288a75484d5a83b7f6d78160760351778cf07
mode 100755,000000..100755
--- /dev/null
@@@ -1,25 -1,0 +1,25 @@@
-     bt_controller_init();
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <unistd.h>
 +#include <string.h>
 +#include "bt.h"
 +#include "freertos/FreeRTOS.h"
 +#include "freertos/task.h"
 +
 +#include "nvs_flash.h"
 +#include "esp_system.h"
 +// #include "EspAudio.h"
 +
 +extern void bte_main_boot_entry(void *);
 +extern void bt_app_task_start_up(void);
 +extern void bt_app_core_start(void);
 +
 +void app_main()
 +{
 +    nvs_flash_init();
 +    // system_init();
 +    // printf("Free memory: %d bytes\n", system_get_free_heap_size());
 +    // EspAudio_Init();
++    esp_bt_controller_init();
 +    bt_app_task_start_up();
 +}