/******************************************************************************
*
* 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: bt_vendor_brcm.c
*
* Description: Broadcom vendor specific library implementation
*
******************************************************************************/
#define LOG_TAG "bt_vendor"
#include <utils/Log.h>
#include <string.h>
#include "bt_vendor_brcm.h"
#include "upio.h"
#include "userial_vendor.h"
#ifndef BTVND_DBG
#define BTVND_DBG FALSE
#endif
#if (BTVND_DBG == TRUE)
#define BTVNDDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
#else
#define BTVNDDBG(param, ...) {}
#endif
/******************************************************************************
** Externs
******************************************************************************/
void hw_config_start(void);
uint8_t hw_lpm_enable(uint8_t turn_on);
uint32_t hw_lpm_get_idle_timeout(void);
void hw_lpm_set_wake_state(uint8_t wake_assert);
#if (SCO_CFG_INCLUDED == TRUE)
void hw_sco_config(void);
#endif
void vnd_load_conf(const char *p_path);
#if (HW_END_WITH_HCI_RESET == TRUE)
void hw_epilog_process(void);
#endif
#if (BRCM_A2DP_OFFLOAD == TRUE)
void brcm_vnd_a2dp_init(bt_vendor_callbacks_t *callback);
int brcm_vnd_a2dp_execute(bt_vendor_opcode_t, void *ev_data);
#endif
/******************************************************************************
** Variables
******************************************************************************/
bt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
uint8_t vnd_local_bd_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/******************************************************************************
** Local type definitions
******************************************************************************/
/******************************************************************************
** Static Variables
******************************************************************************/
static const tUSERIAL_CFG userial_init_cfg =
{
(USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
USERIAL_BAUD_115200
};
/******************************************************************************
** Functions
******************************************************************************/
/*****************************************************************************
**
** BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
**
*****************************************************************************/
static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr)
{
ALOGI("init");
if (p_cb == NULL)
{
ALOGE("init failed with no user callbacks!");
return -1;
}
#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
ALOGW("*****************************************************************");
ALOGW("*****************************************************************");
ALOGW("** Warning - BT Vendor Lib is loaded in debug tuning mode!");
ALOGW("**");
ALOGW("** If this is not intentional, rebuild libbt-vendor.so ");
ALOGW("** with VENDOR_LIB_RUNTIME_TUNING_ENABLED=FALSE and ");
ALOGW("** check if any run-time tuning parameters needed to be");
ALOGW("** carried to the build-time configuration accordingly.");
ALOGW("*****************************************************************");
ALOGW("*****************************************************************");
#endif
userial_vendor_init();
upio_init();
vnd_load_conf(VENDOR_LIB_CONF_FILE);
/* store reference to user callbacks */
bt_vendor_cbacks = (bt_vendor_callbacks_t *) p_cb;
/* This is handed over from the stack */
memcpy(vnd_local_bd_addr, local_bdaddr, 6);
#if (BRCM_A2DP_OFFLOAD == TRUE)
brcm_vnd_a2dp_init(bt_vendor_cbacks);
#endif
return 0;
}
/** Requested operations */
static int op(bt_vendor_opcode_t opcode, void *param)
{
int retval = 0;
BTVNDDBG("op for %d", opcode);
switch(opcode)
{
case BT_VND_OP_POWER_CTRL:
{
int *state = (int *) param;
upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
if (*state == BT_VND_PWR_ON)
{
ALOGW("NOTE: BT_VND_PWR_ON now forces power-off first");
upio_set_bluetooth_power(UPIO_BT_POWER_ON);
} else {
/* Make sure wakelock is released */
hw_lpm_set_wake_state(false);
}
}
break;
case BT_VND_OP_FW_CFG:
{
hw_config_start();
}
break;
case BT_VND_OP_SCO_CFG:
{
#if (SCO_CFG_INCLUDED == TRUE)
hw_sco_config();
#else
retval = -1;
#endif
}
break;
case BT_VND_OP_USERIAL_OPEN:
{
int (*fd_array)[] = (int (*)[]) param;
int fd, idx;
fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
if (fd != -1)
{
for (idx=0; idx < CH_MAX; idx++)
(*fd_array)[idx] = fd;
retval = 1;
}
/* retval contains numbers of open fd of HCI channels */
}
break;
case BT_VND_OP_USERIAL_CLOSE:
{
userial_vendor_close();
}
break;
case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
{
uint32_t *timeout_ms = (uint32_t *) param;
*timeout_ms = hw_lpm_get_idle_timeout();
}
break;
case BT_VND_OP_LPM_SET_MODE:
{
uint8_t *mode = (uint8_t *) param;
retval = hw_lpm_enable(*mode);
}
break;
case BT_VND_OP_LPM_WAKE_SET_STATE:
{
uint8_t *state = (uint8_t *) param;
uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
TRUE : FALSE;
hw_lpm_set_wake_state(wake_assert);
}
break;
case BT_VND_OP_SET_AUDIO_STATE:
{
retval = hw_set_audio_state((bt_vendor_op_audio_state_t *)param);
}
break;
case BT_VND_OP_EPILOG:
{
#if (HW_END_WITH_HCI_RESET == FALSE)
if (bt_vendor_cbacks)
{
bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
}
#else
hw_epilog_process();
#endif
}
break;
#if (BRCM_A2DP_OFFLOAD == TRUE)
case BT_VND_OP_A2DP_OFFLOAD_START:
case BT_VND_OP_A2DP_OFFLOAD_STOP:
retval = brcm_vnd_a2dp_execute(opcode, param);
break;
#endif
}
return retval;
}
/** Closes the interface */
static void cleanup( void )
{
BTVNDDBG("cleanup");
upio_cleanup();
bt_vendor_cbacks = NULL;
}
// Entry point of DLib
const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
sizeof(bt_vendor_interface_t),
init,
op,
cleanup
};