Merge libbt/ from device/common to /
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..2ab3cc6
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,47 @@
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(BOARD_HAVE_BLUETOOTH_BCM),)
+
+include $(CLEAR_VARS)
+
+BDROID_DIR := $(TOP_DIR)external/bluetooth/bluedroid
+
+LOCAL_SRC_FILES := \
+        src/bt_vendor_brcm.c \
+        src/hardware.c \
+        src/userial_vendor.c \
+        src/upio.c \
+        src/conf.c
+
+LOCAL_C_INCLUDES += \
+        $(LOCAL_PATH)/include \
+        $(BDROID_DIR)/hci/include
+
+LOCAL_SHARED_LIBRARIES := \
+        libcutils \
+        liblog
+
+LOCAL_MODULE := libbt-vendor
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_OWNER := broadcom
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)
+
+include $(LOCAL_PATH)/vnd_buildcfg.mk
+
+include $(BUILD_SHARED_LIBRARY)
+
+ifeq ($(TARGET_PRODUCT), full_maguro)
+    include $(LOCAL_PATH)/conf/samsung/maguro/Android.mk
+endif
+ifeq ($(TARGET_PRODUCT), full_crespo)
+    include $(LOCAL_PATH)/conf/samsung/crespo/Android.mk
+endif
+ifeq ($(TARGET_PRODUCT), full_crespo4g)
+    include $(LOCAL_PATH)/conf/samsung/crespo4g/Android.mk
+endif
+ifeq ($(TARGET_PRODUCT), full_wingray)
+    include $(LOCAL_PATH)/conf/moto/wingray/Android.mk
+endif
+
+endif # BOARD_HAVE_BLUETOOTH_BCM
diff --git a/conf/asus/grouper/Android.mk b/conf/asus/grouper/Android.mk
new file mode 100644
index 0000000..974e213
--- /dev/null
+++ b/conf/asus/grouper/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bt_vendor.conf
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
+
diff --git a/conf/asus/grouper/bt_vendor.conf b/conf/asus/grouper/bt_vendor.conf
new file mode 100644
index 0000000..94fa0cd
--- /dev/null
+++ b/conf/asus/grouper/bt_vendor.conf
@@ -0,0 +1,5 @@
+# UART device port where Bluetooth controller is attached
+UartPort = /dev/ttyHS2
+
+# Firmware patch file location
+FwPatchFilePath = /etc/firmware/
diff --git a/conf/moto/wingray/Android.mk b/conf/moto/wingray/Android.mk
new file mode 100644
index 0000000..974e213
--- /dev/null
+++ b/conf/moto/wingray/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bt_vendor.conf
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
+
diff --git a/conf/moto/wingray/bt_vendor.conf b/conf/moto/wingray/bt_vendor.conf
new file mode 100644
index 0000000..94fa0cd
--- /dev/null
+++ b/conf/moto/wingray/bt_vendor.conf
@@ -0,0 +1,5 @@
+# UART device port where Bluetooth controller is attached
+UartPort = /dev/ttyHS2
+
+# Firmware patch file location
+FwPatchFilePath = /etc/firmware/
diff --git a/conf/samsung/crespo/Android.mk b/conf/samsung/crespo/Android.mk
new file mode 100644
index 0000000..974e213
--- /dev/null
+++ b/conf/samsung/crespo/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bt_vendor.conf
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
+
diff --git a/conf/samsung/crespo/bt_vendor.conf b/conf/samsung/crespo/bt_vendor.conf
new file mode 100644
index 0000000..1f471ca
--- /dev/null
+++ b/conf/samsung/crespo/bt_vendor.conf
@@ -0,0 +1,5 @@
+# UART device port where Bluetooth controller is attached
+UartPort = /dev/s3c2410_serial0
+
+# Firmware patch file location
+FwPatchFilePath = /vendor/firmware/
diff --git a/conf/samsung/crespo4g/Android.mk b/conf/samsung/crespo4g/Android.mk
new file mode 100644
index 0000000..974e213
--- /dev/null
+++ b/conf/samsung/crespo4g/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bt_vendor.conf
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
+
diff --git a/conf/samsung/crespo4g/bt_vendor.conf b/conf/samsung/crespo4g/bt_vendor.conf
new file mode 100644
index 0000000..1f471ca
--- /dev/null
+++ b/conf/samsung/crespo4g/bt_vendor.conf
@@ -0,0 +1,5 @@
+# UART device port where Bluetooth controller is attached
+UartPort = /dev/s3c2410_serial0
+
+# Firmware patch file location
+FwPatchFilePath = /vendor/firmware/
diff --git a/conf/samsung/maguro/Android.mk b/conf/samsung/maguro/Android.mk
new file mode 100644
index 0000000..974e213
--- /dev/null
+++ b/conf/samsung/maguro/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bt_vendor.conf
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth
+
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
+
diff --git a/conf/samsung/maguro/bt_vendor.conf b/conf/samsung/maguro/bt_vendor.conf
new file mode 100644
index 0000000..d5547eb
--- /dev/null
+++ b/conf/samsung/maguro/bt_vendor.conf
@@ -0,0 +1,5 @@
+# UART device port where Bluetooth controller is attached
+UartPort = /dev/ttyO1
+
+# Firmware patch file location
+FwPatchFilePath = /vendor/firmware/
diff --git a/include/bt_vendor_brcm.h b/include/bt_vendor_brcm.h
new file mode 100644
index 0000000..858b71b
--- /dev/null
+++ b/include/bt_vendor_brcm.h
@@ -0,0 +1,359 @@
+/******************************************************************************
+ *
+ *  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.h
+ *
+ *  Description:   A wrapper header file of bt_vendor_lib.h
+ *
+ *                 Contains definitions specific for interfacing with Broadcom
+ *                 Bluetooth chipsets
+ *
+ ******************************************************************************/
+
+#ifndef BT_VENDOR_BRCM_H
+#define BT_VENDOR_BRCM_H
+
+#include "bt_vendor_lib.h"
+#include "vnd_buildcfg.h"
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#ifndef TRUE
+#define TRUE   (!FALSE)
+#endif
+
+#ifndef VENDOR_LIB_RUNTIME_TUNING_ENABLED
+#define VENDOR_LIB_RUNTIME_TUNING_ENABLED   FALSE
+#endif
+
+/* Run-time configuration file */
+#ifndef VENDOR_LIB_CONF_FILE
+#define VENDOR_LIB_CONF_FILE "/etc/bluetooth/bt_vendor.conf"
+#endif
+
+/* Device port name where Bluetooth controller attached */
+#ifndef BLUETOOTH_UART_DEVICE_PORT
+#define BLUETOOTH_UART_DEVICE_PORT      "/dev/ttyO1"    /* maguro */
+#endif
+
+/* Location of firmware patch files */
+#ifndef FW_PATCHFILE_LOCATION
+#define FW_PATCHFILE_LOCATION "/vendor/firmware/"  /* maguro */
+#endif
+
+#ifndef UART_TARGET_BAUD_RATE
+#define UART_TARGET_BAUD_RATE           3000000
+#endif
+
+/* The millisecond delay pauses on HCI transport after firmware patches
+ * were downloaded. This gives some time for firmware to restart with
+ * patches before host attempts to send down any HCI commands.
+ *
+ * Note: It has been discovered that BCM43241B0 needs at least 200ms
+ * settlement delay in here. Without the delay, a Hardware Error event
+ * from BCM43241B0 had been seen in HCI upstream path right after the
+ * host sent the HCI_VSC_SET_BDADDR commad to the controller at higher
+ * baud.
+ */
+#ifndef FW_PATCH_SETTLEMENT_DELAY_MS
+#define FW_PATCH_SETTLEMENT_DELAY_MS          0
+#endif
+
+/* The Bluetooth Device Aaddress source switch:
+ *
+ * -FALSE- (default value)
+ *  Get the factory BDADDR from device's file system. Normally the BDADDR is
+ *  stored in the location pointed by the PROPERTY_BT_BDADDR_PATH (defined in
+ *  btif_common.h file) property.
+ *
+ * -TRUE-
+ *  If the Bluetooth Controller has equipped with a non-volatile memory (such
+ *  as BCM4330's OTP memory), the factory BDADDR can be stored in there and
+ *  retrieved by the stack while enabling BT.
+ *  !!! WARNING !!! Make sure that the OTP feature has been enabled in the
+ *  firmware patchram (.hcd) file.
+ */
+#ifndef USE_CONTROLLER_BDADDR
+#define USE_CONTROLLER_BDADDR   FALSE
+#endif
+
+/* sleep mode
+
+    0: disable
+    1: UART with Host wake/BT wake out of band signals
+*/
+#ifndef LPM_SLEEP_MODE
+#define LPM_SLEEP_MODE                  1
+#endif
+
+/* Host Stack Idle Threshold in 300ms or 25ms 
+
+  In sleep mode 1, this is the number of firmware loops executed with no
+    activity before the Host wake line is deasserted. Activity includes HCI
+    traffic excluding certain sleep mode commands and the presence of SCO
+    connections if the "Allow Host Sleep During SCO" flag is not set to 1.
+    Each count of this parameter is roughly equivalent to 300ms or 25ms.
+*/
+#ifndef LPM_IDLE_THRESHOLD
+#define LPM_IDLE_THRESHOLD              1
+#endif
+
+/* Host Controller Idle Threshold in 300ms or 25ms
+
+    This is the number of firmware loops executed with no activity before the
+    HC is considered idle. Depending on the mode, HC may then attempt to sleep.
+    Activity includes HCI traffic excluding certain sleep mode commands and
+    the presence of ACL/SCO connections.
+*/
+#ifndef LPM_HC_IDLE_THRESHOLD
+#define LPM_HC_IDLE_THRESHOLD           1
+#endif
+
+/* BT_WAKE Polarity - 0=Active Low, 1= Active High */
+#ifndef LPM_BT_WAKE_POLARITY
+#define LPM_BT_WAKE_POLARITY            1    /* maguro */
+#endif
+
+/* HOST_WAKE Polarity - 0=Active Low, 1= Active High */
+#ifndef LPM_HOST_WAKE_POLARITY
+#define LPM_HOST_WAKE_POLARITY          1    /* maguro */
+#endif
+
+/* LPM_ALLOW_HOST_SLEEP_DURING_SCO
+
+    When this flag is set to 0, the host is not allowed to sleep while
+    an SCO is active. In sleep mode 1, the device will keep the host
+    wake line asserted while an SCO is active.
+    When this flag is set to 1, the host can sleep while an SCO is active.
+    This flag should only be set to 1 if SCO traffic is directed to the PCM
+    interface.
+*/
+#ifndef LPM_ALLOW_HOST_SLEEP_DURING_SCO
+#define LPM_ALLOW_HOST_SLEEP_DURING_SCO 1
+#endif
+
+/* LPM_COMBINE_SLEEP_MODE_AND_LPM
+
+    In Mode 0, always set byte 7 to 0. In sleep mode 1, device always
+    requires permission to sleep between scans / periodic inquiries regardless
+    of the setting of this byte. In sleep mode 1, if byte is set, device must
+    have "permission" to sleep during the low power modes of sniff, hold, and
+    park. If byte is not set, device can sleep without permission during these
+    modes. Permission to sleep in Mode 1 is obtained if the BT_WAKE signal is
+    not asserted.
+*/
+#ifndef LPM_COMBINE_SLEEP_MODE_AND_LPM
+#define LPM_COMBINE_SLEEP_MODE_AND_LPM  1
+#endif
+
+/* LPM_ENABLE_UART_TXD_TRI_STATE
+
+    When set to 0, the device will not tristate its UART TX line before going
+    to sleep.
+    When set to 1, the device will tristate its UART TX line before going to
+    sleep.
+*/
+#ifndef LPM_ENABLE_UART_TXD_TRI_STATE
+#define LPM_ENABLE_UART_TXD_TRI_STATE   0
+#endif
+
+/* LPM_PULSED_HOST_WAKE
+*/
+#ifndef LPM_PULSED_HOST_WAKE
+#define LPM_PULSED_HOST_WAKE            0
+#endif
+
+/* LPM_IDLE_TIMEOUT_MULTIPLE
+
+    The multiple factor of host stack idle threshold in 300ms/25ms
+*/
+#ifndef LPM_IDLE_TIMEOUT_MULTIPLE
+#define LPM_IDLE_TIMEOUT_MULTIPLE       10
+#endif
+
+/* BT_WAKE_VIA_USERIAL_IOCTL
+
+    Use userial ioctl function to control BT_WAKE signal
+*/
+#ifndef BT_WAKE_VIA_USERIAL_IOCTL
+#define BT_WAKE_VIA_USERIAL_IOCTL       FALSE
+#endif
+
+/* BT_WAKE_VIA_PROC
+
+    LPM & BT_WAKE control through PROC nodes
+*/
+#ifndef BT_WAKE_VIA_PROC
+#define BT_WAKE_VIA_PROC       FALSE
+#endif
+
+/* SCO_CFG_INCLUDED
+
+    Do SCO configuration by default. If the firmware patch had been embedded
+    with desired SCO configuration, set this FALSE to bypass configuration
+    from host software.
+*/
+#ifndef SCO_CFG_INCLUDED
+#define SCO_CFG_INCLUDED                TRUE
+#endif
+
+#ifndef SCO_USE_I2S_INTERFACE
+#define SCO_USE_I2S_INTERFACE           FALSE
+#endif
+
+#if (SCO_USE_I2S_INTERFACE == TRUE)
+#define SCO_I2SPCM_PARAM_SIZE           4
+
+/* SCO_I2SPCM_IF_MODE - 0=Disable, 1=Enable */
+#ifndef SCO_I2SPCM_IF_MODE
+#define SCO_I2SPCM_IF_MODE              1
+#endif
+
+/* SCO_I2SPCM_IF_ROLE - 0=Slave, 1=Master */
+#ifndef SCO_I2SPCM_IF_ROLE
+#define SCO_I2SPCM_IF_ROLE              1
+#endif
+
+/* SCO_I2SPCM_IF_SAMPLE_RATE
+
+    0 : 8K
+    1 : 16K
+    2 : 4K
+*/
+#ifndef SCO_I2SPCM_IF_SAMPLE_RATE
+#define SCO_I2SPCM_IF_SAMPLE_RATE       0
+#endif
+
+/* SCO_I2SPCM_IF_CLOCK_RATE
+
+    0 : 128K
+    1 : 256K
+    2 : 512K
+    3 : 1024K
+    4 : 2048K
+*/
+#ifndef SCO_I2SPCM_IF_CLOCK_RATE
+#define SCO_I2SPCM_IF_CLOCK_RATE        1
+#endif
+#endif // SCO_USE_I2S_INTERFACE
+
+
+#define SCO_PCM_PARAM_SIZE              5
+
+/* SCO_PCM_ROUTING
+
+    0 : PCM
+    1 : Transport
+    2 : Codec
+    3 : I2S
+*/
+#ifndef SCO_PCM_ROUTING
+#define SCO_PCM_ROUTING                 0
+#endif
+
+/* SCO_PCM_IF_CLOCK_RATE
+
+    0 : 128K
+    1 : 256K
+    2 : 512K
+    3 : 1024K
+    4 : 2048K
+*/
+#ifndef SCO_PCM_IF_CLOCK_RATE
+#define SCO_PCM_IF_CLOCK_RATE           4
+#endif
+
+/* SCO_PCM_IF_FRAME_TYPE - 0=Short, 1=Long */
+#ifndef SCO_PCM_IF_FRAME_TYPE
+#define SCO_PCM_IF_FRAME_TYPE           0
+#endif
+
+/* SCO_PCM_IF_SYNC_MODE - 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 */
+#ifndef SCO_PCM_IF_CLOCK_MODE
+#define SCO_PCM_IF_CLOCK_MODE           0
+#endif
+
+#define PCM_DATA_FORMAT_PARAM_SIZE      5
+
+/* PCM_DATA_FMT_SHIFT_MODE
+
+    0 : MSB first
+    1 : LSB first
+*/
+#ifndef PCM_DATA_FMT_SHIFT_MODE
+#define PCM_DATA_FMT_SHIFT_MODE         0
+#endif
+
+/* PCM_DATA_FMT_FILL_BITS
+
+    Specifies the value with which to fill unused bits
+    if Fill_Method is set to programmable
+*/
+#ifndef PCM_DATA_FMT_FILL_BITS
+#define PCM_DATA_FMT_FILL_BITS          0
+#endif
+
+/* PCM_DATA_FMT_FILL_METHOD
+
+    0 : 0's
+    1 : 1's
+    2 : Signed
+    3 : Programmable
+*/
+#ifndef PCM_DATA_FMT_FILL_METHOD
+#define PCM_DATA_FMT_FILL_METHOD        3
+#endif
+
+/* PCM_DATA_FMT_FILL_NUM
+
+    Specifies the number of bits to be filled
+*/
+#ifndef PCM_DATA_FMT_FILL_NUM
+#define PCM_DATA_FMT_FILL_NUM           3
+#endif
+
+/* PCM_DATA_FMT_JUSTIFY_MODE
+
+    0 : Left justify (fill data shifted out last)
+    1 : Right justify (fill data shifted out first)
+*/
+#ifndef PCM_DATA_FMT_JUSTIFY_MODE
+#define PCM_DATA_FMT_JUSTIFY_MODE       0
+#endif
+
+/******************************************************************************
+**  Extern variables and functions
+******************************************************************************/
+
+extern bt_vendor_callbacks_t *bt_vendor_cbacks;
+
+#endif /* BT_VENDOR_BRCM_H */
+
diff --git a/include/upio.h b/include/upio.h
new file mode 100644
index 0000000..aa4fadc
--- /dev/null
+++ b/include/upio.h
@@ -0,0 +1,107 @@
+/******************************************************************************
+ *
+ *  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.h
+ *
+ *  Description:   Contains definitions used for I/O controls
+ *
+ ******************************************************************************/
+
+#ifndef UPIO_H
+#define UPIO_H
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+
+#define UPIO_BT_POWER_OFF 0
+#define UPIO_BT_POWER_ON  1
+
+/* UPIO signals */
+enum {
+    UPIO_BT_WAKE = 0,
+    UPIO_HOST_WAKE,
+    UPIO_LPM_MODE,
+    UPIO_MAX_COUNT
+};
+
+/* UPIO assertion/deassertion */
+enum {
+    UPIO_UNKNOWN = 0,
+    UPIO_DEASSERT,
+    UPIO_ASSERT
+};
+
+/******************************************************************************
+**  Extern variables and functions
+******************************************************************************/
+
+/******************************************************************************
+**  Functions
+******************************************************************************/
+
+/*******************************************************************************
+**
+** Function        upio_init
+**
+** Description     Initialization
+**
+** Returns         None
+**
+*******************************************************************************/
+void upio_init(void);
+
+/*******************************************************************************
+**
+** 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);
+
+/*******************************************************************************
+**
+** Function        upio_set
+**
+** Description     Set i/o based on polarity
+**
+** Returns         None
+**
+*******************************************************************************/
+void upio_set(uint8_t pio, uint8_t action, uint8_t polarity);
+
+#endif /* UPIO_H */
+
diff --git a/include/userial_vendor.h b/include/userial_vendor.h
new file mode 100644
index 0000000..8e8b84f
--- /dev/null
+++ b/include/userial_vendor.h
@@ -0,0 +1,175 @@
+/******************************************************************************
+ *
+ *  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.h
+ *
+ *  Description:   Contains vendor-specific definitions used in serial port
+ *                 controls
+ *
+ ******************************************************************************/
+
+#ifndef USERIAL_VENDOR_H
+#define USERIAL_VENDOR_H
+
+#include "bt_vendor_brcm.h"
+#include "userial.h"
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+
+/**** baud rates ****/
+#define USERIAL_BAUD_300        0
+#define USERIAL_BAUD_600        1
+#define USERIAL_BAUD_1200       2
+#define USERIAL_BAUD_2400       3
+#define USERIAL_BAUD_9600       4
+#define USERIAL_BAUD_19200      5
+#define USERIAL_BAUD_57600      6
+#define USERIAL_BAUD_115200     7
+#define USERIAL_BAUD_230400     8
+#define USERIAL_BAUD_460800     9
+#define USERIAL_BAUD_921600     10
+#define USERIAL_BAUD_1M         11
+#define USERIAL_BAUD_1_5M       12
+#define USERIAL_BAUD_2M         13
+#define USERIAL_BAUD_3M         14
+#define USERIAL_BAUD_4M         15
+#define USERIAL_BAUD_AUTO       16
+
+/**** Data Format ****/
+/* Stop Bits */
+#define USERIAL_STOPBITS_1      1
+#define USERIAL_STOPBITS_1_5    (1<<1)
+#define USERIAL_STOPBITS_2      (1<<2)
+
+/* Parity Bits */
+#define USERIAL_PARITY_NONE     (1<<3)
+#define USERIAL_PARITY_EVEN     (1<<4)
+#define USERIAL_PARITY_ODD      (1<<5)
+
+/* Data Bits */
+#define USERIAL_DATABITS_5      (1<<6)
+#define USERIAL_DATABITS_6      (1<<7)
+#define USERIAL_DATABITS_7      (1<<8)
+#define USERIAL_DATABITS_8      (1<<9)
+
+
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+/* These are the ioctl values used for bt_wake ioctl via UART driver. you may
+ * need to redefine them on you platform!
+ * Logically they need to be unique and not colide with existing uart ioctl's.
+ */
+#ifndef USERIAL_IOCTL_BT_WAKE_ASSERT
+#define USERIAL_IOCTL_BT_WAKE_ASSERT   0x8003
+#endif
+#ifndef USERIAL_IOCTL_BT_WAKE_DEASSERT
+#define USERIAL_IOCTL_BT_WAKE_DEASSERT 0x8004
+#endif
+#ifndef USERIAL_IOCTL_BT_WAKE_GET_ST
+#define USERIAL_IOCTL_BT_WAKE_GET_ST   0x8005
+#endif
+#endif // (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+
+/******************************************************************************
+**  Type definitions
+******************************************************************************/
+
+/* Structure used to configure serial port during open */
+typedef struct
+{
+    uint16_t fmt;       /* Data format */
+    uint8_t  baud;      /* Baud rate */
+} tUSERIAL_CFG;
+
+typedef enum {
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+    USERIAL_OP_ASSERT_BT_WAKE,
+    USERIAL_OP_DEASSERT_BT_WAKE,
+    USERIAL_OP_GET_BT_WAKE_STATE,
+#endif
+    USERIAL_OP_NOP,
+} userial_vendor_ioctl_op_t;
+
+/******************************************************************************
+**  Extern variables and functions
+******************************************************************************/
+
+/******************************************************************************
+**  Functions
+******************************************************************************/
+
+/*******************************************************************************
+**
+** Function        userial_vendor_init
+**
+** Description     Initialize userial vendor-specific control block
+**
+** Returns         None
+**
+*******************************************************************************/
+void userial_vendor_init(void);
+
+/*******************************************************************************
+**
+** Function        userial_vendor_open
+**
+** Description     Open the serial port with the given configuration
+**
+** Returns         device fd
+**
+*******************************************************************************/
+int userial_vendor_open(tUSERIAL_CFG *p_cfg);
+
+/*******************************************************************************
+**
+** Function        userial_vendor_close
+**
+** Description     Conduct vendor-specific close work
+**
+** Returns         None
+**
+*******************************************************************************/
+void userial_vendor_close(void);
+
+/*******************************************************************************
+**
+** Function        userial_vendor_set_baud
+**
+** Description     Set new baud rate
+**
+** Returns         None
+**
+*******************************************************************************/
+void userial_vendor_set_baud(uint8_t userial_baud);
+
+/*******************************************************************************
+**
+** Function        userial_vendor_ioctl
+**
+** Description     ioctl inteface
+**
+** Returns         None
+**
+*******************************************************************************/
+void userial_vendor_ioctl(userial_vendor_ioctl_op_t op, void *p_data);
+
+#endif /* USERIAL_VENDOR_H */
+
diff --git a/include/vnd_crespo.txt b/include/vnd_crespo.txt
new file mode 100644
index 0000000..2ba0780
--- /dev/null
+++ b/include/vnd_crespo.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/s3c2410_serial0"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_PCM_IF_CLOCK_RATE = 0
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_crespo4g.txt b/include/vnd_crespo4g.txt
new file mode 100644
index 0000000..2ba0780
--- /dev/null
+++ b/include/vnd_crespo4g.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/s3c2410_serial0"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_PCM_IF_CLOCK_RATE = 0
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_generic.txt b/include/vnd_generic.txt
new file mode 100644
index 0000000..18964f2
--- /dev/null
+++ b/include/vnd_generic.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = TRUE
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_generic_x86.txt b/include/vnd_generic_x86.txt
new file mode 100644
index 0000000..18964f2
--- /dev/null
+++ b/include/vnd_generic_x86.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = TRUE
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_grouper.txt b/include/vnd_grouper.txt
new file mode 100755
index 0000000..3e4d71c
--- /dev/null
+++ b/include/vnd_grouper.txt
@@ -0,0 +1,10 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2"
+FW_PATCHFILE_LOCATION = "/etc/firmware/"
+BT_WAKE_VIA_PROC = TRUE
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
+SCO_PCM_IF_CLOCK_RATE = 2
+USE_CONTROLLER_BDADDR = TRUE
diff --git a/include/vnd_maguro.txt b/include/vnd_maguro.txt
new file mode 100644
index 0000000..18964f2
--- /dev/null
+++ b/include/vnd_maguro.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = TRUE
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_mako.txt b/include/vnd_mako.txt
new file mode 100644
index 0000000..18964f2
--- /dev/null
+++ b/include/vnd_mako.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = TRUE
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_manta.txt b/include/vnd_manta.txt
new file mode 100644
index 0000000..b2809d1
--- /dev/null
+++ b/include/vnd_manta.txt
@@ -0,0 +1,10 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttySAC0"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+UART_TARGET_BAUD_RATE = 921600
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = TRUE
+SCO_I2SPCM_IF_ROLE = 0
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_phantasm.txt b/include/vnd_phantasm.txt
new file mode 100644
index 0000000..18964f2
--- /dev/null
+++ b/include/vnd_phantasm.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = TRUE
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_stingray.txt b/include/vnd_stingray.txt
new file mode 100755
index 0000000..f5eb1d0
--- /dev/null
+++ b/include/vnd_stingray.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2"
+FW_PATCHFILE_LOCATION = "/etc/firmware/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
+SCO_PCM_IF_CLOCK_RATE = 2
diff --git a/include/vnd_tilapia.txt b/include/vnd_tilapia.txt
new file mode 100755
index 0000000..3e4d71c
--- /dev/null
+++ b/include/vnd_tilapia.txt
@@ -0,0 +1,10 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2"
+FW_PATCHFILE_LOCATION = "/etc/firmware/"
+BT_WAKE_VIA_PROC = TRUE
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
+SCO_PCM_IF_CLOCK_RATE = 2
+USE_CONTROLLER_BDADDR = TRUE
diff --git a/include/vnd_toro.txt b/include/vnd_toro.txt
new file mode 100644
index 0000000..43e790c
--- /dev/null
+++ b/include/vnd_toro.txt
@@ -0,0 +1,9 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+BT_WAKE_VIA_USERIAL_IOCTL = TRUE
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = TRUE
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_tuna.txt b/include/vnd_tuna.txt
new file mode 100644
index 0000000..43e790c
--- /dev/null
+++ b/include/vnd_tuna.txt
@@ -0,0 +1,9 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyO1"
+FW_PATCHFILE_LOCATION = "/vendor/firmware/"
+BT_WAKE_VIA_USERIAL_IOCTL = TRUE
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+SCO_USE_I2S_INTERFACE = TRUE
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
diff --git a/include/vnd_wingray.txt b/include/vnd_wingray.txt
new file mode 100755
index 0000000..f5eb1d0
--- /dev/null
+++ b/include/vnd_wingray.txt
@@ -0,0 +1,8 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2"
+FW_PATCHFILE_LOCATION = "/etc/firmware/"
+LPM_IDLE_TIMEOUT_MULTIPLE = 5
+BTVND_DBG = FALSE
+BTHW_DBG = TRUE
+VNDUSERIAL_DBG = FALSE
+UPIO_DBG = FALSE
+SCO_PCM_IF_CLOCK_RATE = 2
diff --git a/src/bt_vendor_brcm.c b/src/bt_vendor_brcm.c
new file mode 100644
index 0000000..9bd8922
--- /dev/null
+++ b/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/src/conf.c b/src/conf.c
new file mode 100644
index 0000000..39ac12e
--- /dev/null
+++ b/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/src/hardware.c b/src/hardware.c
new file mode 100644
index 0000000..45008ef
--- /dev/null
+++ b/src/hardware.c
@@ -0,0 +1,1233 @@
+/******************************************************************************
+ *
+ *  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_READ_LOCAL_BDADDR                   0x1009
+
+#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE        5
+#define HCI_EVT_CMD_CMPL_LOCAL_NAME_STRING      6
+#define HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY     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
+#if (USE_CONTROLLER_BDADDR == TRUE)
+    , HW_CFG_READ_BD_ADDR
+#endif
+};
+
+/* 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);
+}
+
+#if (USE_CONTROLLER_BDADDR == TRUE)
+/*******************************************************************************
+**
+** Function         hw_config_read_bdaddr
+**
+** Description      Read controller's Bluetooth Device Address
+**
+** Returns          TRUE, if valid address is sent
+**                  FALSE, otherwise
+**
+*******************************************************************************/
+static uint8_t hw_config_read_bdaddr(HC_BT_HDR *p_buf)
+{
+    uint8_t retval = FALSE;
+    uint8_t *p = (uint8_t *) (p_buf + 1);
+
+    UINT16_TO_STREAM(p, HCI_READ_LOCAL_BDADDR);
+    *p = 0; /* parameter length */
+
+    p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+    hw_cfg_cb.state = HW_CFG_READ_BD_ADDR;
+
+    retval = bt_vendor_cbacks->xmit_cb(HCI_READ_LOCAL_BDADDR, p_buf, \
+                                 hw_config_cback);
+
+    return (retval);
+}
+#endif // (USE_CONTROLLER_BDADDR == TRUE)
+
+/*******************************************************************************
+**
+** 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;
+#if (USE_CONTROLLER_BDADDR == TRUE)
+    const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
+#endif
+
+    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 (USE_CONTROLLER_BDADDR == TRUE)
+                if ((is_proceeding = hw_config_read_bdaddr(p_buf)) == TRUE)
+                    break;
+#else
+                if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
+                    break;
+#endif
+                /* 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;
+
+#if (USE_CONTROLLER_BDADDR == TRUE)
+            case HW_CFG_READ_BD_ADDR:
+                p_tmp = (char *) (p_evt_buf + 1) + \
+                         HCI_EVT_CMD_CMPL_LOCAL_BDADDR_ARRAY;
+
+                if (memcmp(p_tmp, null_bdaddr, BD_ADDR_LEN) == 0)
+                {
+                    // Controller does not have a valid OTP BDADDR!
+                    // Set the BTIF initial BDADDR instead.
+                    if ((is_proceeding = hw_config_set_bdaddr(p_buf)) == TRUE)
+                        break;
+                }
+                else
+                {
+                    ALOGI("Controller OTP bdaddr %02X:%02X:%02X:%02X:%02X:%02X",
+                        *(p_tmp+5), *(p_tmp+4), *(p_tmp+3),
+                        *(p_tmp+2), *(p_tmp+1), *p_tmp);
+                }
+
+                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;
+#endif // (USE_CONTROLLER_BDADDR == TRUE)
+        } // 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);
+            upio_set(UPIO_LPM_MODE, UPIO_ASSERT, 0);
+        }
+        else
+        {
+            memset(p, 0, LPM_CMD_PARAM_SIZE);
+            upio_set(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
+        }
+
+        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/src/upio.c b/src/upio.c
new file mode 100644
index 0000000..2de171c
--- /dev/null
+++ b/src/upio.c
@@ -0,0 +1,487 @@
+/******************************************************************************
+ *
+ *  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
+******************************************************************************/
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+
+/* proc fs node for enable/disable lpm mode */
+#ifndef VENDOR_LPM_PROC_NODE
+#define VENDOR_LPM_PROC_NODE "/proc/bluetooth/sleep/lpm"
+#endif
+
+/* proc fs node for notifying write request */
+#ifndef VENDOR_BTWRITE_PROC_NODE
+#define VENDOR_BTWRITE_PROC_NODE "/proc/bluetooth/sleep/btwrite"
+#endif
+
+/*
+ * Maximum btwrite assertion holding time without consecutive btwrite kicking.
+ * This value is correlative(shorter) to the in-activity timeout period set in
+ * the bluesleep LPM code. The current value used in bluesleep is 10sec.
+ */
+#ifndef PROC_BTWRITE_TIMER_TIMEOUT_MS
+#define PROC_BTWRITE_TIMER_TIMEOUT_MS   8000
+#endif
+
+/* lpm proc control block */
+typedef struct
+{
+    uint8_t btwrite_active;
+    uint8_t timer_created;
+    timer_t timer_id;
+    uint32_t timeout_ms;
+} vnd_lpm_proc_cb_t;
+
+static vnd_lpm_proc_cb_t lpm_proc_cb;
+#endif
+
+/******************************************************************************
+**  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_mode[] = {
+    "UNKNOWN",
+    "disabled",
+    "enabled"
+};
+
+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
+*****************************************************************************/
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+/*******************************************************************************
+**
+** Function        proc_btwrite_timeout
+**
+** Description     Timeout thread of proc/.../btwrite assertion holding timer
+**
+** Returns         None
+**
+*******************************************************************************/
+static void proc_btwrite_timeout(union sigval arg)
+{
+    UPIODBG("..%s..", __FUNCTION__);
+    lpm_proc_cb.btwrite_active = FALSE;
+}
+#endif
+
+/*****************************************************************************
+**   UPIO Interface Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function        upio_init
+**
+** Description     Initialization
+**
+** Returns         None
+**
+*******************************************************************************/
+void upio_init(void)
+{
+    memset(upio_state, UPIO_UNKNOWN, UPIO_MAX_COUNT);
+#if (BT_WAKE_VIA_PROC == TRUE)
+    memset(&lpm_proc_cb, 0, sizeof(vnd_lpm_proc_cb_t));
+#endif
+}
+
+/*******************************************************************************
+**
+** Function        upio_cleanup
+**
+** Description     Clean up
+**
+** Returns         None
+**
+*******************************************************************************/
+void upio_cleanup(void)
+{
+#if (BT_WAKE_VIA_PROC == TRUE)
+    if (lpm_proc_cb.timer_created == TRUE)
+        timer_delete(lpm_proc_cb.timer_id);
+
+    lpm_proc_cb.timer_created = FALSE;
+#endif
+}
+
+/*******************************************************************************
+**
+** 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;
+#if (BT_WAKE_VIA_PROC == TRUE)
+    int fd = -1;
+    char buffer;
+#endif
+
+    switch (pio)
+    {
+        case UPIO_LPM_MODE:
+            if (upio_state[UPIO_LPM_MODE] == action)
+            {
+                UPIODBG("LPM is %s already", lpm_mode[action]);
+                return;
+            }
+
+            upio_state[UPIO_LPM_MODE] = action;
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+            fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY);
+
+            if (fd < 0)
+            {
+                ALOGE("upio_set : open(%s) for write failed: %s (%d)",
+                        VENDOR_LPM_PROC_NODE, strerror(errno), errno);
+                return;
+            }
+
+            if (action == UPIO_ASSERT)
+            {
+                buffer = '1';
+            }
+            else
+            {
+                buffer = '0';
+
+                // delete btwrite assertion holding timer
+                if (lpm_proc_cb.timer_created == TRUE)
+                {
+                    timer_delete(lpm_proc_cb.timer_id);
+                    lpm_proc_cb.timer_created = FALSE;
+                }
+            }
+
+            if (write(fd, &buffer, 1) < 0)
+            {
+                ALOGE("upio_set : write(%s) failed: %s (%d)",
+                        VENDOR_LPM_PROC_NODE, strerror(errno),errno);
+            }
+            else
+            {
+                if (action == UPIO_ASSERT)
+                {
+                    // create btwrite assertion holding timer
+                    if (lpm_proc_cb.timer_created == FALSE)
+                    {
+                        int status;
+                        struct sigevent se;
+
+                        se.sigev_notify = SIGEV_THREAD;
+                        se.sigev_value.sival_ptr = &lpm_proc_cb.timer_id;
+                        se.sigev_notify_function = proc_btwrite_timeout;
+                        se.sigev_notify_attributes = NULL;
+
+                        status = timer_create(CLOCK_MONOTONIC, &se,
+                                                &lpm_proc_cb.timer_id);
+
+                        if (status == 0)
+                            lpm_proc_cb.timer_created = TRUE;
+                    }
+                }
+            }
+
+            if (fd >= 0)
+                close(fd);
+#endif
+            break;
+
+        case UPIO_BT_WAKE:
+            if (upio_state[UPIO_BT_WAKE] == action)
+            {
+                UPIODBG("BT_WAKE is %s already", lpm_state[action]);
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+                if (lpm_proc_cb.btwrite_active == TRUE)
+                    /*
+                     * The proc btwrite node could have not been updated for
+                     * certain time already due to heavy downstream path flow.
+                     * In this case, we want to explicity touch proc btwrite
+                     * node to keep the bt_wake assertion in the LPM kernel
+                     * driver. The current kernel bluesleep LPM code starts
+                     * a 10sec internal in-activity timeout timer before it
+                     * attempts to deassert BT_WAKE line.
+                     */
+#endif
+                return;
+            }
+
+            upio_state[UPIO_BT_WAKE] = action;
+
+#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE)
+
+            userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \
+                      USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\
+                      NULL);
+
+#elif (BT_WAKE_VIA_PROC == TRUE)
+
+            /*
+             *  Kick proc btwrite node only at UPIO_ASSERT
+             */
+            if (action == UPIO_DEASSERT)
+                return;
+
+            fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY);
+
+            if (fd < 0)
+            {
+                ALOGE("upio_set : open(%s) for write failed: %s (%d)",
+                        VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno);
+                return;
+            }
+
+            buffer = '1';
+
+            if (write(fd, &buffer, 1) < 0)
+            {
+                ALOGE("upio_set : write(%s) failed: %s (%d)",
+                        VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno);
+            }
+            else
+            {
+                lpm_proc_cb.btwrite_active = TRUE;
+
+                if (lpm_proc_cb.timer_created == TRUE)
+                {
+                    struct itimerspec ts;
+
+                    ts.it_value.tv_sec = PROC_BTWRITE_TIMER_TIMEOUT_MS/1000;
+                    ts.it_value.tv_nsec = 1000*(PROC_BTWRITE_TIMER_TIMEOUT_MS%1000);
+                    ts.it_interval.tv_sec = 0;
+                    ts.it_interval.tv_nsec = 0;
+
+                    timer_settime(lpm_proc_cb.timer_id, 0, &ts, 0);
+                }
+            }
+
+            UPIODBG("proc btwrite assertion");
+
+            if (fd >= 0)
+                close(fd);
+#endif
+
+            break;
+
+        case UPIO_HOST_WAKE:
+            UPIODBG("upio_set: UPIO_HOST_WAKE");
+            break;
+    }
+}
+
+
diff --git a/src/userial_vendor.c b/src/userial_vendor.c
new file mode 100755
index 0000000..1a745b5
--- /dev/null
+++ b/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;
+}
+
diff --git a/vnd_buildcfg.mk b/vnd_buildcfg.mk
new file mode 100644
index 0000000..b65033a
--- /dev/null
+++ b/vnd_buildcfg.mk
@@ -0,0 +1,16 @@
+intermediates := $(local-intermediates-dir)
+
+SRC := $(call my-dir)/include/$(addprefix vnd_, $(addsuffix .txt,$(basename $(TARGET_DEVICE))))
+ifeq (,$(wildcard $(SRC)))
+# configuration file does not exist. Use default one
+SRC := $(call my-dir)/include/vnd_generic.txt
+endif
+GEN := $(intermediates)/vnd_buildcfg.h
+TOOL := $(TOP_DIR)external/bluetooth/bluedroid/tools/gen-buildcfg.sh
+
+$(GEN): PRIVATE_PATH := $(call my-dir)
+$(GEN): PRIVATE_CUSTOM_TOOL = $(TOOL) $< $@
+$(GEN): $(SRC)  $(TOOL)
+	$(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $(GEN)