am 6a471c63: am 4b08afea: dory: Set btwrite timer timeout to 0
* commit '6a471c634a05f8fe1f3d51609e3d3dd99e3c7af5':
dory: Set btwrite timer timeout to 0
diff --git a/include/bt_vendor_brcm.h b/include/bt_vendor_brcm.h
old mode 100644
new mode 100755
index d81e54a..86254ff
--- a/include/bt_vendor_brcm.h
+++ b/include/bt_vendor_brcm.h
@@ -218,6 +218,10 @@
#define BT_WAKE_VIA_PROC FALSE
#endif
+#ifndef BT_WAKE_VIA_PROC_NOTIFY_DEASSERT
+#define BT_WAKE_VIA_PROC_NOTIFY_DEASSERT FALSE
+#endif
+
/* N_BRCM_HCI
UART ioctl line discipline
@@ -240,9 +244,22 @@
#define SCO_USE_I2S_INTERFACE FALSE
#endif
-#if (SCO_USE_I2S_INTERFACE == TRUE)
#define SCO_I2SPCM_PARAM_SIZE 4
+/* SCO_WBS_SAMPLE_RATE
+ 0 : 8K
+ 1 : 16K
+ 2 : 4K
+ This macro is used for setting WBS sampling rate for a SCO connection
+ If the mobile network supports WBS, we need to use 16KHz as default
+ but if the platform doesn't support 16KHz, the sample rate can be
+ overriden to 8KHz by setting this to 0.
+*/
+#ifndef SCO_WBS_SAMPLE_RATE
+#define SCO_WBS_SAMPLE_RATE 1
+#endif
+
+
/* SCO_I2SPCM_IF_MODE - 0=Disable, 1=Enable */
#ifndef SCO_I2SPCM_IF_MODE
#define SCO_I2SPCM_IF_MODE 1
@@ -274,7 +291,18 @@
#ifndef SCO_I2SPCM_IF_CLOCK_RATE
#define SCO_I2SPCM_IF_CLOCK_RATE 1
#endif
-#endif // SCO_USE_I2S_INTERFACE
+
+/* SCO_I2SPCM_IF_CLOCK_RATE4WBS
+
+ 0 : 128K
+ 1 : 256K
+ 2 : 512K
+ 3 : 1024K
+ 4 : 2048K
+*/
+#ifndef SCO_I2SPCM_IF_CLOCK_RATE4WBS
+#define SCO_I2SPCM_IF_CLOCK_RATE4WBS 2
+#endif
#define SCO_PCM_PARAM_SIZE 5
@@ -292,6 +320,8 @@
/* SCO_PCM_IF_CLOCK_RATE
+ NOTICE: suggested to be consistent with SCO_I2SPCM_IF_CLOCK_RATE
+
0 : 128K
1 : 256K
2 : 512K
@@ -307,12 +337,25 @@
#define SCO_PCM_IF_FRAME_TYPE 0
#endif
-/* SCO_PCM_IF_SYNC_MODE - 0=Slave, 1=Master */
+/* SCO_PCM_IF_SYNC_MODE
+
+ NOTICE: in most usage cases the value will be the same as
+ SCO_PCM_IF_CLOCK_MODE setting
+
+ 0 : Slave
+ 1 : Master
+*/
#ifndef SCO_PCM_IF_SYNC_MODE
#define SCO_PCM_IF_SYNC_MODE 0
#endif
-/* SCO_PCM_IF_CLOCK_MODE - 0=Slave, 1=Master */
+/* SCO_PCM_IF_CLOCK_MODE
+
+ NOTICE: suggested to be consistent with SCO_I2SPCM_IF_ROLE
+
+ 0 : Slave
+ 1 : Master
+*/
#ifndef SCO_PCM_IF_CLOCK_MODE
#define SCO_PCM_IF_CLOCK_MODE 0
#endif
@@ -381,5 +424,7 @@
extern bt_vendor_callbacks_t *bt_vendor_cbacks;
+extern int hw_set_audio_state(bt_vendor_op_audio_state_t *p_state);
+
#endif /* BT_VENDOR_BRCM_H */
diff --git a/include/vnd_flounder.txt b/include/vnd_flounder.txt
new file mode 100644
index 0000000..a366b9c
--- /dev/null
+++ b/include/vnd_flounder.txt
@@ -0,0 +1,10 @@
+VENDOR_BTWRITE_PROC_NODE = "/proc/bluetooth/sleep/lpm"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = FALSE
+SCO_PCM_IF_CLOCK_RATE = 3
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+BT_WAKE_VIA_PROC_NOTIFY_DEASSERT = TRUE
+BT_WAKE_VIA_PROC = TRUE
+UPIO_DBG = FALSE
diff --git a/include/vnd_flounder64.txt b/include/vnd_flounder64.txt
new file mode 100644
index 0000000..a366b9c
--- /dev/null
+++ b/include/vnd_flounder64.txt
@@ -0,0 +1,10 @@
+VENDOR_BTWRITE_PROC_NODE = "/proc/bluetooth/sleep/lpm"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = FALSE
+SCO_PCM_IF_CLOCK_RATE = 3
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+BT_WAKE_VIA_PROC_NOTIFY_DEASSERT = TRUE
+BT_WAKE_VIA_PROC = TRUE
+UPIO_DBG = FALSE
diff --git a/include/vnd_fugu.txt b/include/vnd_fugu.txt
new file mode 100644
index 0000000..e9106c4
--- /dev/null
+++ b/include/vnd_fugu.txt
@@ -0,0 +1,11 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyMFD0"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+BT_WAKE_VIA_PROC = FALSE
+BT_WAKE_VIA_USERIAL_IOCTL = FALSE
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+BTVND_DBG = TRUE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = TRUE
+UPIO_DBG = TRUE
+SCO_PCM_IF_CLOCK_RATE = 2
+USE_CONTROLLER_BDADDR = FALSE
diff --git a/include/vnd_hammerhead.txt b/include/vnd_hammerhead.txt
old mode 100644
new mode 100755
index 5c465a5..aa2f928
--- a/include/vnd_hammerhead.txt
+++ b/include/vnd_hammerhead.txt
@@ -6,6 +6,7 @@
LPM_BT_WAKE_POLARITY = 0
LPM_HOST_WAKE_POLARITY = 0
SCO_USE_I2S_INTERFACE = FALSE
+SCO_WBS_SAMPLE_RATE = 0
SCO_I2SPCM_IF_ROLE = 0
BTVND_DBG = FALSE
BTHW_DBG = TRUE
diff --git a/include/vnd_shamu.txt b/include/vnd_shamu.txt
new file mode 100644
index 0000000..3249bf4
--- /dev/null
+++ b/include/vnd_shamu.txt
@@ -0,0 +1,13 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS0"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+BT_WAKE_VIA_PROC = TRUE
+UART_TARGET_BAUD_RATE = 3000000
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+LPM_BT_WAKE_POLARITY = 0
+LPM_HOST_WAKE_POLARITY = 0
+SCO_USE_I2S_INTERFACE = FALSE
+SCO_I2SPCM_IF_ROLE = 0
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/src/bt_vendor_brcm.c b/src/bt_vendor_brcm.c
old mode 100644
new mode 100755
index ef6236f..cc84105
--- a/src/bt_vendor_brcm.c
+++ b/src/bt_vendor_brcm.c
@@ -207,6 +207,12 @@
}
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)
diff --git a/src/hardware.c b/src/hardware.c
old mode 100644
new mode 100755
index e2eb7d7..db7d26a
--- a/src/hardware.c
+++ b/src/hardware.c
@@ -76,6 +76,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
@@ -92,9 +93,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
******************************************************************************/
@@ -165,6 +174,7 @@
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 =
@@ -183,7 +193,9 @@
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,
@@ -201,15 +213,14 @@
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
@@ -221,9 +232,30 @@
{(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
@@ -900,63 +932,146 @@
/*******************************************************************************
**
-** 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);
-
- 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_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)
{
- 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 + 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;
}
- 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;
+
+ /* 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)
+ {
+ 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;
+ }
+ 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
/*****************************************************************************
@@ -1125,61 +1240,234 @@
*******************************************************************************/
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)
- p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE+cmd_u16);
+ {
+ 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 + 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 ((ret=bt_vendor_cbacks->xmit_cb(cmd_u16, p_buf, hw_sco_cfg_cback)) \
- == FALSE)
+ if (codec == SCO_CODEC_MSBC)
{
- bt_vendor_cbacks->dealloc(p_buf);
+ /* Enable mSBC */
+ *p++ = SCO_CODEC_PARAM_SIZE; /* set the parameter size */
+ UINT8_TO_STREAM(p,1); /* enable */
+ UINT16_TO_STREAM(p, codec);
+
+ /* 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
- return;
- }
+ {
+ /* Disable mSBC */
+ *p++ = (SCO_CODEC_PARAM_SIZE - 2); /* set the parameter size */
+ UINT8_TO_STREAM(p,0); /* disable */
- if (bt_vendor_cbacks)
+ /* 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
{
- ALOGE("vendor lib scocfg aborted");
- bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_FAIL);
+ ret_val = -1;
}
-}
-#endif // SCO_CFG_INCLUDED
+ return ret_val;
+}
+
+/*******************************************************************************
+**
+** 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
diff --git a/src/upio.c b/src/upio.c
index 9008355..c996865 100644
--- a/src/upio.c
+++ b/src/upio.c
@@ -436,9 +436,10 @@
/*
* Kick proc btwrite node only at UPIO_ASSERT
*/
+#if (BT_WAKE_VIA_PROC_NOTIFY_DEASSERT == FALSE)
if (action == UPIO_DEASSERT)
return;
-
+#endif
fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY);
if (fd < 0)
@@ -447,8 +448,12 @@
VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno);
return;
}
-
- buffer = '1';
+#if (BT_WAKE_VIA_PROC_NOTIFY_DEASSERT == TRUE)
+ if (action == UPIO_DEASSERT)
+ buffer = '0';
+ else
+#endif
+ buffer = '1';
if (write(fd, &buffer, 1) < 0)
{
diff --git a/src/userial_vendor.c b/src/userial_vendor.c
old mode 100755
new mode 100644
index b9c5f69..0f3f527
--- a/src/userial_vendor.c
+++ b/src/userial_vendor.c
@@ -294,7 +294,8 @@
#endif
ALOGI("device fd = %d close", vnd_userial.fd);
-
+ // flush Tx before close to make sure no chars in buffer
+ tcflush(vnd_userial.fd, TCIOFLUSH);
if ((result = close(vnd_userial.fd)) < 0)
ALOGE( "close(fd:%d) FAILED result:%d", vnd_userial.fd, result);