summaryrefslogtreecommitdiffstats
path: root/libbt/src
diff options
context:
space:
mode:
authorWink Saville <wink@google.com>2012-09-25 05:49:13 -0700
committerWink Saville <wink@google.com>2012-09-25 05:49:13 -0700
commit0c04d598f755c72cf9cca0eed41a43f1ec8e8697 (patch)
tree2371b38cd9cdff37a8c340d23319b866b4b7626a /libbt/src
parent60f0d406019cb4e9d48065e22891360969aa5966 (diff)
downloaddevice_common-0c04d598f755c72cf9cca0eed41a43f1ec8e8697.zip
device_common-0c04d598f755c72cf9cca0eed41a43f1ec8e8697.tar.gz
device_common-0c04d598f755c72cf9cca0eed41a43f1ec8e8697.tar.bz2
Move libbt-vendor from vendor/broadcom/libbt-vendor
Bug: 6837125 Change-Id: Ic3cc73f210e40d95b131a68244dc9e60bae80f37
Diffstat (limited to 'libbt/src')
-rw-r--r--libbt/src/bt_vendor_brcm.c227
-rw-r--r--libbt/src/conf.c147
-rw-r--r--libbt/src/hardware.c1155
-rw-r--r--libbt/src/upio.c298
-rwxr-xr-xlibbt/src/userial_vendor.c361
5 files changed, 2188 insertions, 0 deletions
diff --git a/libbt/src/bt_vendor_brcm.c b/libbt/src/bt_vendor_brcm.c
new file mode 100644
index 0000000..d17baa2
--- /dev/null
+++ b/libbt/src/bt_vendor_brcm.c
@@ -0,0 +1,227 @@
+/******************************************************************************
+ *
+ * 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 "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);
+
+/******************************************************************************
+** 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);
+
+ 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;
+ if (*state == BT_VND_PWR_OFF)
+ upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
+ else if (*state == BT_VND_PWR_ON)
+ upio_set_bluetooth_power(UPIO_BT_POWER_ON);
+ }
+ 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;
+ }
+
+ 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
+};
diff --git a/libbt/src/conf.c b/libbt/src/conf.c
new file mode 100644
index 0000000..39ac12e
--- /dev/null
+++ b/libbt/src/conf.c
@@ -0,0 +1,147 @@
+/******************************************************************************
+ *
+ * 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: conf.c
+ *
+ * Description: Contains functions to conduct run-time module configuration
+ * based on entries present in the .conf file
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_vnd_conf"
+
+#include <utils/Log.h>
+#include <string.h>
+#include "bt_vendor_brcm.h"
+
+/******************************************************************************
+** Externs
+******************************************************************************/
+int userial_set_port(char *p_conf_name, char *p_conf_value, int param);
+int hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param);
+int hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param);
+#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
+int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param);
+#endif
+
+
+/******************************************************************************
+** Local type definitions
+******************************************************************************/
+
+#define CONF_COMMENT '#'
+#define CONF_DELIMITERS " =\n\r\t"
+#define CONF_VALUES_DELIMITERS "=\n\r\t"
+#define CONF_MAX_LINE_LEN 255
+
+typedef int (conf_action_t)(char *p_conf_name, char *p_conf_value, int param);
+
+typedef struct {
+ const char *conf_entry;
+ conf_action_t *p_action;
+ int param;
+} conf_entry_t;
+
+/******************************************************************************
+** Static variables
+******************************************************************************/
+
+/*
+ * Current supported entries and corresponding action functions
+ */
+static const conf_entry_t conf_table[] = {
+ {"UartPort", userial_set_port, 0},
+ {"FwPatchFilePath", hw_set_patch_file_path, 0},
+ {"FwPatchFileName", hw_set_patch_file_name, 0},
+#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
+ {"FwPatchSettlementDelay", hw_set_patch_settlement_delay, 0},
+#endif
+ {(const char *) NULL, NULL, 0}
+};
+
+/*****************************************************************************
+** CONF INTERFACE FUNCTIONS
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function vnd_load_conf
+**
+** Description Read conf entry from p_path file one by one and call
+** the corresponding config function
+**
+** Returns None
+**
+*******************************************************************************/
+void vnd_load_conf(const char *p_path)
+{
+ FILE *p_file;
+ char *p_name;
+ char *p_value;
+ conf_entry_t *p_entry;
+ char line[CONF_MAX_LINE_LEN+1]; /* add 1 for \0 char */
+
+ ALOGI("Attempt to load conf from %s", p_path);
+
+ if ((p_file = fopen(p_path, "r")) != NULL)
+ {
+ /* read line by line */
+ while (fgets(line, CONF_MAX_LINE_LEN+1, p_file) != NULL)
+ {
+ if (line[0] == CONF_COMMENT)
+ continue;
+
+ p_name = strtok(line, CONF_DELIMITERS);
+
+ if (NULL == p_name)
+ {
+ continue;
+ }
+
+ p_value = strtok(NULL, CONF_DELIMITERS);
+
+ if (NULL == p_value)
+ {
+ ALOGW("vnd_load_conf: missing value for name: %s", p_name);
+ continue;
+ }
+
+ p_entry = (conf_entry_t *)conf_table;
+
+ while (p_entry->conf_entry != NULL)
+ {
+ if (strcmp(p_entry->conf_entry, (const char *)p_name) == 0)
+ {
+ p_entry->p_action(p_name, p_value, p_entry->param);
+ break;
+ }
+
+ p_entry++;
+ }
+ }
+
+ fclose(p_file);
+ }
+ else
+ {
+ ALOGI( "vnd_load_conf file >%s< not found", p_path);
+ }
+}
+
diff --git a/libbt/src/hardware.c b/libbt/src/hardware.c
new file mode 100644
index 0000000..a6868e1
--- /dev/null
+++ b/libbt/src/hardware.c
@@ -0,0 +1,1155 @@
+/******************************************************************************
+ *
+ * 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: hardware.c
+ *
+ * Description: Contains controller-specific functions, like
+ * firmware patch download
+ * low power mode operations
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_hwcfg"
+
+#include <utils/Log.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <cutils/properties.h>
+#include <stdlib.h>
+#include "bt_hci_bdroid.h"
+#include "bt_vendor_brcm.h"
+#include "userial.h"
+#include "userial_vendor.h"
+#include "upio.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+
+#ifndef BTHW_DBG
+#define BTHW_DBG FALSE
+#endif
+
+#if (BTHW_DBG == TRUE)
+#define BTHWDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
+#else
+#define BTHWDBG(param, ...) {}
+#endif
+
+#define FW_PATCHFILE_EXTENSION ".hcd"
+#define FW_PATCHFILE_EXTENSION_LEN 4
+#define FW_PATCHFILE_PATH_MAXLEN 248 /* Local_Name length of return of
+ HCI_Read_Local_Name */
+
+#define HCI_CMD_MAX_LEN 258
+
+#define HCI_RESET 0x0C03
+#define HCI_VSC_WRITE_UART_CLOCK_SETTING 0xFC45
+#define HCI_VSC_UPDATE_BAUDRATE 0xFC18
+#define HCI_READ_LOCAL_NAME 0x0C14
+#define HCI_VSC_DOWNLOAD_MINIDRV 0xFC2E
+#define HCI_VSC_WRITE_BD_ADDR 0xFC01
+#define HCI_VSC_WRITE_SLEEP_MODE 0xFC27
+#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_LAUNCH_RAM 0xFC4E
+
+#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5
+#define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING 6
+#define HCI_EVT_CMD_CMPL_OPCODE 3
+#define LPM_CMD_PARAM_SIZE 12
+#define UPDATE_BAUDRATE_CMD_PARAM_SIZE 6
+#define HCI_CMD_PREAMBLE_SIZE 3
+#define HCD_REC_PAYLOAD_LEN_BYTE 2
+#define BD_ADDR_LEN 6
+#define LOCAL_NAME_BUFFER_LEN 32
+#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 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);}
+
+/******************************************************************************
+** Local type definitions
+******************************************************************************/
+
+/* Hardware Configuration State */
+enum {
+ HW_CFG_START = 1,
+ HW_CFG_SET_UART_CLOCK,
+ HW_CFG_SET_UART_BAUD_1,
+ HW_CFG_READ_LOCAL_NAME,
+ HW_CFG_DL_MINIDRIVER,
+ HW_CFG_DL_FW_PATCH,
+ HW_CFG_SET_UART_BAUD_2,
+ HW_CFG_SET_BD_ADDR
+};
+
+/* h/w config control block */
+typedef struct
+{
+ uint8_t state; /* Hardware configuration state */
+ int fw_fd; /* FW patch file fd */
+ uint8_t f_set_baud_2; /* Baud rate switch state */
+ char local_chip_name[LOCAL_NAME_BUFFER_LEN];
+} bt_hw_cfg_cb_t;
+
+/* low power mode parameters */
+typedef struct
+{
+ uint8_t sleep_mode; /* 0(disable),1(UART),9(H5) */
+ uint8_t host_stack_idle_threshold; /* Unit scale 300ms/25ms */
+ uint8_t host_controller_idle_threshold; /* Unit scale 300ms/25ms */
+ uint8_t bt_wake_polarity; /* 0=Active Low, 1= Active High */
+ uint8_t host_wake_polarity; /* 0=Active Low, 1= Active High */
+ uint8_t allow_host_sleep_during_sco;
+ uint8_t combine_sleep_mode_and_lpm;
+ uint8_t enable_uart_txd_tri_state; /* UART_TXD Tri-State */
+ uint8_t sleep_guard_time; /* sleep guard time in 12.5ms */
+ uint8_t wakeup_guard_time; /* wakeup guard time in 12.5ms */
+ uint8_t txd_config; /* TXD is high in sleep state */
+ uint8_t pulsed_host_wake; /* pulsed host wake if mode = 1 */
+} bt_lpm_param_t;
+
+/* Firmware re-launch settlement time */
+typedef struct {
+ const char *chipset_name;
+ const uint32_t delay_time;
+} fw_settlement_entry_t;
+
+
+/******************************************************************************
+** Externs
+******************************************************************************/
+
+void hw_config_cback(void *p_evt_buf);
+extern uint8_t vnd_local_bd_addr[BD_ADDR_LEN];
+
+
+/******************************************************************************
+** Static variables
+******************************************************************************/
+
+static char fw_patchfile_path[256] = FW_PATCHFILE_LOCATION;
+static char fw_patchfile_name[128] = { 0 };
+#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
+static int fw_patch_settlement_delay = -1;
+#endif
+
+static bt_hw_cfg_cb_t hw_cfg_cb;
+
+static bt_lpm_param_t lpm_param =
+{
+ LPM_SLEEP_MODE,
+ LPM_IDLE_THRESHOLD,
+ LPM_HC_IDLE_THRESHOLD,
+ LPM_BT_WAKE_POLARITY,
+ LPM_HOST_WAKE_POLARITY,
+ LPM_ALLOW_HOST_SLEEP_DURING_SCO,
+ LPM_COMBINE_SLEEP_MODE_AND_LPM,
+ LPM_ENABLE_UART_TXD_TRI_STATE,
+ 0, /* not applicable */
+ 0, /* not applicable */
+ 0, /* not applicable */
+ LPM_PULSED_HOST_WAKE
+};
+
+#if (!defined(SCO_USE_I2S_INTERFACE) || (SCO_USE_I2S_INTERFACE == FALSE))
+static uint8_t bt_sco_param[SCO_PCM_PARAM_SIZE] =
+{
+ SCO_PCM_ROUTING,
+ SCO_PCM_IF_CLOCK_RATE,
+ SCO_PCM_IF_FRAME_TYPE,
+ SCO_PCM_IF_SYNC_MODE,
+ SCO_PCM_IF_CLOCK_MODE
+};
+
+static uint8_t bt_pcm_data_fmt_param[PCM_DATA_FORMAT_PARAM_SIZE] =
+{
+ PCM_DATA_FMT_SHIFT_MODE,
+ PCM_DATA_FMT_FILL_BITS,
+ PCM_DATA_FMT_FILL_METHOD,
+ PCM_DATA_FMT_FILL_NUM,
+ PCM_DATA_FMT_JUSTIFY_MODE
+};
+#else
+static uint8_t bt_sco_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
+ * known chipsets.
+ */
+static const fw_settlement_entry_t fw_settlement_table[] = {
+ {"BCM43241", 200},
+ {(const char *) NULL, 100} // Giving the generic fw settlement delay setting.
+};
+
+/******************************************************************************
+** Static functions
+******************************************************************************/
+
+/******************************************************************************
+** Controller Initialization Static Functions
+******************************************************************************/
+
+/*******************************************************************************
+**
+** Function look_up_fw_settlement_delay
+**
+** Description If FW_PATCH_SETTLEMENT_DELAY_MS has not been explicitly
+** re-defined in the platform specific build-time configuration
+** file, we will search into the look-up table for a
+** recommended firmware settlement delay value.
+**
+** Although the settlement time might be also related to board
+** configurations such as the crystal clocking speed.
+**
+** Returns Firmware settlement delay
+**
+*******************************************************************************/
+uint32_t look_up_fw_settlement_delay (void)
+{
+ uint32_t ret_value;
+ fw_settlement_entry_t *p_entry;
+
+ if (FW_PATCH_SETTLEMENT_DELAY_MS > 0)
+ {
+ ret_value = FW_PATCH_SETTLEMENT_DELAY_MS;
+ }
+#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
+ else if (fw_patch_settlement_delay >= 0)
+ {
+ ret_value = fw_patch_settlement_delay;
+ }
+#endif
+ else
+ {
+ p_entry = (fw_settlement_entry_t *)fw_settlement_table;
+
+ while (p_entry->chipset_name != NULL)
+ {
+ if (strstr(hw_cfg_cb.local_chip_name, p_entry->chipset_name)!=NULL)
+ {
+ break;
+ }
+
+ p_entry++;
+ }
+
+ ret_value = p_entry->delay_time;
+ }
+
+ BTHWDBG( "Settlement delay -- %d ms", ret_value);
+
+ return (ret_value);
+}
+
+/*******************************************************************************
+**
+** Function ms_delay
+**
+** Description sleep unconditionally for timeout milliseconds
+**
+** Returns None
+**
+*******************************************************************************/
+void ms_delay (uint32_t timeout)
+{
+ struct timespec delay;
+ int err;
+
+ if (timeout == 0)
+ return;
+
+ delay.tv_sec = timeout / 1000;
+ delay.tv_nsec = 1000 * 1000 * (timeout%1000);
+
+ /* [u]sleep can't be used because it uses SIGALRM */
+ do {
+ err = nanosleep(&delay, &delay);
+ } while (err < 0 && errno ==EINTR);
+}
+
+/*******************************************************************************
+**
+** Function line_speed_to_userial_baud
+**
+** Description helper function converts line speed number into USERIAL baud
+** rate symbol
+**
+** Returns unit8_t (USERIAL baud symbol)
+**
+*******************************************************************************/
+uint8_t line_speed_to_userial_baud(uint32_t line_speed)
+{
+ uint8_t baud;
+
+ if (line_speed == 4000000)
+ baud = USERIAL_BAUD_4M;
+ else if (line_speed == 3000000)
+ baud = USERIAL_BAUD_3M;
+ else if (line_speed == 2000000)
+ baud = USERIAL_BAUD_2M;
+ else if (line_speed == 1000000)
+ baud = USERIAL_BAUD_1M;
+ else if (line_speed == 921600)
+ baud = USERIAL_BAUD_921600;
+ else if (line_speed == 460800)
+ baud = USERIAL_BAUD_460800;
+ else if (line_speed == 230400)
+ baud = USERIAL_BAUD_230400;
+ else if (line_speed == 115200)
+ baud = USERIAL_BAUD_115200;
+ else if (line_speed == 57600)
+ baud = USERIAL_BAUD_57600;
+ else if (line_speed == 19200)
+ baud = USERIAL_BAUD_19200;
+ else if (line_speed == 9600)
+ baud = USERIAL_BAUD_9600;
+ else if (line_speed == 1200)
+ baud = USERIAL_BAUD_1200;
+ else if (line_speed == 600)
+ baud = USERIAL_BAUD_600;
+ else
+ {
+ ALOGE( "userial vendor: unsupported baud speed %d", line_speed);
+ baud = USERIAL_BAUD_115200;
+ }
+
+ return baud;
+}
+
+
+/*******************************************************************************
+**
+** Function hw_strncmp
+**
+** Description Used to compare two strings in caseless
+**
+** Returns 0: match, otherwise: not match
+**
+*******************************************************************************/
+static int hw_strncmp (const char *p_str1, const char *p_str2, const int len)
+{
+ int i;
+
+ if (!p_str1 || !p_str2)
+ return (1);
+
+ for (i = 0; i < len; i++)
+ {
+ if (toupper(p_str1[i]) != toupper(p_str2[i]))
+ return (i+1);
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function hw_config_findpatch
+**
+** Description Search for a proper firmware patch file
+** The selected firmware patch file name with full path
+** will be stored in the input string parameter, i.e.
+** p_chip_id_str, when returns.
+**
+** Returns TRUE when found the target patch file, otherwise FALSE
+**
+*******************************************************************************/
+static uint8_t hw_config_findpatch(char *p_chip_id_str)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ int filenamelen;
+ uint8_t retval = FALSE;
+
+ BTHWDBG("Target name = [%s]", p_chip_id_str);
+
+ if (strlen(fw_patchfile_name)> 0)
+ {
+ /* If specific filepath and filename have been given in run-time
+ * configuration /etc/bluetooth/bt_vendor.conf file, we will use them
+ * to concatenate the filename to open rather than searching a file
+ * matching to chipset name in the fw_patchfile_path folder.
+ */
+ sprintf(p_chip_id_str, "%s", fw_patchfile_path);
+ if (fw_patchfile_path[strlen(fw_patchfile_path)- 1] != '/')
+ {
+ strcat(p_chip_id_str, "/");
+ }
+ strcat(p_chip_id_str, fw_patchfile_name);
+
+ ALOGI("FW patchfile: %s", p_chip_id_str);
+ return TRUE;
+ }
+
+ if ((dirp = opendir(fw_patchfile_path)) != NULL)
+ {
+ /* Fetch next filename in patchfile directory */
+ while ((dp = readdir(dirp)) != NULL)
+ {
+ /* Check if filename starts with chip-id name */
+ if ((hw_strncmp(dp->d_name, p_chip_id_str, strlen(p_chip_id_str)) \
+ ) == 0)
+ {
+ /* Check if it has .hcd extenstion */
+ filenamelen = strlen(dp->d_name);
+ if ((filenamelen >= FW_PATCHFILE_EXTENSION_LEN) &&
+ ((hw_strncmp(
+ &dp->d_name[filenamelen-FW_PATCHFILE_EXTENSION_LEN], \
+ FW_PATCHFILE_EXTENSION, \
+ FW_PATCHFILE_EXTENSION_LEN) \
+ ) == 0))
+ {
+ ALOGI("Found patchfile: %s/%s", \
+ fw_patchfile_path, dp->d_name);
+
+ /* Make sure length does not exceed maximum */
+ if ((filenamelen + strlen(fw_patchfile_path)) > \
+ FW_PATCHFILE_PATH_MAXLEN)
+ {
+ ALOGE("Invalid patchfile name (too long)");
+ }
+ else
+ {
+ memset(p_chip_id_str, 0, FW_PATCHFILE_PATH_MAXLEN);
+ /* Found patchfile. Store location and name */
+ strcpy(p_chip_id_str, fw_patchfile_path);
+ if (fw_patchfile_path[ \
+ strlen(fw_patchfile_path)- 1 \
+ ] != '/')
+ {
+ strcat(p_chip_id_str, "/");
+ }
+ strcat(p_chip_id_str, dp->d_name);
+ retval = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ closedir(dirp);
+
+ if (retval == FALSE)
+ {
+ /* Try again chip name without revision info */
+
+ int len = strlen(p_chip_id_str);
+ char *p = p_chip_id_str + len - 1;
+
+ /* Scan backward and look for the first alphabet
+ which is not M or m
+ */
+ while (len > 3) // BCM****
+ {
+ if ((isdigit(*p)==0) && (*p != 'M') && (*p != 'm'))
+ break;
+
+ p--;
+ len--;
+ }
+
+ if (len > 3)
+ {
+ *p = 0;
+ retval = hw_config_findpatch(p_chip_id_str);
+ }
+ }
+ }
+ else
+ {
+ ALOGE("Could not open %s", fw_patchfile_path);
+ }
+
+ return (retval);
+}
+
+/*******************************************************************************
+**
+** Function hw_config_set_bdaddr
+**
+** Description Program controller's Bluetooth Device Address
+**
+** Returns TRUE, if valid address is sent
+** FALSE, otherwise
+**
+*******************************************************************************/
+static uint8_t hw_config_set_bdaddr(HC_BT_HDR *p_buf)
+{
+ uint8_t retval = FALSE;
+ uint8_t *p = (uint8_t *) (p_buf + 1);
+
+ ALOGI("Setting local bd addr to %02X:%02X:%02X:%02X:%02X:%02X",
+ vnd_local_bd_addr[0], vnd_local_bd_addr[1], vnd_local_bd_addr[2],
+ vnd_local_bd_addr[3], vnd_local_bd_addr[4], vnd_local_bd_addr[5]);
+
+ UINT16_TO_STREAM(p, HCI_VSC_WRITE_BD_ADDR);
+ *p++ = BD_ADDR_LEN; /* parameter length */
+ *p++ = vnd_local_bd_addr[5];
+ *p++ = vnd_local_bd_addr[4];
+ *p++ = vnd_local_bd_addr[3];
+ *p++ = vnd_local_bd_addr[2];
+ *p++ = vnd_local_bd_addr[1];
+ *p = vnd_local_bd_addr[0];
+
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + BD_ADDR_LEN;
+ hw_cfg_cb.state = HW_CFG_SET_BD_ADDR;
+
+ retval = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_BD_ADDR, p_buf, \
+ hw_config_cback);
+
+ return (retval);
+}
+
+/*******************************************************************************
+**
+** Function hw_config_cback
+**
+** Description Callback function for controller configuration
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_config_cback(void *p_mem)
+{
+ HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
+ char *p_name, *p_tmp;
+ uint8_t *p, status;
+ uint16_t opcode;
+ HC_BT_HDR *p_buf=NULL;
+ uint8_t is_proceeding = FALSE;
+ int i;
+
+ 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);
+
+ /* Ask a new buffer big enough to hold any HCI commands sent in here */
+ if ((status == 0) && bt_vendor_cbacks)
+ p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
+ HCI_CMD_MAX_LEN);
+
+ if (p_buf != NULL)
+ {
+ p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+ p_buf->offset = 0;
+ p_buf->len = 0;
+ p_buf->layer_specific = 0;
+
+ p = (uint8_t *) (p_buf + 1);
+
+ switch (hw_cfg_cb.state)
+ {
+ case HW_CFG_SET_UART_BAUD_1:
+ /* update baud rate of host's UART port */
+ ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
+ userial_vendor_set_baud( \
+ line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
+ );
+
+ /* read local name */
+ UINT16_TO_STREAM(p, HCI_READ_LOCAL_NAME);
+ *p = 0; /* parameter length */
+
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+ hw_cfg_cb.state = HW_CFG_READ_LOCAL_NAME;
+
+ is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_NAME, \
+ p_buf, hw_config_cback);
+ break;
+
+ case HW_CFG_READ_LOCAL_NAME:
+ p_tmp = p_name = (char *) (p_evt_buf + 1) + \
+ HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING;
+
+ for (i=0; (i < LOCAL_NAME_BUFFER_LEN)||(*(p_name+i) != 0); i++)
+ *(p_name+i) = toupper(*(p_name+i));
+
+ if ((p_name = strstr(p_name, "BCM")) != NULL)
+ {
+ strncpy(hw_cfg_cb.local_chip_name, p_name, \
+ LOCAL_NAME_BUFFER_LEN-1);
+ }
+ else
+ {
+ strncpy(hw_cfg_cb.local_chip_name, "UNKNOWN", \
+ LOCAL_NAME_BUFFER_LEN-1);
+ p_name = p_tmp;
+ }
+
+ hw_cfg_cb.local_chip_name[LOCAL_NAME_BUFFER_LEN-1] = 0;
+
+ BTHWDBG("Chipset %s", hw_cfg_cb.local_chip_name);
+
+ if ((status = hw_config_findpatch(p_name)) == TRUE)
+ {
+ if ((hw_cfg_cb.fw_fd = open(p_name, O_RDONLY)) == -1)
+ {
+ ALOGE("vendor lib preload failed to open [%s]", p_name);
+ }
+ else
+ {
+ /* vsc_download_minidriver */
+ UINT16_TO_STREAM(p, HCI_VSC_DOWNLOAD_MINIDRV);
+ *p = 0; /* parameter length */
+
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+ hw_cfg_cb.state = HW_CFG_DL_MINIDRIVER;
+
+ is_proceeding = bt_vendor_cbacks->xmit_cb( \
+ HCI_VSC_DOWNLOAD_MINIDRV, p_buf, \
+ hw_config_cback);
+ }
+ }
+ else
+ {
+ ALOGE( \
+ "vendor lib preload failed to locate firmware patch file" \
+ );
+ }
+
+ if (is_proceeding == FALSE)
+ {
+ is_proceeding = hw_config_set_bdaddr(p_buf);
+ }
+ break;
+
+ case HW_CFG_DL_MINIDRIVER:
+ /* give time for placing firmware in download mode */
+ ms_delay(50);
+ hw_cfg_cb.state = HW_CFG_DL_FW_PATCH;
+ /* fall through intentionally */
+ case HW_CFG_DL_FW_PATCH:
+ p_buf->len = read(hw_cfg_cb.fw_fd, p, HCI_CMD_PREAMBLE_SIZE);
+ if (p_buf->len > 0)
+ {
+ if ((p_buf->len < HCI_CMD_PREAMBLE_SIZE) || \
+ (opcode == HCI_VSC_LAUNCH_RAM))
+ {
+ ALOGW("firmware patch file might be altered!");
+ }
+ else
+ {
+ p_buf->len += read(hw_cfg_cb.fw_fd, \
+ p+HCI_CMD_PREAMBLE_SIZE,\
+ *(p+HCD_REC_PAYLOAD_LEN_BYTE));
+ STREAM_TO_UINT16(opcode,p);
+ is_proceeding = bt_vendor_cbacks->xmit_cb(opcode, \
+ p_buf, hw_config_cback);
+ break;
+ }
+ }
+
+ close(hw_cfg_cb.fw_fd);
+ hw_cfg_cb.fw_fd = -1;
+
+ /* Normally the firmware patch configuration file
+ * sets the new starting baud rate at 115200.
+ * So, we need update host's baud rate accordingly.
+ */
+ ALOGI("bt vendor lib: set UART baud 115200");
+ userial_vendor_set_baud(USERIAL_BAUD_115200);
+
+ /* Next, we would like to boost baud rate up again
+ * to desired working speed.
+ */
+ hw_cfg_cb.f_set_baud_2 = TRUE;
+
+ /* Check if we need to pause a few hundred milliseconds
+ * before sending down any HCI command.
+ */
+ ms_delay(look_up_fw_settlement_delay());
+
+ /* fall through intentionally */
+ case HW_CFG_START:
+ if (UART_TARGET_BAUD_RATE > 3000000)
+ {
+ /* set UART clock to 48MHz */
+ UINT16_TO_STREAM(p, HCI_VSC_WRITE_UART_CLOCK_SETTING);
+ *p++ = 1; /* parameter length */
+ *p = 1; /* (1,"UART CLOCK 48 MHz")(2,"UART CLOCK 24 MHz") */
+
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + 1;
+ hw_cfg_cb.state = HW_CFG_SET_UART_CLOCK;
+
+ is_proceeding = bt_vendor_cbacks->xmit_cb( \
+ HCI_VSC_WRITE_UART_CLOCK_SETTING, \
+ p_buf, hw_config_cback);
+ break;
+ }
+ /* fall through intentionally */
+ case HW_CFG_SET_UART_CLOCK:
+ /* set controller's UART baud rate to 3M */
+ UINT16_TO_STREAM(p, HCI_VSC_UPDATE_BAUDRATE);
+ *p++ = UPDATE_BAUDRATE_CMD_PARAM_SIZE; /* parameter length */
+ *p++ = 0; /* encoded baud rate */
+ *p++ = 0; /* use encoded form */
+ UINT32_TO_STREAM(p, UART_TARGET_BAUD_RATE);
+
+ p_buf->len = HCI_CMD_PREAMBLE_SIZE + \
+ UPDATE_BAUDRATE_CMD_PARAM_SIZE;
+ hw_cfg_cb.state = (hw_cfg_cb.f_set_baud_2) ? \
+ HW_CFG_SET_UART_BAUD_2 : HW_CFG_SET_UART_BAUD_1;
+
+ is_proceeding = bt_vendor_cbacks->xmit_cb(HCI_VSC_UPDATE_BAUDRATE, \
+ p_buf, hw_config_cback);
+ break;
+
+ case HW_CFG_SET_UART_BAUD_2:
+ /* update baud rate of host's UART port */
+ ALOGI("bt vendor lib: set UART baud %i", UART_TARGET_BAUD_RATE);
+ userial_vendor_set_baud( \
+ line_speed_to_userial_baud(UART_TARGET_BAUD_RATE) \
+ );
+
+ if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
+ break;
+
+ /* fall through intentionally */
+ case HW_CFG_SET_BD_ADDR:
+ ALOGI("vendor lib fwcfg completed");
+ bt_vendor_cbacks->dealloc(p_buf);
+ bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+
+ hw_cfg_cb.state = 0;
+
+ if (hw_cfg_cb.fw_fd != -1)
+ {
+ close(hw_cfg_cb.fw_fd);
+ hw_cfg_cb.fw_fd = -1;
+ }
+
+ is_proceeding = TRUE;
+ break;
+ } // switch(hw_cfg_cb.state)
+ } // if (p_buf != NULL)
+
+ /* Free the RX event buffer */
+ if (bt_vendor_cbacks)
+ bt_vendor_cbacks->dealloc(p_evt_buf);
+
+ if (is_proceeding == FALSE)
+ {
+ ALOGE("vendor lib fwcfg aborted!!!");
+ if (bt_vendor_cbacks)
+ {
+ if (p_buf != NULL)
+ bt_vendor_cbacks->dealloc(p_buf);
+
+ bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
+ }
+
+ if (hw_cfg_cb.fw_fd != -1)
+ {
+ close(hw_cfg_cb.fw_fd);
+ hw_cfg_cb.fw_fd = -1;
+ }
+
+ hw_cfg_cb.state = 0;
+ }
+}
+
+/******************************************************************************
+** LPM Static Functions
+******************************************************************************/
+
+/*******************************************************************************
+**
+** Function hw_lpm_ctrl_cback
+**
+** Description Callback function for lpm enable/disable rquest
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_lpm_ctrl_cback(void *p_mem)
+{
+ 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;
+ }
+
+ if (bt_vendor_cbacks)
+ {
+ bt_vendor_cbacks->lpm_cb(status);
+ bt_vendor_cbacks->dealloc(p_evt_buf);
+ }
+}
+
+
+#if (SCO_CFG_INCLUDED == TRUE)
+/*****************************************************************************
+** SCO Configuration Static Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function hw_sco_cfg_cback
+**
+** Description Callback function for SCO configuration rquest
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_sco_cfg_cback(void *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;
+
+ p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+ STREAM_TO_UINT16(opcode,p);
+
+ /* 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)
+ {
+ 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);
+
+ if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_PCM_DATA_FORMAT_PARAM,\
+ p_buf, hw_sco_cfg_cback)) == FALSE)
+ {
+ bt_vendor_cbacks->dealloc(p_buf);
+ }
+ else
+ return;
+ }
+ }
+#endif // !SCO_USE_I2S_INTERFACE
+
+if (bt_vendor_cbacks)
+ bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_SUCCESS);
+}
+#endif // SCO_CFG_INCLUDED
+
+/*****************************************************************************
+** Hardware Configuration Interface Functions
+*****************************************************************************/
+
+
+/*******************************************************************************
+**
+** Function hw_config_start
+**
+** Description Kick off controller initialization process
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_config_start(void)
+{
+ HC_BT_HDR *p_buf = NULL;
+ uint8_t *p;
+
+ hw_cfg_cb.state = 0;
+ hw_cfg_cb.fw_fd = -1;
+ hw_cfg_cb.f_set_baud_2 = FALSE;
+
+ /* Start from sending HCI_RESET */
+
+ if (bt_vendor_cbacks)
+ {
+ 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 */
+
+ hw_cfg_cb.state = HW_CFG_START;
+
+ bt_vendor_cbacks->xmit_cb(HCI_RESET, p_buf, hw_config_cback);
+ }
+ else
+ {
+ if (bt_vendor_cbacks)
+ {
+ ALOGE("vendor lib fw conf aborted [no buffer]");
+ bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function hw_lpm_enable
+**
+** Description Enalbe/Disable LPM
+**
+** Returns TRUE/FALSE
+**
+*******************************************************************************/
+uint8_t hw_lpm_enable(uint8_t turn_on)
+{
+ HC_BT_HDR *p_buf = NULL;
+ uint8_t *p;
+ uint8_t ret = FALSE;
+
+ if (bt_vendor_cbacks)
+ p_buf = (HC_BT_HDR *) bt_vendor_cbacks->alloc(BT_HC_HDR_SIZE + \
+ HCI_CMD_PREAMBLE_SIZE + \
+ LPM_CMD_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 + LPM_CMD_PARAM_SIZE;
+
+ p = (uint8_t *) (p_buf + 1);
+ UINT16_TO_STREAM(p, HCI_VSC_WRITE_SLEEP_MODE);
+ *p++ = LPM_CMD_PARAM_SIZE; /* parameter length */
+
+ if (turn_on)
+ {
+ memcpy(p, &lpm_param, LPM_CMD_PARAM_SIZE);
+ }
+ else
+ {
+ memset(p, 0, LPM_CMD_PARAM_SIZE);
+ }
+
+ if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SLEEP_MODE, p_buf, \
+ hw_lpm_ctrl_cback)) == FALSE)
+ {
+ bt_vendor_cbacks->dealloc(p_buf);
+ }
+ }
+
+ if ((ret == FALSE) && bt_vendor_cbacks)
+ bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_FAIL);
+
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function hw_lpm_get_idle_timeout
+**
+** Description Calculate idle time based on host stack idle threshold
+**
+** Returns idle timeout value
+**
+*******************************************************************************/
+uint32_t hw_lpm_get_idle_timeout(void)
+{
+ uint32_t timeout_ms;
+
+ /* set idle time to be LPM_IDLE_TIMEOUT_MULTIPLE times of
+ * host stack idle threshold (in 300ms/25ms)
+ */
+ timeout_ms = (uint32_t)lpm_param.host_stack_idle_threshold \
+ * LPM_IDLE_TIMEOUT_MULTIPLE;
+
+ if (strstr(hw_cfg_cb.local_chip_name, "BCM4325") != NULL)
+ timeout_ms *= 25; // 12.5 or 25 ?
+ else
+ timeout_ms *= 300;
+
+ return timeout_ms;
+}
+
+/*******************************************************************************
+**
+** Function hw_lpm_set_wake_state
+**
+** Description Assert/Deassert BT_WAKE
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_lpm_set_wake_state(uint8_t wake_assert)
+{
+ uint8_t state = (wake_assert) ? UPIO_ASSERT : UPIO_DEASSERT;
+
+ upio_set(UPIO_BT_WAKE, state, lpm_param.bt_wake_polarity);
+}
+
+#if (SCO_CFG_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function hw_sco_config
+**
+** Description Configure SCO related hardware settings
+**
+** Returns None
+**
+*******************************************************************************/
+void hw_sco_config(void)
+{
+ HC_BT_HDR *p_buf = NULL;
+ uint8_t *p, ret;
+
+#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
+
+ 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);
+#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]);
+
+#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)
+ {
+ bt_vendor_cbacks->dealloc(p_buf);
+ }
+ else
+ return;
+ }
+
+ if (bt_vendor_cbacks)
+ {
+ ALOGE("vendor lib scocfg aborted");
+ bt_vendor_cbacks->scocfg_cb(BT_VND_OP_RESULT_FAIL);
+ }
+}
+#endif // SCO_CFG_INCLUDED
+
+/*******************************************************************************
+**
+** Function hw_set_patch_file_path
+**
+** Description Set the location of firmware patch file
+**
+** Returns 0 : Success
+** Otherwise : Fail
+**
+*******************************************************************************/
+int hw_set_patch_file_path(char *p_conf_name, char *p_conf_value, int param)
+{
+
+ strcpy(fw_patchfile_path, p_conf_value);
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function hw_set_patch_file_name
+**
+** Description Give the specific firmware patch filename
+**
+** Returns 0 : Success
+** Otherwise : Fail
+**
+*******************************************************************************/
+int hw_set_patch_file_name(char *p_conf_name, char *p_conf_value, int param)
+{
+
+ strcpy(fw_patchfile_name, p_conf_value);
+
+ return 0;
+}
+
+#if (VENDOR_LIB_RUNTIME_TUNING_ENABLED == TRUE)
+/*******************************************************************************
+**
+** Function hw_set_patch_settlement_delay
+**
+** Description Give the specific firmware patch settlement time in milliseconds
+**
+** Returns 0 : Success
+** Otherwise : Fail
+**
+*******************************************************************************/
+int hw_set_patch_settlement_delay(char *p_conf_name, char *p_conf_value, int param)
+{
+ fw_patch_settlement_delay = atoi(p_conf_value);
+
+ return 0;
+}
+#endif //VENDOR_LIB_RUNTIME_TUNING_ENABLED
+
diff --git a/libbt/src/upio.c b/libbt/src/upio.c
new file mode 100644
index 0000000..d32f334
--- /dev/null
+++ b/libbt/src/upio.c
@@ -0,0 +1,298 @@
+/******************************************************************************
+ *
+ * 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: upio.c
+ *
+ * Description: Contains I/O functions, like
+ * rfkill control
+ * BT_WAKE/HOST_WAKE control
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_upio"
+
+#include <utils/Log.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <cutils/properties.h>
+#include "bt_vendor_brcm.h"
+#include "upio.h"
+#include "userial_vendor.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+
+#ifndef UPIO_DBG
+#define UPIO_DBG FALSE
+#endif
+
+#if (UPIO_DBG == TRUE)
+#define UPIODBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
+#else
+#define UPIODBG(param, ...) {}
+#endif
+
+/******************************************************************************
+** Local type definitions
+******************************************************************************/
+
+/******************************************************************************
+** Static variables
+******************************************************************************/
+
+static uint8_t upio_state[UPIO_MAX_COUNT];
+static int rfkill_id = -1;
+static int bt_emul_enable = 0;
+static char *rfkill_state_path = NULL;
+
+/******************************************************************************
+** Static functions
+******************************************************************************/
+
+/* for friendly debugging outpout string */
+static char *lpm_state[] = {
+ "UNKNOWN",
+ "de-asserted",
+ "asserted"
+};
+
+/*****************************************************************************
+** Bluetooth On/Off Static Functions
+*****************************************************************************/
+static int is_emulator_context(void)
+{
+ char value[PROPERTY_VALUE_MAX];
+
+ property_get("ro.kernel.qemu", value, "0");
+ UPIODBG("is_emulator_context : %s", value);
+ if (strcmp(value, "1") == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+static int is_rfkill_disabled(void)
+{
+ char value[PROPERTY_VALUE_MAX];
+
+ property_get("ro.rfkilldisabled", value, "0");
+ UPIODBG("is_rfkill_disabled ? [%s]", value);
+
+ if (strcmp(value, "1") == 0) {
+ return UPIO_BT_POWER_ON;
+ }
+
+ return UPIO_BT_POWER_OFF;
+}
+
+static int init_rfkill()
+{
+ char path[64];
+ char buf[16];
+ int fd, sz, id;
+
+ if (is_rfkill_disabled())
+ return -1;
+
+ for (id = 0; ; id++)
+ {
+ snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ {
+ ALOGE("init_rfkill : open(%s) failed: %s (%d)\n", \
+ path, strerror(errno), errno);
+ return -1;
+ }
+
+ sz = read(fd, &buf, sizeof(buf));
+ close(fd);
+
+ if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0)
+ {
+ rfkill_id = id;
+ break;
+ }
+ }
+
+ asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
+ return 0;
+}
+
+/*****************************************************************************
+** LPM Static Functions
+*****************************************************************************/
+
+/*****************************************************************************
+** UPIO Interface Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function upio_init
+**
+** Description Initialization
+**
+** Returns None
+**
+*******************************************************************************/
+void upio_init(void)
+{
+ memset(upio_state, UPIO_UNKNOWN, UPIO_MAX_COUNT);
+}
+
+/*******************************************************************************
+**
+** Function upio_cleanup
+**
+** Description Clean up
+**
+** Returns None
+**
+*******************************************************************************/
+void upio_cleanup(void)
+{
+}
+
+/*******************************************************************************
+**
+** Function upio_set_bluetooth_power
+**
+** Description Interact with low layer driver to set Bluetooth power
+** on/off.
+**
+** Returns 0 : SUCCESS or Not-Applicable
+** <0 : ERROR
+**
+*******************************************************************************/
+int upio_set_bluetooth_power(int on)
+{
+ int sz;
+ int fd = -1;
+ int ret = -1;
+ char buffer = '0';
+
+ switch(on)
+ {
+ case UPIO_BT_POWER_OFF:
+ buffer = '0';
+ break;
+
+ case UPIO_BT_POWER_ON:
+ buffer = '1';
+ break;
+ }
+
+ if (is_emulator_context())
+ {
+ /* if new value is same as current, return -1 */
+ if (bt_emul_enable == on)
+ return ret;
+
+ UPIODBG("set_bluetooth_power [emul] %d", on);
+
+ bt_emul_enable = on;
+ return 0;
+ }
+
+ /* check if we have rfkill interface */
+ if (is_rfkill_disabled())
+ return 0;
+
+ if (rfkill_id == -1)
+ {
+ if (init_rfkill())
+ return ret;
+ }
+
+ fd = open(rfkill_state_path, O_WRONLY);
+
+ if (fd < 0)
+ {
+ ALOGE("set_bluetooth_power : open(%s) for write failed: %s (%d)",
+ rfkill_state_path, strerror(errno), errno);
+ return ret;
+ }
+
+ sz = write(fd, &buffer, 1);
+
+ if (sz < 0) {
+ ALOGE("set_bluetooth_power : write(%s) failed: %s (%d)",
+ rfkill_state_path, strerror(errno),errno);
+ }
+ else
+ ret = 0;
+
+ if (fd >= 0)
+ close(fd);
+
+ return ret;
+}
+
+
+/*******************************************************************************
+**
+** Function upio_set
+**
+** Description Set i/o based on polarity
+**
+** Returns None
+**
+*******************************************************************************/
+void upio_set(uint8_t pio, uint8_t action, uint8_t polarity)
+{
+ int rc;
+
+ switch (pio)
+ {
+ case UPIO_BT_WAKE:
+
+ if (upio_state[UPIO_BT_WAKE] == action)
+ {
+ UPIODBG("BT_WAKE is %s already", lpm_state[action]);
+ return;
+ }
+
+ upio_state[UPIO_BT_WAKE] = action;
+
+ /****************************************
+ * !!! TODO !!!
+ *
+ * === Custom Porting Required ===
+ *
+ * Platform dependent user-to-kernel
+ * interface is required to set output
+ * state of physical BT_WAKE pin.
+ ****************************************/
+#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE)
+ userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \
+ USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\
+ NULL);
+#endif
+ break;
+
+ case UPIO_HOST_WAKE:
+ UPIODBG("upio_set: UPIO_HOST_WAKE");
+ break;
+ }
+}
+
+
diff --git a/libbt/src/userial_vendor.c b/libbt/src/userial_vendor.c
new file mode 100755
index 0000000..1a745b5
--- /dev/null
+++ b/libbt/src/userial_vendor.c
@@ -0,0 +1,361 @@
+/******************************************************************************
+ *
+ * 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: userial_vendor.c
+ *
+ * Description: Contains vendor-specific userial functions
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_userial_vendor"
+
+#include <utils/Log.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include "bt_vendor_brcm.h"
+#include "userial.h"
+#include "userial_vendor.h"
+
+/******************************************************************************
+** Constants & Macros
+******************************************************************************/
+
+#ifndef VNDUSERIAL_DBG
+#define VNDUSERIAL_DBG FALSE
+#endif
+
+#if (VNDUSERIAL_DBG == TRUE)
+#define VNDUSERIALDBG(param, ...) {ALOGD(param, ## __VA_ARGS__);}
+#else
+#define VNDUSERIALDBG(param, ...) {}
+#endif
+
+#define VND_PORT_NAME_MAXLEN 256
+
+/******************************************************************************
+** Local type definitions
+******************************************************************************/
+
+/* vendor serial control block */
+typedef struct
+{
+ int fd; /* fd to Bluetooth device */
+ struct termios termios; /* serial terminal of BT port */
+ char port_name[VND_PORT_NAME_MAXLEN];
+} vnd_userial_cb_t;
+
+/******************************************************************************
+** Static variables
+******************************************************************************/
+
+static vnd_userial_cb_t vnd_userial;
+
+/*****************************************************************************
+** Helper Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function userial_to_tcio_baud
+**
+** Description helper function converts USERIAL baud rates into TCIO
+** conforming baud rates
+**
+** Returns TRUE/FALSE
+**
+*******************************************************************************/
+uint8_t userial_to_tcio_baud(uint8_t cfg_baud, uint32_t *baud)
+{
+ if (cfg_baud == USERIAL_BAUD_115200)
+ *baud = B115200;
+ else if (cfg_baud == USERIAL_BAUD_4M)
+ *baud = B4000000;
+ else if (cfg_baud == USERIAL_BAUD_3M)
+ *baud = B3000000;
+ else if (cfg_baud == USERIAL_BAUD_2M)
+ *baud = B2000000;
+ else if (cfg_baud == USERIAL_BAUD_1M)
+ *baud = B1000000;
+ else if (cfg_baud == USERIAL_BAUD_921600)
+ *baud = B921600;
+ else if (cfg_baud == USERIAL_BAUD_460800)
+ *baud = B460800;
+ else if (cfg_baud == USERIAL_BAUD_230400)
+ *baud = B230400;
+ else if (cfg_baud == USERIAL_BAUD_57600)
+ *baud = B57600;
+ else if (cfg_baud == USERIAL_BAUD_19200)
+ *baud = B19200;
+ else if (cfg_baud == USERIAL_BAUD_9600)
+ *baud = B9600;
+ else if (cfg_baud == USERIAL_BAUD_1200)
+ *baud = B1200;
+ else if (cfg_baud == USERIAL_BAUD_600)
+ *baud = B600;
+ else
+ {
+ ALOGE( "userial vendor open: unsupported baud idx %i", cfg_baud);
+ *baud = B115200;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+/*******************************************************************************
+**
+** Function userial_ioctl_init_bt_wake
+**
+** Description helper function to set the open state of the bt_wake if ioctl
+** is used. it should not hurt in the rfkill case but it might
+** be better to compile it out.
+**
+** Returns none
+**
+*******************************************************************************/
+void userial_ioctl_init_bt_wake(int fd)
+{
+ uint32_t bt_wake_state;
+
+ /* assert BT_WAKE through ioctl */
+ ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL);
+ ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, &bt_wake_state);
+ VNDUSERIALDBG("userial_ioctl_init_bt_wake read back BT_WAKE state=%i", \
+ bt_wake_state);
+}
+#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+
+
+/*****************************************************************************
+** Userial Vendor API Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function userial_vendor_init
+**
+** Description Initialize userial vendor-specific control block
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_init(void)
+{
+ vnd_userial.fd = -1;
+ snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", \
+ BLUETOOTH_UART_DEVICE_PORT);
+}
+
+/*******************************************************************************
+**
+** Function userial_vendor_open
+**
+** Description Open the serial port with the given configuration
+**
+** Returns device fd
+**
+*******************************************************************************/
+int userial_vendor_open(tUSERIAL_CFG *p_cfg)
+{
+ uint32_t baud;
+ uint8_t data_bits;
+ uint16_t parity;
+ uint8_t stop_bits;
+
+ vnd_userial.fd = -1;
+
+ if (!userial_to_tcio_baud(p_cfg->baud, &baud))
+ {
+ return -1;
+ }
+
+ if(p_cfg->fmt & USERIAL_DATABITS_8)
+ data_bits = CS8;
+ else if(p_cfg->fmt & USERIAL_DATABITS_7)
+ data_bits = CS7;
+ else if(p_cfg->fmt & USERIAL_DATABITS_6)
+ data_bits = CS6;
+ else if(p_cfg->fmt & USERIAL_DATABITS_5)
+ data_bits = CS5;
+ else
+ {
+ ALOGE("userial vendor open: unsupported data bits");
+ return -1;
+ }
+
+ if(p_cfg->fmt & USERIAL_PARITY_NONE)
+ parity = 0;
+ else if(p_cfg->fmt & USERIAL_PARITY_EVEN)
+ parity = PARENB;
+ else if(p_cfg->fmt & USERIAL_PARITY_ODD)
+ parity = (PARENB | PARODD);
+ else
+ {
+ ALOGE("userial vendor open: unsupported parity bit mode");
+ return -1;
+ }
+
+ if(p_cfg->fmt & USERIAL_STOPBITS_1)
+ stop_bits = 0;
+ else if(p_cfg->fmt & USERIAL_STOPBITS_2)
+ stop_bits = CSTOPB;
+ else
+ {
+ ALOGE("userial vendor open: unsupported stop bits");
+ return -1;
+ }
+
+ ALOGI("userial vendor open: opening %s", vnd_userial.port_name);
+
+ if ((vnd_userial.fd = open(vnd_userial.port_name, O_RDWR)) == -1)
+ {
+ ALOGE("userial vendor open: unable to open %s", vnd_userial.port_name);
+ return -1;
+ }
+
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+
+ tcgetattr(vnd_userial.fd, &vnd_userial.termios);
+ cfmakeraw(&vnd_userial.termios);
+ vnd_userial.termios.c_cflag |= (CRTSCTS | stop_bits);
+ tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+
+ tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+ tcflush(vnd_userial.fd, TCIOFLUSH);
+
+ /* set input/output baudrate */
+ cfsetospeed(&vnd_userial.termios, baud);
+ cfsetispeed(&vnd_userial.termios, baud);
+ tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+ userial_ioctl_init_bt_wake(vnd_userial.fd);
+#endif
+
+ ALOGI("device fd = %d open", vnd_userial.fd);
+
+ return vnd_userial.fd;
+}
+
+/*******************************************************************************
+**
+** Function userial_vendor_close
+**
+** Description Conduct vendor-specific close work
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_close(void)
+{
+ int result;
+
+ if (vnd_userial.fd == -1)
+ return;
+
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+ /* de-assert bt_wake BEFORE closing port */
+ ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL);
+#endif
+
+ ALOGI("device fd = %d close", vnd_userial.fd);
+
+ if ((result = close(vnd_userial.fd)) < 0)
+ ALOGE( "close(fd:%d) FAILED result:%d", vnd_userial.fd, result);
+
+ vnd_userial.fd = -1;
+}
+
+/*******************************************************************************
+**
+** Function userial_vendor_set_baud
+**
+** Description Set new baud rate
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_set_baud(uint8_t userial_baud)
+{
+ uint32_t tcio_baud;
+
+ userial_to_tcio_baud(userial_baud, &tcio_baud);
+
+ cfsetospeed(&vnd_userial.termios, tcio_baud);
+ cfsetispeed(&vnd_userial.termios, tcio_baud);
+ tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+}
+
+/*******************************************************************************
+**
+** Function userial_vendor_ioctl
+**
+** Description ioctl inteface
+**
+** Returns None
+**
+*******************************************************************************/
+void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data)
+{
+ switch(op)
+ {
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+ case USERIAL_OP_ASSERT_BT_WAKE:
+ VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##");
+ ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL);
+ break;
+
+ case USERIAL_OP_DEASSERT_BT_WAKE:
+ VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##");
+ ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL);
+ break;
+
+ case USERIAL_OP_GET_BT_WAKE_STATE:
+ ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data);
+ break;
+#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+
+ default:
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function userial_set_port
+**
+** Description Configure UART port name
+**
+** Returns 0 : Success
+** Otherwise : Fail
+**
+*******************************************************************************/
+int userial_set_port(char *p_conf_name, char *p_conf_value, int param)
+{
+ strcpy(vnd_userial.port_name, p_conf_value);
+
+ return 0;
+}
+