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) |