summaryrefslogtreecommitdiff
Diffstat
-rw-r--r--Android.mk49
-rw-r--r--conf/asus/grouper/Android.mk14
-rw-r--r--conf/asus/grouper/bt_vendor.conf5
-rw-r--r--conf/meson/Android.mk14
-rw-r--r--conf/meson/bt_vendor.conf5
-rw-r--r--conf/moto/wingray/Android.mk14
-rw-r--r--conf/moto/wingray/bt_vendor.conf5
-rw-r--r--conf/samsung/crespo/Android.mk14
-rw-r--r--conf/samsung/crespo/bt_vendor.conf5
-rw-r--r--conf/samsung/crespo4g/Android.mk14
-rw-r--r--conf/samsung/crespo4g/bt_vendor.conf5
-rw-r--r--conf/samsung/maguro/Android.mk14
-rw-r--r--conf/samsung/maguro/bt_vendor.conf5
-rwxr-xr-xgen-buildcfg.sh25
-rwxr-xr-xinclude/bt_vendor_brcm.h103
-rw-r--r--[-rwxr-xr-x]include/vnd_40183_lpm.txt0
-rw-r--r--include/vnd_angler.txt17
-rw-r--r--include/vnd_anthias.txt10
-rw-r--r--include/vnd_bass.txt16
-rw-r--r--include/vnd_carp.txt14
-rw-r--r--include/vnd_crespo.txt8
-rw-r--r--include/vnd_crespo4g.txt8
-rw-r--r--include/vnd_dory.txt14
-rw-r--r--include/vnd_dragon.txt9
-rw-r--r--include/vnd_flounder.txt10
-rw-r--r--include/vnd_flounder64.txt10
-rw-r--r--include/vnd_flounder_lte.txt10
-rw-r--r--include/vnd_fugu.txt11
-rw-r--r--[-rwxr-xr-x]include/vnd_generic.txt1
-rw-r--r--[-rwxr-xr-x]include/vnd_generic_x86.txt1
-rw-r--r--include/vnd_grouper.txt10
-rw-r--r--include/vnd_hammerhead.txt15
-rw-r--r--include/vnd_lenok.txt16
-rw-r--r--include/vnd_maguro.txt8
-rw-r--r--include/vnd_mako.txt8
-rw-r--r--include/vnd_manta.txt10
-rw-r--r--[-rwxr-xr-x]include/vnd_meson6.txt0
-rw-r--r--[-rwxr-xr-x]include/vnd_meson6_lpm.txt0
-rw-r--r--[-rwxr-xr-x]include/vnd_meson8.txt0
-rw-r--r--[-rwxr-xr-x]include/vnd_meson8_lpm.txt0
-rw-r--r--include/vnd_nemo.txt16
-rw-r--r--include/vnd_phantasm.txt8
-rw-r--r--include/vnd_puffer.txt15
-rw-r--r--include/vnd_shamu.txt14
-rw-r--r--include/vnd_smelt.txt14
-rw-r--r--include/vnd_sparrow.txt10
-rw-r--r--include/vnd_sprat.txt21
-rw-r--r--include/vnd_stingray.txt8
-rw-r--r--include/vnd_sturgeon.txt14
-rw-r--r--include/vnd_tetra.txt15
-rw-r--r--include/vnd_tilapia.txt10
-rw-r--r--include/vnd_toro.txt9
-rw-r--r--include/vnd_tuna.txt9
-rw-r--r--include/vnd_wingray.txt8
-rw-r--r--include/vnd_wren.txt10
-rwxr-xr-xsrc/bt_vendor_brcm.c23
-rwxr-xr-xsrc/hardware.c543
-rwxr-xr-xsrc/upio.c93
-rwxr-xr-xsrc/userial_vendor.c29
-rwxr-xr-xvnd_buildcfg.mk4
60 files changed, 1223 insertions, 147 deletions
diff --git a/src/hardware.c b/src/hardware.c
index 180325c..02103ca 100755
--- a/src/hardware.c
+++ b/src/hardware.c
@@ -39,8 +39,10 @@
#include <ctype.h>
#include <cutils/properties.h>
#include <stdlib.h>
+#include <string.h>
#include "bt_hci_bdroid.h"
#include "bt_vendor_brcm.h"
+#include "hci_audio.h"
#include "userial.h"
#include "userial_vendor.h"
#include "upio.h"
@@ -48,6 +50,7 @@
/******************************************************************************
** Constants & Macros
******************************************************************************/
+
#ifndef BTHW_DBG
#define BTHW_DBG FALSE
#endif
@@ -75,6 +78,7 @@
#define HCI_VSC_WRITE_SCO_PCM_INT_PARAM 0xFC1C
#define HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM 0xFC1E
#define HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM 0xFC6D
+#define HCI_VSC_ENABLE_WBS 0xFC7E
#define HCI_VSC_LAUNCH_RAM 0xFC4E
#define HCI_READ_LOCAL_BDADDR 0x1009
@@ -91,9 +95,17 @@
#define LOCAL_BDADDR_PATH_BUFFER_LEN 256
#define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
+#define UINT8_TO_STREAM(p, u8) {*(p)++ = (uint8_t)(u8);}
#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
#define UINT32_TO_STREAM(p, u32) {*(p)++ = (uint8_t)(u32); *(p)++ = (uint8_t)((u32) >> 8); *(p)++ = (uint8_t)((u32) >> 16); *(p)++ = (uint8_t)((u32) >> 24);}
+#define SCO_INTERFACE_PCM 0
+#define SCO_INTERFACE_I2S 1
+
+/* one byte is for enable/disable
+ next 2 bytes are for codec type */
+#define SCO_CODEC_PARAM_SIZE 3
+
/******************************************************************************
** Local type definitions
******************************************************************************/
@@ -159,11 +171,12 @@ extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
******************************************************************************/
static char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION;
-static char fw_patchfile_name[128] = {0};
+static char fw_patchfile_name[128] = { 0 };
#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
static int fw_patch_settlement_delay = -1;
#endif
+static int wbs_sample_rate = SCO_WBS_SAMPLE_RATE;
static bt_hw_cfg_cb_t hw_cfg_cb;
static bt_lpm_param_t lpm_param =
@@ -182,7 +195,9 @@ static bt_lpm_param_t lpm_param =
LPM_PULSED_HOST_WAKE
};
-#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
+/* need to update the bt_sco_i2spcm_param as well
+ bt_sco_i2spcm_param will be used for WBS setting
+ update the bt_sco_param and bt_sco_i2spcm_param */
static uint8_t bt_sco_param[SCO_PCM_PARAM_SIZE] =
{
SCO_PCM_ROUTING,
@@ -200,15 +215,14 @@ static uint8_t bt_pcm_data_fmt_param[PCM_DATA_FORMAT_PARAM_SIZE] =
PCM_DATA_FMT_FILL_NUM,
PCM_DATA_FMT_JUSTIFY_MODE
};
-#else
-static uint8_t bt_sco_param[SCO_I2SPCM_PARAM_SIZE] =
+
+static uint8_t bt_sco_i2spcm_param[SCO_I2SPCM_PARAM_SIZE] =
{
SCO_I2SPCM_IF_MODE,
SCO_I2SPCM_IF_ROLE,
SCO_I2SPCM_IF_SAMPLE_RATE,
SCO_I2SPCM_IF_CLOCK_RATE
};
-#endif
/*
* The look-up table of recommended firmware settlement delay (milliseconds) on
@@ -216,12 +230,34 @@ static uint8_t bt_sco_param[SCO_I2SPCM_PARAM_SIZE] =
*/
static const fw_settlement_entry_t fw_settlement_table[] = {
{"BCM43241", 200},
+ {"BCM43341", 100},
{(const char *) NULL, 100} // Giving the generic fw settlement delay setting.
};
+
+/*
+ * NOTICE:
+ * If the platform plans to run I2S interface bus over I2S/PCM port of the
+ * BT Controller with the Host AP, explicitly set "SCO_USE_I2S_INTERFACE = TRUE"
+ * in the correspodning include/vnd_<target>.txt file.
+ * Otherwise, leave SCO_USE_I2S_INTERFACE undefined in the vnd_<target>.txt file.
+ * And, PCM interface will be set as the default bus format running over I2S/PCM
+ * port.
+ */
+#if (defined(SCO_USE_I2S_INTERFACE) && SCO_USE_I2S_INTERFACE == TRUE)
+static uint8_t sco_bus_interface = SCO_INTERFACE_I2S;
+#else
+static uint8_t sco_bus_interface = SCO_INTERFACE_PCM;
+#endif
+
+#define INVALID_SCO_CLOCK_RATE 0xFF
+static uint8_t sco_bus_clock_rate = INVALID_SCO_CLOCK_RATE;
+static uint8_t sco_bus_wbs_clock_rate = INVALID_SCO_CLOCK_RATE;
+
/******************************************************************************
** Static functions
******************************************************************************/
+static void hw_sco_i2spcm_config(void *p_mem, uint16_t codec);
/******************************************************************************
** Controller Initialization Static Functions
@@ -585,6 +621,7 @@ void hw_config_cback(void *p_mem)
HC_BT_HDR *p_buf=NULL;
uint8_t is_proceeding = FALSE;
int i;
+ int delay=100;
#if (USE_CONTROLLER_BDADDR == TRUE)
const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
#endif
@@ -622,13 +659,12 @@ void hw_config_cback(void *p_mem)
p_buf->len = HCI_CMD_PREAMBLE_SIZE;
hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME;
- ms_delay(10);
+
is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, \
p_buf, hw_config_cback);
break;
case HW_CFG_READ_LOCAL_NAME:
- ALOGI("bt vendor lib: read local name");
p_tmp = p_name = (char *) (p_evt_buf + 1) + \
HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING;
@@ -665,7 +701,6 @@ void hw_config_cback(void *p_mem)
p_buf->len = HCI_CMD_PREAMBLE_SIZE;
hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER;
- ms_delay(50);
is_proceeding = bt_vendor_cbacks->xmit_cb( \
HCI_VSC_DOWNLOAD_MINIDRV, p_buf, \
@@ -686,13 +721,11 @@ void hw_config_cback(void *p_mem)
break;
case HW_CFG_DL_MINIDRIVER:
- ALOGI("bt vendor lib: download minidriver");
/* give time for placing firmware in download mode */
- ms_delay(100);
+ ms_delay(50);
hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
/* fall through intentionally */
case HW_CFG_DL_FW_PATCH:
- //ALOGI("bt vendor lib: download fw");
p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE);
if (p_buf->len > 0)
{
@@ -731,9 +764,17 @@ void hw_config_cback(void *p_mem)
/* Check if we need to pause a few hundred milliseconds
* before sending down any HCI command.
*/
- ms_delay(look_up_fw_settlement_delay());
+ delay = look_up_fw_settlement_delay();
+ ALOGI("Setting fw settlement delay to %d ", delay);
+ ms_delay(delay);
+
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+ UINT16_TO_STREAM(p, HCI_RESET);
+ *p = 0; /* parameter length */
+ hw_cfg_cb.state = HW_CFG_START;
+ is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_config_cback);
+ break;
- /* fall through intentionally */
case HW_CFG_START:
if (UART_TARGET_BAUD_RATE > 3000000)
{
@@ -774,7 +815,7 @@ void hw_config_cback(void *p_mem)
userial_vendor_set_baud( \
line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
);
- ms_delay(10);
+
#if (USE_CONTROLLER_BDADDR == TRUE)
if ((is_proceeding = hw_config_read_bdaddr(p_buf)) == TRUE)
break;
@@ -899,63 +940,146 @@ void hw_lpm_ctrl_cback(void *p_mem)
/*******************************************************************************
**
-** Function hw_sco_cfg_cback
+** Function hw_sco_i2spcm_cfg_cback
**
-** Description Callback function for SCO configuration rquest
+** Description Callback function for SCO I2S/PCM configuration rquest
**
** Returns None
**
*******************************************************************************/
-void hw_sco_cfg_cback(void *p_mem)
+static void hw_sco_i2spcm_cfg_cback(void *p_mem)
{
- HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
+ HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
uint8_t *p;
uint16_t opcode;
- HC_BT_HDR *p_buf=NULL;
+ HC_BT_HDR *p_buf = NULL;
+ bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL;
p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
STREAM_TO_UINT16(opcode,p);
+ if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0)
+ {
+ status = BT_VND_OP_RESULT_SUCCESS;
+ }
+
/* Free the RX event buffer */
if (bt_vendor_cbacks)
bt_vendor_cbacks->dealloc(p_evt_buf);
-#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
- if (opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM)
+ if (status == BT_VND_OP_RESULT_SUCCESS)
{
- uint8_t ret = FALSE;
-
- /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */
- if (bt_vendor_cbacks)
- p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
- HCI_CMD_PREAMBLE_SIZE + \
- PCM_DATA_FORMAT_PARAM_SIZE);
- if (p_buf)
+ if ((opcode == HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM) &&
+ (SCO_INTERFACE_PCM == sco_bus_interface))
{
- p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
- p_buf->offset = 0;
- p_buf->layer_specific = 0;
- p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE;
+ uint8_t ret = FALSE;
- p = (uint8_t *) (p_buf + 1);
- UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM);
- *p++ = PCM_DATA_FORMAT_PARAM_SIZE;
- memcpy(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE);
+ /* Ask a new buffer to hold WRITE_SCO_PCM_INT_PARAM command */
+ if (bt_vendor_cbacks)
+ p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
+ BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE);
+ if (p_buf)
+ {
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->layer_specific = 0;
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE;
+ p = (uint8_t *)(p_buf + 1);
+
+ /* do we need this VSC for I2S??? */
+ UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM);
+ *p++ = SCO_PCM_PARAM_SIZE;
+ memcpy(p, &bt_sco_param, SCO_PCM_PARAM_SIZE);
+ ALOGI("SCO PCM configure {0x%x, 0x%x, 0x%x, 0x%x, 0x%x}",
+ bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3],
+ bt_sco_param[4]);
+ if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SCO_PCM_INT_PARAM, p_buf,
+ hw_sco_i2spcm_cfg_cback)) == FALSE)
+ {
+ bt_vendor_cbacks->dealloc(p_buf);
+ }
+ else
+ return;
+ }
+ status = BT_VND_OP_RESULT_FAIL;
+ }
+ else if ((opcode == HCI_VSC_WRITE_SCO_PCM_INT_PARAM) &&
+ (SCO_INTERFACE_PCM == sco_bus_interface))
+ {
+ uint8_t ret = FALSE;
- if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM,\
- p_buf, hw_sco_cfg_cback)) == FALSE)
+ /* Ask a new buffer to hold WRITE_PCM_DATA_FORMAT_PARAM command */
+ if (bt_vendor_cbacks)
+ p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
+ BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE);
+ if (p_buf)
{
- bt_vendor_cbacks->dealloc(p_buf);
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->layer_specific = 0;
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + PCM_DATA_FORMAT_PARAM_SIZE;
+
+ p = (uint8_t *)(p_buf + 1);
+ UINT16_TO_STREAM(p, HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM);
+ *p++ = PCM_DATA_FORMAT_PARAM_SIZE;
+ memcpy(p, &bt_pcm_data_fmt_param, PCM_DATA_FORMAT_PARAM_SIZE);
+
+ ALOGI("SCO PCM data format {0x%x, 0x%x, 0x%x, 0x%x, 0x%x}",
+ bt_pcm_data_fmt_param[0], bt_pcm_data_fmt_param[1],
+ bt_pcm_data_fmt_param[2], bt_pcm_data_fmt_param[3],
+ bt_pcm_data_fmt_param[4]);
+
+ if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM,
+ p_buf, hw_sco_i2spcm_cfg_cback)) == FALSE)
+ {
+ bt_vendor_cbacks->dealloc(p_buf);
+ }
+ else
+ return;
}
- else
- return;
+ status = BT_VND_OP_RESULT_FAIL;
}
}
-#endif // !SCO_USE_I2S_INTERFACE
-if (bt_vendor_cbacks)
- bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
+ ALOGI("sco I2S/PCM config result %d [0-Success, 1-Fail]", status);
+ if (bt_vendor_cbacks)
+ {
+ bt_vendor_cbacks->audio_state_cb(status);
+ }
}
+
+/*******************************************************************************
+**
+** Function hw_set_MSBC_codec_cback
+**
+** Description Callback function for setting WBS codec
+**
+** Returns None
+**
+*******************************************************************************/
+static void hw_set_MSBC_codec_cback(void *p_mem)
+{
+ /* whenever update the codec enable/disable, need to update I2SPCM */
+ ALOGI("SCO I2S interface change the sample rate to 16K");
+ hw_sco_i2spcm_config(p_mem, SCO_CODEC_MSBC);
+}
+
+/*******************************************************************************
+**
+** Function hw_set_CVSD_codec_cback
+**
+** Description Callback function for setting NBS codec
+**
+** Returns None
+**
+*******************************************************************************/
+static void hw_set_CVSD_codec_cback(void *p_mem)
+{
+ /* whenever update the codec enable/disable, need to update I2SPCM */
+ ALOGI("SCO I2S interface change the sample rate to 8K");
+ hw_sco_i2spcm_config(p_mem, SCO_CODEC_CVSD);
+}
+
#endif // SCO_CFG_INCLUDED
/*****************************************************************************
@@ -1124,63 +1248,236 @@ void hw_lpm_set_wake_state(uint8_t wake_assert)
*******************************************************************************/
void hw_sco_config(void)
{
- HC_BT_HDR *p_buf = NULL;
- uint8_t *p, ret;
+ if (SCO_INTERFACE_I2S == sco_bus_interface)
+ {
+ /* 'Enable' I2S mode */
+ bt_sco_i2spcm_param[0] = 1;
-#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
- uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_PCM_PARAM_SIZE;
-#else
- uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_I2SPCM_PARAM_SIZE;
-#endif
+ /* set nbs clock rate as the value in SCO_I2SPCM_IF_CLOCK_RATE field */
+ sco_bus_clock_rate = bt_sco_i2spcm_param[3];
+ }
+ else
+ {
+ /* 'Disable' I2S mode */
+ bt_sco_i2spcm_param[0] = 0;
+
+ /* set nbs clock rate as the value in SCO_PCM_IF_CLOCK_RATE field */
+ sco_bus_clock_rate = bt_sco_param[1];
+
+ /* sync up clock mode setting */
+ bt_sco_i2spcm_param[1] = bt_sco_param[4];
+ }
+
+ if (sco_bus_wbs_clock_rate == INVALID_SCO_CLOCK_RATE)
+ {
+ /* set default wbs clock rate */
+ sco_bus_wbs_clock_rate = SCO_I2SPCM_IF_CLOCK_RATE4WBS;
+
+ if (sco_bus_wbs_clock_rate < sco_bus_clock_rate)
+ sco_bus_wbs_clock_rate = sco_bus_clock_rate;
+ }
+
+ /*
+ * To support I2S/PCM port multiplexing signals for sharing Bluetooth audio
+ * and FM on the same PCM pins, we defer Bluetooth audio (SCO/eSCO)
+ * configuration till SCO/eSCO is being established;
+ * i.e. in hw_set_audio_state() call.
+ */
+
+ if (bt_vendor_cbacks)
+ {
+ bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
+ }
+}
+
+/*******************************************************************************
+**
+** Function hw_sco_i2spcm_config
+**
+** Description Configure SCO over I2S or PCM
+**
+** Returns None
+**
+*******************************************************************************/
+static void hw_sco_i2spcm_config(void *p_mem, uint16_t codec)
+{
+ HC_BT_HDR *p_evt_buf = (HC_BT_HDR *)p_mem;
+ bt_vendor_op_result_t status = BT_VND_OP_RESULT_FAIL;
+
+ if (*((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE) == 0)
+ {
+ status = BT_VND_OP_RESULT_SUCCESS;
+ }
+
+ /* Free the RX event buffer */
+ if (bt_vendor_cbacks)
+ bt_vendor_cbacks->dealloc(p_evt_buf);
+
+ if (status == BT_VND_OP_RESULT_SUCCESS)
+ {
+ HC_BT_HDR *p_buf = NULL;
+ uint8_t *p, ret;
+ uint16_t cmd_u16 = HCI_CMD_PREAMBLE_SIZE + SCO_I2SPCM_PARAM_SIZE;
+
+ if (bt_vendor_cbacks)
+ p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + cmd_u16);
+
+ if (p_buf)
+ {
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->layer_specific = 0;
+ p_buf->len = cmd_u16;
+
+ p = (uint8_t *)(p_buf + 1);
+
+ UINT16_TO_STREAM(p, HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM);
+ *p++ = SCO_I2SPCM_PARAM_SIZE;
+ if (codec == SCO_CODEC_CVSD)
+ {
+ bt_sco_i2spcm_param[2] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE 8k */
+ bt_sco_i2spcm_param[3] = bt_sco_param[1] = sco_bus_clock_rate;
+ }
+ else if (codec == SCO_CODEC_MSBC)
+ {
+ bt_sco_i2spcm_param[2] = wbs_sample_rate; /* SCO_I2SPCM_IF_SAMPLE_RATE 16K */
+ bt_sco_i2spcm_param[3] = bt_sco_param[1] = sco_bus_wbs_clock_rate;
+ }
+ else
+ {
+ bt_sco_i2spcm_param[2] = 0; /* SCO_I2SPCM_IF_SAMPLE_RATE 8k */
+ bt_sco_i2spcm_param[3] = bt_sco_param[1] = sco_bus_clock_rate;
+ ALOGE("wrong codec is use in hw_sco_i2spcm_config, goes default NBS");
+ }
+ memcpy(p, &bt_sco_i2spcm_param, SCO_I2SPCM_PARAM_SIZE);
+ cmd_u16 = HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM;
+ ALOGI("I2SPCM config {0x%x, 0x%x, 0x%x, 0x%x}",
+ bt_sco_i2spcm_param[0], bt_sco_i2spcm_param[1],
+ bt_sco_i2spcm_param[2], bt_sco_i2spcm_param[3]);
+
+ if ((ret = bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf, hw_sco_i2spcm_cfg_cback)) == FALSE)
+ {
+ bt_vendor_cbacks->dealloc(p_buf);
+ }
+ else
+ return;
+ }
+ status = BT_VND_OP_RESULT_FAIL;
+ }
+
+ if (bt_vendor_cbacks)
+ {
+ bt_vendor_cbacks->audio_state_cb(status);
+ }
+}
+
+/*******************************************************************************
+**
+** Function hw_set_SCO_codec
+**
+** Description This functgion sends command to the controller to setup
+** WBS/NBS codec for the upcoming eSCO connection.
+**
+** Returns -1 : Failed to send VSC
+** 0 : Success
+**
+*******************************************************************************/
+static int hw_set_SCO_codec(uint16_t codec)
+{
+ HC_BT_HDR *p_buf = NULL;
+ uint8_t *p;
+ uint8_t ret;
+ int ret_val = 0;
+ tINT_CMD_CBACK p_set_SCO_codec_cback;
+
+ BTHWDBG( "hw_set_SCO_codec 0x%x", codec);
if (bt_vendor_cbacks)
- p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE+cmd_u16);
+ p_buf = (HC_BT_HDR *)bt_vendor_cbacks->alloc(
+ BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE + SCO_CODEC_PARAM_SIZE);
if (p_buf)
{
p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
p_buf->offset = 0;
p_buf->layer_specific = 0;
- p_buf->len = cmd_u16;
+ p = (uint8_t *)(p_buf + 1);
- p = (uint8_t *) (p_buf + 1);
-#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
- UINT16_TO_STREAM(p, HCI_VSC_WRITE_SCO_PCM_INT_PARAM);
- *p++ = SCO_PCM_PARAM_SIZE;
- memcpy(p, &bt_sco_param, SCO_PCM_PARAM_SIZE);
- cmd_u16 = HCI_VSC_WRITE_SCO_PCM_INT_PARAM;
- ALOGI("SCO PCM configure {%d, %d, %d, %d, %d}",
- bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3], \
- bt_sco_param[4]);
+ UINT16_TO_STREAM(p, HCI_VSC_ENABLE_WBS);
-#else
- UINT16_TO_STREAM(p, HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM);
- *p++ = SCO_I2SPCM_PARAM_SIZE;
- memcpy(p, &bt_sco_param, SCO_I2SPCM_PARAM_SIZE);
- cmd_u16 = HCI_VSC_WRITE_I2SPCM_INTERFACE_PARAM;
- ALOGI("SCO over I2SPCM interface {%d, %d, %d, %d}",
- bt_sco_param[0], bt_sco_param[1], bt_sco_param[2], bt_sco_param[3]);
-#endif
+ if (codec == SCO_CODEC_MSBC)
+ {
+ /* Enable mSBC */
+ *p++ = SCO_CODEC_PARAM_SIZE; /* set the parameter size */
+ UINT8_TO_STREAM(p,1); /* enable */
+ UINT16_TO_STREAM(p, codec);
- if ((ret=bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf, hw_sco_cfg_cback)) \
- == FALSE)
+ /* set the totall size of this packet */
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_CODEC_PARAM_SIZE;
+
+ p_set_SCO_codec_cback = hw_set_MSBC_codec_cback;
+ }
+ else
+ {
+ /* Disable mSBC */
+ *p++ = (SCO_CODEC_PARAM_SIZE - 2); /* set the parameter size */
+ UINT8_TO_STREAM(p,0); /* disable */
+
+ /* set the totall size of this packet */
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + SCO_CODEC_PARAM_SIZE - 2;
+
+ p_set_SCO_codec_cback = hw_set_CVSD_codec_cback;
+ if ((codec != SCO_CODEC_CVSD) && (codec != SCO_CODEC_NONE))
+ {
+ ALOGW("SCO codec setting is wrong: codec: 0x%x", codec);
+ }
+ }
+
+ if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_ENABLE_WBS, p_buf, p_set_SCO_codec_cback))\
+ == FALSE)
{
bt_vendor_cbacks->dealloc(p_buf);
+ ret_val = -1;
}
- else
- return;
}
-
- if (bt_vendor_cbacks)
+ else
{
- ALOGE("vendor lib scocfg aborted");
- bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_FAIL);
+ ret_val = -1;
}
+
+ return ret_val;
}
-#endif // SCO_CFG_INCLUDED
/*******************************************************************************
**
+** Function hw_set_audio_state
+**
+** Description This function configures audio base on provided audio state
+**
+** Paramters pointer to audio state structure
+**
+** Returns 0: ok, -1: error
+**
+*******************************************************************************/
+int hw_set_audio_state(bt_vendor_op_audio_state_t *p_state)
+{
+ int ret_val = -1;
+
+ if (!bt_vendor_cbacks)
+ return ret_val;
+
+ ret_val = hw_set_SCO_codec(p_state->peer_codec);
+ return ret_val;
+}
+
+#else // SCO_CFG_INCLUDED
+int hw_set_audio_state(bt_vendor_op_audio_state_t *p_state)
+{
+ return -256;
+}
+#endif
+/*******************************************************************************
+**
** Function hw_set_patch_file_path
**
** Description Set the location of firmware patch file
@@ -1234,3 +1531,89 @@ int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int par
}
#endif //VENDOR_LIB_RUNTIME_TUNING_ENABLED
+/*****************************************************************************
+** Sample Codes Section
+*****************************************************************************/
+
+#if (HW_END_WITH_HCI_RESET == TRUE)
+/*******************************************************************************
+**
+** Function hw_epilog_cback
+**
+** Description Callback function for Command Complete Events from HCI
+** commands sent in epilog process.
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_epilog_cback(void *p_mem)
+{
+ HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
+ uint8_t *p, status;
+ uint16_t opcode;
+
+ status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode,p);
+
+ BTHWDBG("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
+
+ if (bt_vendor_cbacks)
+ {
+ /* Must free the RX event buffer */
+ bt_vendor_cbacks->dealloc(p_evt_buf);
+
+ /* Once epilog process is done, must call epilog_cb callback
+ to notify caller */
+ bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
+ }
+}
+
+/*******************************************************************************
+**
+** Function hw_epilog_process
+**
+** Description Sample implementation of epilog process
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_epilog_process(void)
+{
+ HC_BT_HDR *p_buf = NULL;
+ uint8_t *p;
+
+ BTHWDBG("hw_epilog_process");
+
+ /* Sending a HCI_RESET */
+ if (bt_vendor_cbacks)
+ {
+ /* Must allocate command buffer via HC's alloc API */
+ p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
+ HCI_CMD_PREAMBLE_SIZE);
+ }
+
+ if (p_buf)
+ {
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->layer_specific = 0;
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+ p = (uint8_t *) (p_buf + 1);
+ UINT16_TO_STREAM(p, HCI_RESET);
+ *p = 0; /* parameter length */
+
+ /* Send command via HC's xmit_cb API */
+ bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback);
+ }
+ else
+ {
+ if (bt_vendor_cbacks)
+ {
+ ALOGE("vendor lib epilog process aborted [no buffer]");
+ bt_vendor_cbacks->epilog_cb(BT_VND_OP_RESULT_FAIL);
+ }
+ }
+}
+#endif // (HW_END_WITH_HCI_RESET == TRUE)