Stop wcnss_filter if start timesout waiting for cb
am: 28d8d2c448

Change-Id: I6cbb879b49df62eba6981ae5a9f6e68ada7ba0e1
diff --git a/Android.mk b/Android.mk
index c2d1878..5c7c040 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,23 +1,11 @@
+LOCAL_PATH := $(call my-dir)
 # TODO:  Find a better way to separate build configs for ADP vs non-ADP devices
 ifneq ($(BOARD_IS_AUTOMOTIVE),true)
-  ifneq ($(filter msm8960 msm8x27 msm8226,$(TARGET_BOARD_PLATFORM)),)
+  ifneq ($(filter msm8x27 msm8226,$(TARGET_BOARD_PLATFORM)),)
     include $(call all-named-subdir-makefiles,msm8960)
-  else
-    ifneq ($(filter msm8994 msm8992,$(TARGET_BOARD_PLATFORM)),)
-      include $(call all-named-subdir-makefiles,msm8992)
-    else
-      ifneq ($(filter msm8996,$(TARGET_BOARD_PLATFORM)),)
-        include $(call all-named-subdir-makefiles,msm8996)
-      else
-        ifneq ($(filter msm8909 ,$(TARGET_BOARD_PLATFORM)),)
-          #For msm8909 target
-          include $(call all-named-subdir-makefiles,msm8909)
-        else
-          ifneq ($(filter msm8998,$(TARGET_BOARD_PLATFORM)),)
-            include $(call all-named-subdir-makefiles,msm8998)
-          endif
-        endif
-      endif
-    endif
+  else ifneq ($(filter msm8994,$(TARGET_BOARD_PLATFORM)),)
+    include $(call all-named-subdir-makefiles,msm8992)
+  else ifneq ($(wildcard $(LOCAL_PATH)/$(TARGET_BOARD_PLATFORM)),)
+    include $(call all-named-subdir-makefiles,$(TARGET_BOARD_PLATFORM))
   endif
 endif
diff --git a/msm8998/libbt-vendor/Android.mk b/msm8998/libbt-vendor/Android.mk
index f75ad1a..91d098e 100644
--- a/msm8998/libbt-vendor/Android.mk
+++ b/msm8998/libbt-vendor/Android.mk
@@ -66,6 +66,9 @@
         libcutils \
         liblog
 
+LOCAL_HEADER_LIBRARIES := \
+        libutils_headers
+
 LOCAL_MODULE := libbt-vendor
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
diff --git a/msm8998/libbt-vendor/include/hci_uart.h b/msm8998/libbt-vendor/include/hci_uart.h
index 21e9689..50740d7 100644
--- a/msm8998/libbt-vendor/include/hci_uart.h
+++ b/msm8998/libbt-vendor/include/hci_uart.h
@@ -20,6 +20,7 @@
 #define HCI_UART_H
 
 #include <asm-generic/ioctls.h>
+#include <termios.h>
 
 /* Variables to identify the platform */
 /*BT HS UART TTY DEVICE */
diff --git a/msm8998/libbt-vendor/include/hw_ar3k.h b/msm8998/libbt-vendor/include/hw_ar3k.h
index 2129548..1b22f4f 100644
--- a/msm8998/libbt-vendor/include/hw_ar3k.h
+++ b/msm8998/libbt-vendor/include/hw_ar3k.h
@@ -18,6 +18,8 @@
 #ifndef HW_AR3K_H
 #define HW_AR3K_H
 
+#include <sys/socket.h>
+
 /******************************************************************************
 **  Constants & Macros
 ******************************************************************************/
diff --git a/msm8998/libbt-vendor/src/bt_vendor_qcom.c b/msm8998/libbt-vendor/src/bt_vendor_qcom.c
index a1f88fe..432534a 100644
--- a/msm8998/libbt-vendor/src/bt_vendor_qcom.c
+++ b/msm8998/libbt-vendor/src/bt_vendor_qcom.c
@@ -26,20 +26,24 @@
 #define LOG_TAG "bt_vendor"
 #define BLUETOOTH_MAC_ADDR_BOOT_PROPERTY "ro.boot.btmacaddr"
 
-#include <utils/Log.h>
-#include <cutils/properties.h>
-#include <fcntl.h>
-#include <termios.h>
+#include "bt_vendor_lib.h"
+#include "bt_vendor_persist.h"
 #include "bt_vendor_qcom.h"
-#include "hci_uart.h"
 #include "hci_smd.h"
+#include "hci_uart.h"
+#include "hw_rome.h"
+
+#include <fcntl.h>
+#include <linux/un.h>
+#include <pthread.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
 #include <cutils/sockets.h>
-#include <linux/un.h>
-#include "bt_vendor_persist.h"
-#include "hw_rome.h"
-#include "bt_vendor_lib.h"
+#include <utils/Log.h>
 #define WAIT_TIMEOUT 200000
 #define BT_VND_OP_GET_LINESPEED 30
 
@@ -604,7 +608,7 @@
 
     q.rfkill_id = -1;
     q.enable_extldo = FALSE;
-    q.cb = cb;
+    q.cb = (bt_vendor_callbacks_t*)cb;
     q.ant_fd = -1;
     q.soc_type = get_bt_soc_type();
     soc_init(q.soc_type);
diff --git a/msm8998/libbt-vendor/src/hardware.c b/msm8998/libbt-vendor/src/hardware.c
index 6984ff0..cd6790b 100644
--- a/msm8998/libbt-vendor/src/hardware.c
+++ b/msm8998/libbt-vendor/src/hardware.c
@@ -26,20 +26,22 @@
 
 #define LOG_TAG "bt_vendor"
 
-#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_qcom.h"
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <utils/Log.h>
 #define MAX_CNT_RETRY 100
 
 int hw_config(int nState)
diff --git a/msm8998/libbt-vendor/src/hci_smd.c b/msm8998/libbt-vendor/src/hci_smd.c
index 7e5b16d..9833281 100644
--- a/msm8998/libbt-vendor/src/hci_smd.c
+++ b/msm8998/libbt-vendor/src/hci_smd.c
@@ -24,15 +24,18 @@
 
 #define LOG_TAG "bt_vendor"
 
-#include <utils/Log.h>
-#include <termios.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
 #include "bt_vendor_qcom.h"
 #include "hci_smd.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
 #include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
 #include <cutils/properties.h>
+#include <utils/Log.h>
 
 /*****************************************************************************
 **   Macros & Constants
diff --git a/msm8998/libbt-vendor/src/hci_uart.c b/msm8998/libbt-vendor/src/hci_uart.c
index 2aeace8..fa0fc0f 100644
--- a/msm8998/libbt-vendor/src/hci_uart.c
+++ b/msm8998/libbt-vendor/src/hci_uart.c
@@ -26,14 +26,18 @@
 
 #define LOG_TAG "bt_vendor"
 
-#include <utils/Log.h>
-#include <termios.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
 #include "bt_vendor_qcom.h"
 #include "hci_uart.h"
+
+#include <asm-generic/ioctls.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
 #include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <utils/Log.h>
 
 /******************************************************************************
 **  Constants & Macros
diff --git a/msm8998/libbt-vendor/src/hw_ar3k.c b/msm8998/libbt-vendor/src/hw_ar3k.c
index 1a68aab..b484d0b 100644
--- a/msm8998/libbt-vendor/src/hw_ar3k.c
+++ b/msm8998/libbt-vendor/src/hw_ar3k.c
@@ -34,26 +34,29 @@
 
 #define LOG_TAG "bt_vendor"
 
-#include <sys/socket.h>
-#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 <termios.h>
-#include <string.h>
-
 #include "bt_hci_bdroid.h"
 #include "bt_vendor_qcom.h"
+#include "bt_vendor_qcom.h"
 #include "hci_uart.h"
 #include "hw_ar3k.h"
-#include "bt_vendor_qcom.h"
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <utils/Log.h>
 
 /******************************************************************************
 **  Variables
diff --git a/msm8998/libbt-vendor/src/hw_rome.c b/msm8998/libbt-vendor/src/hw_rome.c
index 58c0159..cf34006 100644
--- a/msm8998/libbt-vendor/src/hw_rome.c
+++ b/msm8998/libbt-vendor/src/hw_rome.c
@@ -34,26 +34,29 @@
 
 #define LOG_TAG "bt_vendor"
 
-#include <sys/socket.h>
-#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 <termios.h>
-#include <string.h>
-#include <stdbool.h>
 #include "bt_hci_bdroid.h"
 #include "bt_vendor_qcom.h"
 #include "hci_uart.h"
 #include "hw_rome.h"
 
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <utils/Log.h>
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/sdm845/Android.mk b/sdm845/Android.mk
new file mode 100644
index 0000000..cd2c3ae
--- /dev/null
+++ b/sdm845/Android.mk
@@ -0,0 +1,3 @@
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+include $(call all-named-subdir-makefiles,libbt-vendor)
+endif # is-vendor-board-platform
diff --git a/sdm845/CleanSpec.mk b/sdm845/CleanSpec.mk
new file mode 100755
index 0000000..8ab6f23
--- /dev/null
+++ b/sdm845/CleanSpec.mk
@@ -0,0 +1,54 @@
+# Copyright (C) 2007 The Android Open Source Project
+#
+# 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libbt-vendor_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/NOTICE_FILES/src/system/vendor/lib/libbt-vendor.so.txt)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/lib/libbt-vendor.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/system/vendor/lib/libbt-vendor.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/vendor/lib/libbt-vendor.so)
diff --git a/sdm845/libbt-vendor/Android.mk b/sdm845/libbt-vendor/Android.mk
new file mode 100644
index 0000000..8d3f9d4
--- /dev/null
+++ b/sdm845/libbt-vendor/Android.mk
@@ -0,0 +1,88 @@
+#
+# Copyright 2012 The Android Open Source Project
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(BOARD_HAVE_BLUETOOTH_QCOM),true)
+
+include $(CLEAR_VARS)
+
+
+LOCAL_SRC_FILES := \
+        src/bt_vendor_qcom.c \
+        src/hardware.c \
+        src/hci_uart.c \
+        src/hci_smd.c \
+        src/hw_rome.c \
+        src/hw_ar3k.c \
+        src/bt_vendor_persist.cpp
+
+#Disable this flag in case if FM over UART support not needed
+LOCAL_CFLAGS := -DFM_OVER_UART
+
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+LOCAL_CFLAGS += -DPANIC_ON_SOC_CRASH
+LOCAL_CFLAGS += -DENABLE_DBG_FLAGS
+endif
+
+LOCAL_C_INCLUDES += \
+        $(LOCAL_PATH)/include \
+        external/bluetooth/bluedroid/hci/include \
+        system/bt/hci/include \
+        $(TARGET_OUT_HEADERS)/bt/hci_qcomm_init \
+        $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+
+LOCAL_ADDITIONAL_DEPENDENCIES += \
+$(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+ifeq ($(BOARD_HAS_QCA_BT_AR3002), true)
+LOCAL_C_FLAGS := \
+        -DBT_WAKE_VIA_PROC
+endif #BOARD_HAS_QCA_BT_AR3002
+
+ifeq ($(WIFI_BT_STATUS_SYNC), true)
+LOCAL_CFLAGS += -DWIFI_BT_STATUS_SYNC
+endif #WIFI_BT_STATUS_SYNC
+
+LOCAL_SHARED_LIBRARIES := \
+        libcutils \
+        liblog \
+        libbtnv
+
+LOCAL_MODULE := libbt-vendor
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_OWNER := qcom
+
+ifdef TARGET_2ND_ARCH
+LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib
+LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64
+else
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)
+endif
+
+LOCAL_CFLAGS += -DBT_NV_SUPPORT
+
+ifneq ($(BOARD_ANT_WIRELESS_DEVICE),)
+LOCAL_CFLAGS += -DENABLE_ANT
+endif
+#LOCAL_CFLAGS += -DREAD_BT_ADDR_FROM_PROP
+
+#include $(LOCAL_PATH)/vnd_buildcfg.mk
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # BOARD_HAVE_BLUETOOTH_QCOM
diff --git a/sdm845/libbt-vendor/NOTICE b/sdm845/libbt-vendor/NOTICE
new file mode 100644
index 0000000..33ff961
--- /dev/null
+++ b/sdm845/libbt-vendor/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2012, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/sdm845/libbt-vendor/include/bt_vendor_persist.h b/sdm845/libbt-vendor/include/bt_vendor_persist.h
new file mode 100644
index 0000000..4f2e8ee
--- /dev/null
+++ b/sdm845/libbt-vendor/include/bt_vendor_persist.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BT_VENDOR_PERSIST_H_
+#define BT_VENDOR_PERSIST_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdio.h>
+
+#ifdef BT_NV_SUPPORT
+
+#endif /* BT_NV_SUPPORT */
+typedef unsigned char boolean;
+/*===========================================================================
+FUNCTION   bt_vendor_nv_read
+
+DESCRIPTION
+ Helper Routine to process the nv read command
+
+DEPENDENCIES
+  NIL
+
+RETURN VALUE
+  RETURN VALUE
+  FALSE = failure, else TRUE
+
+SIDE EFFECTS
+  None
+
+===========================================================================*/
+extern uint8_t bt_vendor_nv_read
+(
+  uint8_t nv_item,
+  uint8_t * rsp_buf
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BT_VENDOR_PERSIST_H_ */
+
diff --git a/sdm845/libbt-vendor/include/bt_vendor_qcom.h b/sdm845/libbt-vendor/include/bt_vendor_qcom.h
new file mode 100644
index 0000000..8565b6c
--- /dev/null
+++ b/sdm845/libbt-vendor/include/bt_vendor_qcom.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef BT_VENDOR_QCOM_H
+#define BT_VENDOR_QCOM_H
+
+#include <stdbool.h>
+#include "bt_vendor_lib.h"
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#ifndef TRUE
+#define TRUE   (!FALSE)
+#endif
+
+#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);}
+
+typedef enum {
+    BT_SOC_DEFAULT = 0,
+    BT_SOC_SMD = BT_SOC_DEFAULT,
+    BT_SOC_AR3K,
+    BT_SOC_ROME,
+    BT_SOC_CHEROKEE,
+    /* Add chipset type here */
+    BT_SOC_RESERVED
+}bt_soc_type;
+
+typedef enum {
+    FM_VND_OP_POWER_CTRL = (unsigned int)BT_VND_OP_A2DP_OFFLOAD_STOP + 1,
+    BT_VND_OP_FM_USERIAL_OPEN,
+    BT_VND_OP_FM_USERIAL_CLOSE,
+}bt_fm_serial;
+
+typedef enum {
+    BT_VND_OP_ANT_USERIAL_OPEN = 254,
+    BT_VND_OP_ANT_USERIAL_CLOSE
+}ant_serial;
+
+/* HW_NEED_END_WITH_HCI_RESET
+
+    code implementation of sending a HCI_RESET command during the epilog
+    process. It calls back to the callers after command complete of HCI_RESET
+    is received.
+
+    Default TRUE .
+*/
+#ifndef HW_NEED_END_WITH_HCI_RESET
+#define HW_NEED_END_WITH_HCI_RESET TRUE
+#endif
+
+#define HCI_RESET  0x0C03
+#define HCI_CMD_PREAMBLE_SIZE 3
+#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE   5
+#define HCI_EVT_CMD_CMPL_OPCODE        3
+#define BT_PWR_CNTRL_DEVICE    "/dev/btpower"
+
+enum {
+    BT_STATUS_SUCCESS = 0,
+    BT_STATUS_FAIL,
+    BT_STATUS_INVAL,
+    BT_STATUS_NOMEM,
+    BT_STATUS_PROP_FAILURE,
+};
+#define BT_CMD_PWR_CTRL         0xbfad
+struct bt_qcom_struct {
+    int fd[2];
+    int ant_fd;
+    int fm_fd;
+    bt_vendor_callbacks_t *cb;
+    uint8_t bdaddr[6];
+    int soc_type;
+    int rfkill_id;
+    char *rfkill_state;
+    bool enable_extldo;
+};
+extern struct bt_qcom_struct *q;
+extern pthread_mutex_t q_lock;
+
+#endif /* BT_VENDOR_QCOM_H */
+
diff --git a/sdm845/libbt-vendor/include/hci_smd.h b/sdm845/libbt-vendor/include/hci_smd.h
new file mode 100644
index 0000000..055b779
--- /dev/null
+++ b/sdm845/libbt-vendor/include/hci_smd.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ *  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:      hci_smd.h
+ *
+ *  Description:   Contains vendor-specific definitions used in smd controls
+ *
+ ******************************************************************************/
+
+#ifndef HCI_SMD_H
+#define HCI_SMD_H
+
+#define APPS_RIVA_BT_ACL_CH  "/dev/smd2"
+#define APPS_RIVA_BT_CMD_CH  "/dev/smd3"
+
+int bt_hci_init_transport ( int *pFd );
+
+int bt_hci_deinit_transport(int *pFd);
+
+#endif /* HCI_SMD_H */
diff --git a/sdm845/libbt-vendor/include/hci_uart.h b/sdm845/libbt-vendor/include/hci_uart.h
new file mode 100644
index 0000000..21e9689
--- /dev/null
+++ b/sdm845/libbt-vendor/include/hci_uart.h
@@ -0,0 +1,263 @@
+/*
+ *  Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  Not a Contribution.
+ *  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.
+ */
+
+#ifndef HCI_UART_H
+#define HCI_UART_H
+
+#include <asm-generic/ioctls.h>
+
+/* Variables to identify the platform */
+/*BT HS UART TTY DEVICE */
+#define BT_HS_UART_DEVICE "/dev/ttyHS0"
+
+/**** 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)
+
+/* HCI Packet types */
+#define HCI_COMMAND_PKT     0x01
+#define HCI_ACLDATA_PKT      0x02
+#define HCI_SCODATA_PKT     0x03
+#define HCI_EVENT_PKT           0x04
+#define HCI_VENDOR_PKT        0xff
+
+/* HCI Command/Event Opcode */
+#define HCI_RESET                       0x0C03
+#define EVT_CMD_COMPLETE       0x0E
+
+/* Command opcode pack/unpack */
+#define cmd_opcode_pack(ogf, ocf)   (uint16_t)((ocf & 0x03ff)|(ogf << 10))
+
+#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)
+
+/* UART CLOCK IOCTLS*/
+/* UART CLOCK IOCTLS*/
+#define USERIAL_OP_CLK_ON    TIOCPMGET    /* PM get */
+#define USERIAL_OP_CLK_OFF    TIOCPMPUT   /* PM put */
+#define USERIAL_OP_CLK_STATE    TIOCPMACT    /* PM is active */
+
+/******************************************************************************
+**  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_FLOW_ON,
+    USERIAL_OP_FLOW_OFF,
+    USERIAL_OP_NOP,
+} userial_vendor_ioctl_op_t;
+
+/* 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
+};
+
+#define VND_PORT_NAME_MAXLEN    256
+
+/* 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;
+
+typedef struct {
+    uint8_t     ncmd;
+    uint16_t    opcode;
+} __attribute__ ((packed)) evt_cmd_complete;
+
+typedef struct {
+    uint8_t     status;
+    uint8_t     ncmd;
+    uint16_t    opcode;
+} __attribute__ ((packed)) evt_cmd_status;
+
+typedef struct {
+    uint16_t    opcode;
+    uint8_t     plen;
+} __attribute__ ((packed))  hci_command_hdr;
+
+typedef struct {
+    uint8_t     evt;
+    uint8_t     plen;
+} __attribute__ ((packed))  hci_event_hdr;
+
+/******************************************************************************
+**  Extern
+******************************************************************************/
+extern vnd_userial_cb_t vnd_userial;
+
+
+/*******************************************************************************
+**
+** 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         int error
+**
+*******************************************************************************/
+int userial_vendor_ioctl(userial_vendor_ioctl_op_t op, int *p_data);
+
+/*******************************************************************************
+**
+** 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);
+
+/*******************************************************************************
+**
+** Function        userial_to_baud_tcio
+**
+** Description     helper function converts TCIO baud rate into integer
+**
+** Returns         uint32_t
+**
+*******************************************************************************/
+int userial_tcio_baud_to_int(uint32_t baud);
+
+/*******************************************************************************
+**
+** Function        read_hci_event
+**
+** Description     Read HCI event during vendor initialization
+**
+** Returns         int: size to read
+**
+*******************************************************************************/
+int read_hci_event(int fd, unsigned char* buf, int size);
+
+#endif /* HCI_UART_H */
diff --git a/sdm845/libbt-vendor/include/hw_ar3k.h b/sdm845/libbt-vendor/include/hw_ar3k.h
new file mode 100644
index 0000000..2129548
--- /dev/null
+++ b/sdm845/libbt-vendor/include/hw_ar3k.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ *  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.
+ */
+#ifndef HW_AR3K_H
+#define HW_AR3K_H
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+#define MAX_CNT_RETRY 100
+
+#define HCI_MAX_CMD_SIZE   260
+#define HCI_MAX_EVENT_SIZE  260
+#define HCI_CHG_BAUD_CMD_OCF 0x0C
+#define HCI_VENDOR_CMD_OGF 0x3F
+#define WRITE_BDADDR_CMD_LEN 14
+#define WRITE_BAUD_CMD_LEN   6
+#define MAX_CMD_LEN WRITE_BDADDR_CMD_LEN
+#define GET_VERSION_OCF 0x1E
+/* Byte order conversions */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define htobs(d)  (d)
+#define htobl(d)  (d)
+#define btohs(d)  (d)
+#define btohl(d)  (d)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define htobs(d)  bswap_16(d)
+#define htobl(d)  bswap_32(d)
+#define btohs(d)  bswap_16(d)
+#define btohl(d)  bswap_32(d)
+#else
+#error "Unknown byte order"
+#endif
+
+#define FW_PATH "/system/etc/firmware/ar3k/"
+
+#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);}
+
+#define MAX_TAGS              50
+#define PS_HDR_LEN            4
+#define HCI_VENDOR_CMD_OGF    0x3F
+#define HCI_PS_CMD_OCF        0x0B
+
+#define VERIFY_CRC   9
+#define PS_REGION    1
+#define PATCH_REGION 2
+#define BDADDR_FILE "ar3kbdaddr.pst"
+
+
+#define MAX_PATCH_CMD 244
+struct patch_entry {
+    int16_t len;
+    uint8_t data[MAX_PATCH_CMD];
+};
+#define HCI_UART_RAW_DEVICE    0
+#define HCI_COMMAND_HDR_SIZE 3
+#define PS_WRITE           1
+#define PS_RESET           2
+#define WRITE_PATCH        8
+#define ENABLE_PATCH       11
+
+#define HCI_PS_CMD_HDR_LEN 7
+#define HCI_CMD_MAX_LEN             258
+#define PS_RESET_PARAM_LEN 6
+#define PS_RESET_CMD_LEN   (HCI_PS_CMD_HDR_LEN + PS_RESET_PARAM_LEN)
+
+#define PS_ID_MASK         0xFF
+
+
+#define LOCAL_NAME_BUFFER_LEN                   32
+#define DEV_REGISTER      0x4FFC
+#define GET_DEV_TYPE_OCF  0x05
+
+#define HCIDEVUP            _IOW('H', 201, int)
+#define OGF_VENDOR_CMD                  0x3f
+#define EVT_CMD_COMPLETE_SIZE     3
+#define EVT_CMD_STATUS                   0x0F
+#define EVT_CMD_STATUS_SIZE         4
+#define HCI_COMMAND_HDR_SIZE      3
+#define HCI_EVENT_HDR_SIZE            2
+#define HCI_EV_SUCCESS                    0x00
+/* HCI Socket options */
+#define HCI_DATA_DIR        1
+#define HCI_FILTER              2
+#define HCI_TIME_STAMP    3
+
+/* HCI CMSG flags */
+#define HCI_CMSG_DIR            0x0001
+#define HCI_CMSG_TSTAMP     0x0002
+
+#ifndef VENDOR_LPM_PROC_NODE
+#define VENDOR_LPM_PROC_NODE "/sys/module/hci_uart/parameters/ath_lpm"
+#endif
+
+/* proc fs node for notifying write request */
+#ifndef VENDOR_BTWRITE_PROC_NODE
+#define VENDOR_BTWRITE_PROC_NODE "/sys/module/hci_uart/parameters/ath_btwrite"
+#endif
+
+/******************************************************************************
+**  Local type definitions
+******************************************************************************/
+typedef struct {
+    uint8_t b[6];
+} __attribute__((packed)) bdaddr_t;
+
+struct sockaddr_hci {
+    sa_family_t hci_family;
+    unsigned short  hci_dev;
+    unsigned short  hci_channel;
+};
+
+struct tag_info {
+    unsigned section;
+    unsigned line_count;
+    unsigned char_cnt;
+    unsigned byte_count;
+};
+
+struct ps_cfg_entry {
+    uint32_t id;
+    uint32_t len;
+    uint8_t *data;
+};
+
+struct ps_entry_type {
+    unsigned char type;
+    unsigned char array;
+};
+
+struct uart_t {
+    char *type;
+    int  m_id;
+    int  p_id;
+    int  proto;
+    int  init_speed;
+    int  speed;
+    int  flags;
+    int  pm;
+    char *bdaddr;
+    int  (*init) (int fd, struct uart_t *u, struct termios *ti);
+    int  (*post) (int fd, struct uart_t *u, struct termios *ti);
+};
+#endif /* HW_AR3K_H */
diff --git a/sdm845/libbt-vendor/include/hw_rome.h b/sdm845/libbt-vendor/include/hw_rome.h
new file mode 100644
index 0000000..08efb39
--- /dev/null
+++ b/sdm845/libbt-vendor/include/hw_rome.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ *  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.
+ */
+#ifndef HW_ROME_H
+#define HW_ROME_H
+
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+#define HCI_MAX_CMD_SIZE        260
+#define HCI_MAX_EVENT_SIZE     260
+#define PRINT_BUF_SIZE              ((HCI_MAX_CMD_SIZE * 3) + 2)
+
+#define HCI_CHG_BAUD_CMD_OCF        0x0C
+#define HCI_VENDOR_CMD_OGF             0x3F
+#define WRITE_BDADDR_CMD_LEN        14
+#define WRITE_BAUD_CMD_LEN             6
+#define MAX_CMD_LEN                    WRITE_BDADDR_CMD_LEN
+#define GET_VERSION_OCF            0x1E
+
+#define PS_HDR_LEN                         4
+#define HCI_VENDOR_CMD_OGF      0x3F
+#define HCI_PS_CMD_OCF                0x0B
+
+#define HCI_COMMAND_HDR_SIZE        3
+#define EVT_CMD_COMPLETE_SIZE       3
+#define EVT_CMD_STATUS                     0x0F
+#define EVT_CMD_STATUS_SIZE           4
+#define HCI_EVENT_HDR_SIZE              2
+#define HCI_EV_SUCCESS                      0x00
+/* HCI Socket options */
+#define HCI_DATA_DIR            1
+#define HCI_FILTER                  2
+#define HCI_TIME_STAMP        3
+
+#define P_ID_OFFSET                                     (0)
+#define HCI_CMD_IND                                   (1)
+#define EVENTCODE_OFFSET                      (1)
+#define EVT_PLEN                                             (2)
+#define PLEN                                                       (3)
+#define CMD_RSP_OFFSET                             (3)
+#define RSP_TYPE_OFFSET                            (4)
+#define BAUDRATE_RSP_STATUS_OFFSET    (4)
+#define CMD_STATUS_OFFSET                      (5)
+#define P_ROME_VER_OFFSET                       (4)
+#define P_BUILD_VER_OFFSET                      (6)
+#define P_BASE_ADDR_OFFSET                     (8)
+#define P_ENTRY_ADDR_OFFSET                   (12)
+#define P_LEN_OFFSET                                   (16)
+#define P_CRC_OFFSET                                  (20)
+#define P_CONTROL_OFFSET                          (24)
+#define PATCH_HDR_LEN                               (28)
+#define MAX_DATA_PER_SEGMENT                (239)
+#define VSEVENT_CODE                                 (0xFF)
+#define HC_VS_MAX_CMD_EVENT                 (0xFF)
+#define PATCH_PROD_ID_OFFSET                (5)
+#define PATCH_PATCH_VER_OFFSET            (9)
+#define PATCH_ROM_BUILD_VER_OFFSET       (11)
+#define PATCH_SOC_VER_OFFSET             (13)
+#define MAX_SIZE_PER_TLV_SEGMENT        (243)
+
+/* VS Opcode */
+#define HCI_PATCH_CMD_OCF                       (0)
+#define EDL_SET_BAUDRATE_CMD_OCF        (0x48)
+#define EDL_WIPOWER_VS_CMD_OCF          (0x1f)
+#define HCI_VS_GET_ADDON_FEATURES_SUPPORT   (0x1d)
+
+/* VS Commands */
+#define VSC_SET_BAUDRATE_REQ_LEN        (1)
+#define EDL_PATCH_CMD_LEN	                       (1)
+#define EDL_PATCH_CMD_REQ_LEN               (1)
+#define EDL_WIP_QUERY_CHARGING_STATUS_LEN   (0x01)
+#define EDL_WIP_START_HANDOFF_TO_HOST_LEN   (0x01)
+#define EDL_PATCH_DLD_REQ_CMD               (0x01)
+#define EDL_PATCH_RST_REQ_CMD               (0x05)
+#define EDL_PATCH_SET_REQ_CMD               (0x16)
+#define EDL_PATCH_ATCH_REQ_CMD            (0x17)
+#define EDL_PATCH_VER_REQ_CMD               (0x19)
+#define EDL_GET_BUILD_INFO                  (0x20)
+#define EDL_PATCH_TLV_REQ_CMD               (0x1E)
+#define EDL_WIP_QUERY_CHARGING_STATUS_CMD   (0x1D)
+#define EDL_WIP_START_HANDOFF_TO_HOST_CMD   (0x1E)
+
+/* VS Event */
+#define EDL_CMD_REQ_RES_EVT                 (0x00)
+#define EDL_CMD_EXE_STATUS_EVT           (0x00)
+#define EDL_SET_BAUDRATE_RSP_EVT       (0x92)
+#define EDL_PATCH_VER_RES_EVT             (0x19)
+#define EDL_TVL_DNLD_RES_EVT                (0x04)
+#define EDL_APP_VER_RES_EVT                  (0x02)
+#define EDL_WIP_QUERY_CHARGING_STATUS_EVT    (0x18)
+#define EDL_WIP_START_HANDOFF_TO_HOST_EVENT  (0x19)
+#define HCI_VS_GET_ADDON_FEATURES_EVENT      (0x1B)
+#define HCI_VS_GET_BUILD_VER_EVT             (0x05)
+#define HCI_VS_STRAY_EVT                (0x17)
+
+/* Status Codes of HCI CMD execution*/
+#define HCI_CMD_SUCCESS                     (0x0)
+#define PATCH_LEN_ERROR                       (0x1)
+#define PATCH_VER_ERROR                       (0x2)
+#define PATCH_CRC_ERROR                     (0x3)
+#define PATCH_NOT_FOUND                      (0x4)
+#define TLV_TYPE_ERROR                         (0x10)
+#define NVM_ACCESS_CODE                     (0x0B)
+#define BAUDRATE_CHANGE_SUCCESS   (1)
+
+/* Wipower status codes */
+#define WIPOWER_IN_EMBEDDED_MODE 0x01
+#define NON_WIPOWER_MODE 0x02
+
+/* mask to validate support for wipower */
+#define ADDON_FEATURES_EVT_WIPOWER_MASK      (0x01)
+
+/* TLV_TYPE */
+#define TLV_TYPE_PATCH                  (1)
+#define TLV_TYPE_NVM                      (2)
+
+/* NVM */
+#define MAX_TAG_CMD                 30
+#define TAG_END                           0xFF
+#define NVM_ACCESS_SET            0x01
+#define TAG_NUM_OFFSET             5
+#define TAG_NUM_2                       2
+#define TAG_BDADDR_OFFSET     7
+
+/* NVM Tags specifically used for ROME 1.0 */
+#define ROME_1_0_100022_1       0x101000221
+#define ROME_1_0_100019           0x101000190
+#define ROME_1_0_6002               0x100600200
+
+/* Default NVM Version setting for ROME 1.0 */
+#define NVM_VERSION                  ROME_1_0_100022_1
+
+
+#define LSH(val, n)     ((uint32_t)(val) << (n))
+#define EXTRACT_BYTE(val, pos)      (char) (((val) >> (8 * (pos))) & 0xFF)
+#define CALC_SEG_SIZE(len, max)   ((plen) % (max))?((plen/max)+1) : ((plen) / (max))
+
+#define ROME_FW_PATH                      "/system/etc/firmware/rampatch.img"
+#define ROME_RAMPATCH_TLV_PATH            "/system/etc/firmware/rampatch_tlv.img"
+#define ROME_NVM_TLV_PATH                 "/system/etc/firmware/nvm_tlv.bin"
+#define ROME_RAMPATCH_TLV_1_0_3_PATH      "/system/etc/firmware/rampatch_tlv_1.3.tlv"
+#define ROME_NVM_TLV_1_0_3_PATH           "/system/etc/firmware/nvm_tlv_1.3.bin"
+#define ROME_RAMPATCH_TLV_2_0_1_PATH      "/system/etc/firmware/rampatch_tlv_2.1.tlv"
+#define ROME_NVM_TLV_2_0_1_PATH           "/system/etc/firmware/nvm_tlv_2.1.bin"
+#define ROME_RAMPATCH_TLV_3_0_0_PATH      "/bt_firmware/image/btfw30.tlv"
+#define ROME_NVM_TLV_3_0_0_PATH           "/bt_firmware/image/btnv30.bin"
+#define ROME_RAMPATCH_TLV_3_0_2_PATH      "/bt_firmware/image/btfw32.tlv"
+#define ROME_NVM_TLV_3_0_2_PATH           "/bt_firmware/image/btnv32.bin"
+
+#define ROME_3_1_FW_SU  "bprm.cnss.3.1"
+#define ROME_3_2_FW_SU  "btfwp.cnss.3.2"
+
+/* Rome 3.1 FW SU release has been branched from rome 3.0 SU 224
+    So, rome 3.1 formula is SU = patch version -(0xE0 = 224) - 0x111 -1
+*/
+#define ROME_3_1_FW_SW_OFFSET   0x01F2
+
+/* Rome 3.2 FW SU formula is SU = patch version - 0x111 -1 */
+#define ROME_3_2_FW_SW_OFFSET   0x0112
+
+/* This header value in rampatch file decides event handling mechanism in the HOST */
+#define ROME_SKIP_EVT_NONE     0x00
+#define ROME_SKIP_EVT_VSE      0x01
+#define ROME_SKIP_EVT_CC       0x02
+#define ROME_SKIP_EVT_VSE_CC   0x03
+
+/******************************************************************************
+**  Local type definitions
+******************************************************************************/
+typedef struct {
+    unsigned short rom_version;
+    unsigned short build_version;
+} __attribute__ ((packed)) patch_version;
+
+typedef struct {
+    unsigned int patch_id;
+    patch_version patch_ver;
+    unsigned int patch_base_addr;
+    unsigned int patch_entry_addr;
+    unsigned short patch_length;
+    int patch_crc;
+    unsigned short patch_ctrl;
+} __attribute__ ((packed)) patch_info;
+
+typedef struct {
+    unsigned int  tlv_data_len;
+    unsigned int  tlv_patch_data_len;
+    unsigned char sign_ver;
+    unsigned char sign_algorithm;
+    unsigned char dwnd_cfg;
+    unsigned char reserved1;
+    unsigned short prod_id;
+    unsigned short build_ver;
+    unsigned short patch_ver;
+    unsigned short reserved2;
+    unsigned int patch_entry_addr;
+} __attribute__ ((packed)) tlv_patch_hdr;
+
+typedef struct {
+    unsigned short tag_id;
+    unsigned short tag_len;
+    unsigned int tag_ptr;
+    unsigned int tag_ex_flag;
+} __attribute__ ((packed)) tlv_nvm_hdr;
+
+typedef struct {
+    unsigned char tlv_type;
+    unsigned char tlv_length1;
+    unsigned char tlv_length2;
+    unsigned char tlv_length3;
+
+    union{
+        tlv_patch_hdr patch;
+        tlv_nvm_hdr nvm;
+    }tlv;
+} __attribute__ ((packed)) tlv_patch_info;
+
+
+enum{
+    BAUDRATE_115200     = 0x00,
+    BAUDRATE_57600      = 0x01,
+    BAUDRATE_38400      = 0x02,
+    BAUDRATE_19200      = 0x03,
+    BAUDRATE_9600       = 0x04,
+    BAUDRATE_230400     = 0x05,
+    BAUDRATE_250000     = 0x06,
+    BAUDRATE_460800     = 0x07,
+    BAUDRATE_500000     = 0x08,
+    BAUDRATE_720000     = 0x09,
+    BAUDRATE_921600     = 0x0A,
+    BAUDRATE_1000000   = 0x0B,
+    BAUDRATE_1250000   = 0x0C,
+    BAUDRATE_2000000   = 0x0D,
+    BAUDRATE_3000000   = 0x0E,
+    BAUDRATE_4000000   = 0x0F,
+    BAUDRATE_1600000   = 0x10,
+    BAUDRATE_3200000   = 0x11,
+    BAUDRATE_3500000   = 0x12,
+    BAUDRATE_AUTO        = 0xFE,
+    BAUDRATE_Reserved  = 0xFF
+};
+
+enum{
+    ROME_PATCH_VER_0100 = 0x0100,
+    ROME_PATCH_VER_0101 = 0x0101,
+    ROME_PATCH_VER_0200 = 0x0200,
+    ROME_PATCH_VER_0300 = 0x0300,
+    ROME_PATCH_VER_0302 = 0x0302
+ };
+
+enum{
+    ROME_SOC_ID_00 = 0x00000000,
+    ROME_SOC_ID_11 = 0x00000011,
+    ROME_SOC_ID_22 = 0x00000022,
+    ROME_SOC_ID_44 = 0x00000044
+};
+
+enum{
+    ROME_VER_UNKNOWN = 0,
+    ROME_VER_1_0 = ((ROME_PATCH_VER_0100 << 16 ) | ROME_SOC_ID_00 ),
+    ROME_VER_1_1 = ((ROME_PATCH_VER_0101 << 16 ) | ROME_SOC_ID_00 ),
+    ROME_VER_1_3 = ((ROME_PATCH_VER_0200 << 16 ) | ROME_SOC_ID_00 ),
+    ROME_VER_2_1 = ((ROME_PATCH_VER_0200 << 16 ) | ROME_SOC_ID_11 ),
+    ROME_VER_3_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_22 ),
+    ROME_VER_3_2 = ((ROME_PATCH_VER_0302 << 16 ) | ROME_SOC_ID_44 )
+};
+
+//declarations
+int rome_soc_init(int fd, char *bdaddr);
+int check_embedded_mode(int fd);
+int rome_get_addon_feature_list(int fd);
+void enable_controller_log(int fd, unsigned char req);
+void cherokee_shutdown_vs_cmd(int fd);
+#endif /* HW_ROME_H */
diff --git a/sdm845/libbt-vendor/include/vnd_generic.txt b/sdm845/libbt-vendor/include/vnd_generic.txt
new file mode 100644
index 0000000..43e790c
--- /dev/null
+++ b/sdm845/libbt-vendor/include/vnd_generic.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/sdm845/libbt-vendor/include/vnd_mako.txt b/sdm845/libbt-vendor/include/vnd_mako.txt
new file mode 100644
index 0000000..5408c92
--- /dev/null
+++ b/sdm845/libbt-vendor/include/vnd_mako.txt
@@ -0,0 +1,9 @@
+BLUETOOTH_UART_DEVICE_PORT = "/dev/smd3"
+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/sdm845/libbt-vendor/src/bt_vendor_persist.cpp b/sdm845/libbt-vendor/src/bt_vendor_persist.cpp
new file mode 100644
index 0000000..519e826
--- /dev/null
+++ b/sdm845/libbt-vendor/src/bt_vendor_persist.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bt_vendor_persist.h"
+
+#ifdef BT_NV_SUPPORT
+#include "bt_nv.h"
+#include <utils/Log.h>
+
+/*===========================================================================
+FUNCTION   bt_vendor_nv_read
+
+DESCRIPTION
+ Helper Routine to process the nv read command
+
+DEPENDENCIES
+  NIL
+
+RETURN VALUE
+  RETURN VALUE
+  FALSE = failure, else TRUE
+
+SIDE EFFECTS
+  None
+
+===========================================================================*/
+uint8_t bt_vendor_nv_read
+(
+  uint8_t nv_item,
+  uint8_t * rsp_buf
+)
+{
+  nv_persist_item_type my_nv_item;
+  nv_persist_stat_enum_type cmd_result;
+  boolean result = FALSE;
+
+  switch(nv_item)
+  {
+    case NV_BD_ADDR_I:
+      cmd_result = (nv_persist_stat_enum_type)bt_nv_cmd(NV_READ_F,  NV_BD_ADDR_I, &my_nv_item);
+      ALOGI("CMD result: %d", cmd_result);
+      if (NV_SUCCESS != cmd_result)
+      {
+        ALOGE("Failed to read BD_ADDR from NV");
+        /* Send fail response */
+        result = FALSE;
+      }
+      else
+      {
+        /* copy bytes */
+        rsp_buf[0] = my_nv_item.bd_addr[0];
+        rsp_buf[1] = my_nv_item.bd_addr[1];
+        rsp_buf[2] = my_nv_item.bd_addr[2];
+        rsp_buf[3] = my_nv_item.bd_addr[3];
+        rsp_buf[4] = my_nv_item.bd_addr[4];
+        rsp_buf[5] = my_nv_item.bd_addr[5];
+
+        ALOGI("BD address read for NV_BD_ADDR_I: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+                (unsigned int) my_nv_item.bd_addr[0],(unsigned int) my_nv_item.bd_addr[1],
+                (unsigned int) my_nv_item.bd_addr[2],(unsigned int) my_nv_item.bd_addr[3],
+                (unsigned int) my_nv_item.bd_addr[4],(unsigned int) my_nv_item.bd_addr[5]);
+        result = TRUE;
+      }
+      break;
+  }
+  return result;
+}
+#endif /* End of BT_NV_SUPPORT */
diff --git a/sdm845/libbt-vendor/src/bt_vendor_qcom.c b/sdm845/libbt-vendor/src/bt_vendor_qcom.c
new file mode 100755
index 0000000..8cbf5d1
--- /dev/null
+++ b/sdm845/libbt-vendor/src/bt_vendor_qcom.c
@@ -0,0 +1,1483 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * 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_qcom.c
+ *
+ *  Description:   vendor specific library implementation
+ *
+ ******************************************************************************/
+#define LOG_TAG "bt_vendor"
+#define BLUETOOTH_MAC_ADDR_BOOT_PROPERTY "ro.boot.btmacaddr"
+
+#include <utils/Log.h>
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <termios.h>
+#include "bt_vendor_qcom.h"
+#include "hci_uart.h"
+#include "hci_smd.h"
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <cutils/sockets.h>
+#include <linux/un.h>
+#include "bt_vendor_persist.h"
+#include "hw_rome.h"
+#include "bt_vendor_lib.h"
+#define WAIT_TIMEOUT 200000
+#define BT_VND_OP_GET_LINESPEED 30
+
+#define STOP_WCNSS_FILTER 0xDD
+#define STOP_WAIT_TIMEOUT   1000
+
+#define SOC_INIT_PROPERTY "wc_transport.soc_initialized"
+
+#define BT_VND_FILTER_START "wc_transport.start_hci"
+
+#define CMD_TIMEOUT  0x22
+
+static void wait_for_patch_download(bool is_ant_req);
+static bool is_debug_force_special_bytes(void);
+int connect_to_local_socket(char* name);
+/******************************************************************************
+**  Externs
+******************************************************************************/
+extern int hw_config(int nState);
+extern int is_hw_ready();
+extern int chipset_ver;
+
+/******************************************************************************
+**  Variables
+******************************************************************************/
+struct bt_qcom_struct *q = NULL;
+pthread_mutex_t q_lock = PTHREAD_MUTEX_INITIALIZER;
+
+int userial_clock_operation(int fd, int cmd);
+int ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti);
+int userial_vendor_get_baud(void);
+int readTrpState();
+void lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity);
+bool is_download_progress();
+
+static const tUSERIAL_CFG userial_init_cfg =
+{
+    (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
+    USERIAL_BAUD_115200
+};
+
+#if (HW_NEED_END_WITH_HCI_RESET == TRUE)
+void __hw_epilog_process(void);
+#endif
+
+#ifdef WIFI_BT_STATUS_SYNC
+#include <string.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include "cutils/properties.h"
+
+static const char WIFI_PROP_NAME[]    = "wlan.driver.status";
+static const char SERVICE_PROP_NAME[]    = "bluetooth.hsic_ctrl";
+static const char BT_STATUS_NAME[]    = "bluetooth.enabled";
+static const char WIFI_SERVICE_PROP[] = "wlan.hsic_ctrl";
+
+#define WIFI_BT_STATUS_LOCK    "/data/connectivity/wifi_bt_lock"
+int isInit=0;
+#endif /* WIFI_BT_STATUS_SYNC */
+bool is_soc_initialized(void);
+
+/******************************************************************************
+**  Local type definitions
+******************************************************************************/
+
+/******************************************************************************
+**  Functions
+******************************************************************************/
+#ifdef WIFI_BT_STATUS_SYNC
+int bt_semaphore_create(void)
+{
+    int fd;
+
+    fd = open(WIFI_BT_STATUS_LOCK, O_RDONLY);
+
+    if (fd < 0)
+        ALOGE("can't create file\n");
+
+    return fd;
+}
+
+int bt_semaphore_get(int fd)
+{
+    int ret;
+
+    if (fd < 0)
+        return -1;
+
+    ret = flock(fd, LOCK_EX);
+    if (ret != 0) {
+        ALOGE("can't hold lock: %s\n", strerror(errno));
+        return -1;
+    }
+
+    return ret;
+}
+
+int bt_semaphore_release(int fd)
+{
+    int ret;
+
+    if (fd < 0)
+        return -1;
+
+    ret = flock(fd, LOCK_UN);
+    if (ret != 0) {
+        ALOGE("can't release lock: %s\n", strerror(errno));
+        return -1;
+    }
+
+    return ret;
+}
+
+int bt_semaphore_destroy(int fd)
+{
+    if (fd < 0)
+        return -1;
+
+    return close (fd);
+}
+
+int bt_wait_for_service_done(void)
+{
+    char service_status[PROPERTY_VALUE_MAX];
+    int count = 30;
+
+    ALOGE("%s: check\n", __func__);
+
+    /* wait for service done */
+    while (count-- > 0) {
+        property_get(WIFI_SERVICE_PROP, service_status, NULL);
+
+        if (strcmp(service_status, "") != 0) {
+            usleep(200000);
+        } else {
+            break;
+        }
+    }
+
+    return 0;
+}
+
+#endif /* WIFI_BT_STATUS_SYNC */
+
+/** Get Bluetooth SoC type from system setting */
+static int get_bt_soc_type()
+{
+    int ret = 0;
+    char bt_soc_type[PROPERTY_VALUE_MAX];
+
+    ALOGI("bt-vendor : get_bt_soc_type");
+
+    ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL);
+    if (ret != 0) {
+        ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type);
+        if (!strncasecmp(bt_soc_type, "rome", sizeof("rome"))) {
+            return BT_SOC_ROME;
+        }
+        else if (!strncasecmp(bt_soc_type, "cherokee", sizeof("cherokee"))) {
+            return BT_SOC_CHEROKEE;
+        }
+        else if (!strncasecmp(bt_soc_type, "ath3k", sizeof("ath3k"))) {
+            return BT_SOC_AR3K;
+        }
+        else if (!strncasecmp(bt_soc_type, "cherokee", sizeof("cherokee"))) {
+            return BT_SOC_CHEROKEE;
+        }
+        else {
+            ALOGI("qcom.bluetooth.soc not set, so using default.\n");
+            return BT_SOC_DEFAULT;
+        }
+    }
+    else {
+        ALOGE("%s: Failed to get soc type", __FUNCTION__);
+        ret = BT_SOC_DEFAULT;
+    }
+
+    return ret;
+}
+
+bool can_perform_action(char action) {
+    bool can_perform = false;
+    char ref_count[PROPERTY_VALUE_MAX];
+    char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
+    int value, ret;
+
+    property_get("wc_transport.ref_count", ref_count, "0");
+
+    value = atoi(ref_count);
+    ALOGV("%s: ref_count: %s\n",__func__,  ref_count);
+
+    if(action == '1') {
+        ALOGV("%s: on : value is: %d", __func__, value);
+        if(value == 1)
+        {
+            if ((is_soc_initialized() == true)
+               || is_download_progress() || get_bt_soc_type() == BT_SOC_CHEROKEE)
+          {
+            value++;
+            ALOGV("%s: on : value is incremented to : %d", __func__, value);
+          }
+        }
+        else
+        {
+             value++;
+        }
+
+        if (value == 1)
+            can_perform = true;
+        else if (value > 3)
+            return false;
+    }
+    else {
+        ALOGV("%s: off : value is: %d", __func__, value);
+        if (--value <= 0) {
+            ALOGE("%s: BT turn off twice before BT On(ref_count=%d)\n",
+                    __func__, value);
+            value = 0;
+            can_perform = true;
+        }
+    }
+
+    snprintf(ref_count, 3, "%d", value);
+    ALOGV("%s: updated ref_count is: %s", __func__, ref_count);
+
+    ret  = property_set("wc_transport.ref_count", ref_count);
+    if (ret < 0) {
+        ALOGE("%s: Error while updating property: %d\n", __func__, ret);
+        return false;
+    }
+    ALOGV("%s returning %d", __func__, can_perform);
+    return can_perform;
+}
+
+void stop_hci_filter() {
+       char value[PROPERTY_VALUE_MAX] = {'\0'};
+       int retval, filter_ctrl, i;
+       char stop_val = STOP_WCNSS_FILTER;
+       int soc_type = BT_SOC_DEFAULT;
+
+       ALOGV("%s: Entry ", __func__);
+
+       if ((soc_type = get_bt_soc_type()) == BT_SOC_CHEROKEE) {
+           property_get("wc_transport.hci_filter_status", value, "0");
+           if (strcmp(value, "0") == 0) {
+               ALOGI("%s: hci_filter has been stopped already", __func__);
+           }
+           else {
+               filter_ctrl = connect_to_local_socket("wcnssfilter_ctrl");
+               if (filter_ctrl < 0) {
+                   ALOGI("%s: Error while connecting to CTRL_SOCK, filter should stopped: %d",
+                          __func__, filter_ctrl);
+               }
+               else {
+                   retval = write(filter_ctrl, &stop_val, 1);
+                   if (retval != 1) {
+                       ALOGI("%s: problem writing to CTRL_SOCK, ignore: %d", __func__, retval);
+                       //Ignore and fallback
+                   }
+
+                   close(filter_ctrl);
+               }
+           }
+
+           /* Ensure Filter is closed by checking the status before
+              RFKILL 0 operation. this should ideally comeout very
+              quick */
+           for(i=0; i<500; i++) {
+               property_get(BT_VND_FILTER_START, value, "false");
+               if (strcmp(value, "false") == 0) {
+                   ALOGI("%s: WCNSS_FILTER stopped", __func__);
+                   usleep(STOP_WAIT_TIMEOUT * 10);
+                   break;
+               } else {
+                   /*sleep of 1ms, This should give enough time for FILTER to
+                   exit with all necessary cleanup*/
+                   usleep(STOP_WAIT_TIMEOUT);
+               }
+           }
+
+           /*Never use SIGKILL to stop the filter*/
+           /* Filter will be stopped by below two conditions
+            - by Itself, When it realizes there are no CONNECTED clients
+            - Or through STOP_WCNSS_FILTER byte on Control socket
+            both of these ensure clean shutdown of chip
+           */
+           //property_set(BT_VND_FILTER_START, "false");
+       } else if (soc_type == BT_SOC_ROME) {
+           property_set(BT_VND_FILTER_START, "false");
+       } else {
+           ALOGI("%s: Unknown soc type %d, Unexpected!", __func__, soc_type);
+       }
+
+       ALOGV("%s: Exit ", __func__);
+}
+
+int start_hci_filter() {
+       ALOGV("%s: Entry ", __func__);
+       int i, init_success = -1;
+       char value[PROPERTY_VALUE_MAX] = {'\0'};
+
+       property_get(BT_VND_FILTER_START, value, false);
+
+       if (strcmp(value, "true") == 0) {
+           ALOGI("%s: hci_filter has been started already", __func__);
+           //Filter should have been started OR in the process of initializing
+           //Make sure of hci_filter_status and return the state based on it
+       } else {
+
+           property_set("wc_transport.hci_filter_status", "0");
+           property_set(BT_VND_FILTER_START, "true");
+           ALOGV("%s: %s set to true ", __func__, BT_VND_FILTER_START );
+       }
+
+       /*If there are back to back ON requests from different clients,
+         All client should come and stuck in this while loop till FILTER
+         comesup and ready to accept the connections */
+       //sched_yield();
+       for(i=0; i<45; i++) {
+          property_get("wc_transport.hci_filter_status", value, "0");
+          if (strcmp(value, "1") == 0) {
+               init_success = 1;
+               break;
+           } else {
+               usleep(WAIT_TIMEOUT);
+           }
+        }
+        ALOGV("start_hcifilter status:%d after %f seconds \n", init_success, 0.2*i);
+
+        ALOGV("%s: Exit ", __func__);
+        return init_success;
+}
+
+/*
+ * Bluetooth Controller power up or shutdown, this function is called with
+ * q_lock held and q is non-NULL
+ */
+static int bt_powerup(int en )
+{
+    char rfkill_type[64], *enable_ldo_path = NULL;
+    char type[16], enable_ldo[6];
+    int fd = 0, size, i, ret, fd_ldo, fd_btpower;
+
+    char disable[PROPERTY_VALUE_MAX];
+    char state;
+    char on = (en)?'1':'0';
+
+#ifdef WIFI_BT_STATUS_SYNC
+    char wifi_status[PROPERTY_VALUE_MAX];
+    int lock_fd;
+#endif /*WIFI_BT_STATUS_SYNC*/
+
+    ALOGI("bt_powerup: %c", on);
+
+    /* Check if rfkill has been disabled */
+    ret = property_get("ro.rfkilldisabled", disable, "0");
+    if (!ret ){
+        ALOGE("Couldn't get ro.rfkilldisabled (%d)", ret);
+        return -1;
+    }
+    /* In case rfkill disabled, then no control power*/
+    if (strcmp(disable, "1") == 0) {
+        ALOGI("ro.rfkilldisabled : %s", disable);
+        return -1;
+    }
+
+#ifdef WIFI_BT_STATUS_SYNC
+    lock_fd = bt_semaphore_create();
+    bt_semaphore_get(lock_fd);
+    bt_wait_for_service_done();
+#endif
+
+    /* Assign rfkill_id and find bluetooth rfkill state path*/
+    for(i = 0; (q->rfkill_id == -1) && (q->rfkill_state == NULL); i++)
+    {
+        snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i);
+        if ((fd = open(rfkill_type, O_RDONLY)) < 0)
+        {
+            ALOGE("open(%s) failed: %s (%d)\n", rfkill_type, strerror(errno), errno);
+
+#ifdef WIFI_BT_STATUS_SYNC
+            bt_semaphore_release(lock_fd);
+            bt_semaphore_destroy(lock_fd);
+#endif
+            return -1;
+        }
+
+        size = read(fd, &type, sizeof(type));
+        close(fd);
+
+        if ((size >= 9) && !memcmp(type, "bluetooth", 9))
+        {
+            asprintf(&q->rfkill_state, "/sys/class/rfkill/rfkill%d/state", q->rfkill_id = i);
+            break;
+        }
+    }
+
+    /* Get rfkill State to control */
+    if (q->rfkill_state != NULL)
+    {
+        if ((fd = open(q->rfkill_state, O_RDWR)) < 0)
+        {
+            ALOGE("open(%s) for write failed: %s (%d)", q->rfkill_state, strerror(errno), errno);
+#ifdef WIFI_BT_STATUS_SYNC
+            bt_semaphore_release(lock_fd);
+            bt_semaphore_destroy(lock_fd);
+#endif
+
+            return -1;
+        }
+    }
+    /* Always perform BT power action so as to have the chance to 
+       recover BT power properly from un-expected error. */
+#ifdef CHECK_BT_POWER_PERFORM_ACTION
+    if(can_perform_action(on) == false) {
+        ALOGE("%s:can't perform action as it is being used by other clients", __func__);
+#ifdef WIFI_BT_STATUS_SYNC
+            bt_semaphore_release(lock_fd);
+            bt_semaphore_destroy(lock_fd);
+#endif
+            goto done;
+    }
+#else
+    ALOGI("%s: always perform action", __func__);
+#endif
+    ret = asprintf(&enable_ldo_path, "/sys/class/rfkill/rfkill%d/device/extldo", q->rfkill_id);
+    if( (ret < 0 ) || (enable_ldo_path == NULL) )
+    {
+        ALOGE("Memory Allocation failure");
+        return -1;
+    }
+    if ((fd_ldo = open(enable_ldo_path, O_RDWR)) < 0) {
+        ALOGE("open(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
+        return -1;
+    }
+    size = read(fd_ldo, &enable_ldo, sizeof(enable_ldo));
+    close(fd_ldo);
+    if (size <= 0) {
+        ALOGE("read(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
+        return -1;
+    }
+    if (!memcmp(enable_ldo, "true", 4)) {
+        ALOGI("External LDO has been configured");
+        ret = property_set("wc_transport.extldo", "enabled");
+        if (ret < 0) {
+            ALOGI("%s: Not able to set property wc_transport.extldo\n", __func__);
+        }
+        q->enable_extldo = TRUE;
+    }
+
+    if(on == '0'){
+        ALOGE("Stopping HCI filter as part of CTRL:OFF");
+        stop_hci_filter();
+        property_set("wc_transport.soc_initialized", "0");
+    }
+
+    if (q->soc_type >= BT_SOC_CHEROKEE && q->soc_type < BT_SOC_RESERVED) {
+       ALOGI("open bt power devnode,send ioctl power op  :%d ",en);
+       fd_btpower = open(BT_PWR_CNTRL_DEVICE, O_RDWR, O_NONBLOCK);
+       if (fd_btpower < 0) {
+           ALOGE("\nfailed to open bt device error = (%s)\n",strerror(errno));
+#ifdef WIFI_BT_STATUS_SYNC
+           bt_semaphore_release(lock_fd);
+           bt_semaphore_destroy(lock_fd);
+#endif
+           return -1;
+       }
+       ret = ioctl(fd_btpower, BT_CMD_PWR_CTRL, (unsigned long)en);
+        if (ret < 0) {
+            ALOGE(" ioctl failed to power control:%d error =(%s)",ret,strerror(errno));
+        }
+        close(fd_btpower);
+    } else {
+       ALOGI("Write %c to rfkill\n", on);
+       /* Write value to control rfkill */
+       if(fd >= 0) {
+           if ((size = write(fd, &on, 1)) < 0) {
+               ALOGE("write(%s) failed: %s (%d)", q->rfkill_state, strerror(errno), errno);
+#ifdef WIFI_BT_STATUS_SYNC
+               bt_semaphore_release(lock_fd);
+               bt_semaphore_destroy(lock_fd);
+#endif
+               return -1;
+           }
+       }
+   }
+#ifdef WIFI_BT_STATUS_SYNC
+    /* query wifi status */
+    property_get(WIFI_PROP_NAME, wifi_status, "");
+
+    ALOGE("bt get wifi status: %s, isInit: %d\n",  wifi_status, isInit);
+
+    /* If wlan driver is not loaded, and bt is changed from off => on */
+    if (strncmp(wifi_status, "unloaded", strlen("unloaded")) == 0 || strlen(wifi_status) == 0) {
+        if (on == '1') {
+            ALOGI("%s: BT_VND_PWR_ON\n", __func__);
+            if(property_set(SERVICE_PROP_NAME, "load_wlan") < 0) {
+                ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
+                close(fd);
+                bt_semaphore_release(lock_fd);
+                bt_semaphore_destroy(lock_fd);
+                return -1;
+            }
+        }
+        else if (isInit == 0 && on == '0') {
+            ALOGI("%s: BT_VND_PWR_OFF\n", __func__);
+            if(property_set(SERVICE_PROP_NAME, "unbind_hsic") < 0) {
+                ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
+                close(fd);
+                bt_semaphore_release(lock_fd);
+                bt_semaphore_destroy(lock_fd);
+                return -1;
+            }
+       }
+    }
+
+    if (isInit == 0 && on == '0')
+        property_set(BT_STATUS_NAME, "false");
+    else if (on == '1')
+        property_set(BT_STATUS_NAME, "true");
+
+    bt_semaphore_release(lock_fd);
+    bt_semaphore_destroy(lock_fd);
+#endif /* WIFI_BT_STATUS_SYNC */
+
+done:
+    if (fd >= 0)
+        close(fd);
+    return 0;
+}
+
+static inline void soc_init(int soc_type)
+{
+    switch (soc_type)
+    {
+    case BT_SOC_CHEROKEE:
+    case BT_SOC_ROME:
+    case BT_SOC_AR3K:
+        ALOGI("bt-vendor : Initializing UART transport layer");
+        userial_vendor_init();
+        break;
+    case BT_SOC_DEFAULT:
+        break;
+    default:
+        ALOGE("Unknown soc yype: %d", soc_type);
+        break;
+    }
+}
+
+/* Copy BD Address as little-endian byte order */
+static inline void le2bd(unsigned char *src, unsigned char *dst)
+{
+    int i;
+    for (i = 0; i < 6; i++)
+        dst[i] = src[5-i];
+}
+
+static inline void print_bdaddr(unsigned char *addr)
+{
+    ALOGI("BD Address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", addr[0], addr[1],
+            addr[2], addr[3], addr[4], addr[5]);
+}
+
+/*****************************************************************************
+**
+**   BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
+**
+*****************************************************************************/
+
+static int init(const bt_vendor_callbacks_t *cb, unsigned char *bdaddr)
+{
+    char prop[PROPERTY_VALUE_MAX] = {0};
+    struct bt_qcom_struct *temp = NULL;
+    int ret = BT_STATUS_SUCCESS, i;
+
+    ALOGI("++%s", __FUNCTION__);
+
+    if (!cb || !bdaddr) {
+        ALOGE("Invalid input args cb %p bdaddr %p", cb, bdaddr);
+        ret = -BT_STATUS_INVAL;
+        goto out;
+    }
+
+    temp = (struct bt_qcom_struct *) malloc(sizeof(*q));
+    if (!temp) {
+        ALOGE("Failed to allocate memory. err %s(%d)", strerror(errno), errno);
+        ret = -BT_STATUS_NOMEM;
+        goto out;
+    }
+    memset(temp, 0, sizeof(*temp));
+
+    temp->rfkill_id = -1;
+    temp->enable_extldo = FALSE;
+    temp->cb = cb;
+    temp->ant_fd = -1;
+    temp->soc_type = get_bt_soc_type();
+    soc_init(temp->soc_type);
+
+    le2bd(bdaddr, temp->bdaddr);
+    print_bdaddr(temp->bdaddr);
+    snprintf(prop, sizeof(prop), "%02x:%02x:%02x:%02x:%02x:%02x",
+             temp->bdaddr[0], temp->bdaddr[1], temp->bdaddr[2],
+             temp->bdaddr[3], temp->bdaddr[4], temp->bdaddr[5]);
+    ret = property_set("wc_transport.stack_bdaddr", prop);
+    if (ret < 0) {
+        ALOGE("Failed to set wc_transport.stack_bdaddr prop, ret = %d", ret);
+        ret = -BT_STATUS_PROP_FAILURE;
+        goto out;
+    }
+
+/* TODO: Move these fields inside bt_qcom context */
+#ifdef WIFI_BT_STATUS_SYNC
+    isInit = 1;
+#endif /* WIFI_BT_STATUS_SYNC */
+
+    /* Everything successful */
+    q = temp;
+    return ret;
+
+out:
+    if (temp)
+        free(temp);
+    ALOGI("--%s ret %d", __FUNCTION__, ret);
+    return ret;
+}
+
+#ifdef READ_BT_ADDR_FROM_PROP
+static bool validate_tok(char* bdaddr_tok) {
+    int i = 0;
+    bool ret;
+
+    if (strlen(bdaddr_tok) != 2) {
+        ret = FALSE;
+        ALOGE("Invalid token length");
+    } else {
+        ret = TRUE;
+        for (i=0; i<2; i++) {
+            if ((bdaddr_tok[i] >= '0' && bdaddr_tok[i] <= '9') ||
+                (bdaddr_tok[i] >= 'A' && bdaddr_tok[i] <= 'F') ||
+                (bdaddr_tok[i] >= 'a' && bdaddr_tok[i] <= 'f')) {
+                ret = TRUE;
+                ALOGV("%s: tok %s @ %d is good", __func__, bdaddr_tok, i);
+             } else {
+                ret = FALSE;
+                ALOGE("invalid character in tok: %s at ind: %d", bdaddr_tok, i);
+                break;
+             }
+        }
+    }
+    return ret;
+}
+#endif /*READ_BT_ADDR_FROM_PROP*/
+
+int connect_to_local_socket(char* name) {
+       socklen_t len; int sk = -1;
+
+       ALOGE("%s: ACCEPT ", __func__);
+       sk  = socket(AF_LOCAL, SOCK_STREAM, 0);
+       if (sk < 0) {
+           ALOGE("Socket creation failure");
+           return -1;
+       }
+
+        if(socket_local_client_connect(sk, name,
+            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
+        {
+             ALOGE("failed to connect (%s)", strerror(errno));
+             close(sk);
+             sk = -1;
+        } else {
+                ALOGE("%s: Connection succeeded\n", __func__);
+        }
+        return sk;
+}
+
+bool is_soc_initialized() {
+    bool init = false;
+    char init_value[PROPERTY_VALUE_MAX];
+    int ret;
+
+    ALOGI("bt-vendor : is_soc_initialized");
+
+    ret = property_get(SOC_INIT_PROPERTY, init_value, NULL);
+    if (ret != 0) {
+        ALOGI("%s set to %s\n", SOC_INIT_PROPERTY, init_value);
+        if (!strncasecmp(init_value, "1", sizeof("1"))) {
+            init = true;
+        }
+    }
+    else {
+        ALOGE("%s: Failed to get %s", __FUNCTION__, SOC_INIT_PROPERTY);
+    }
+
+    return init;
+}
+
+/* flavor of op without locks */
+static int __op(bt_vendor_opcode_t opcode, void *param)
+{
+    int retval = BT_STATUS_SUCCESS;
+    int nCnt = 0;
+    int nState = -1;
+    bool is_ant_req = false;
+    bool is_fm_req = false;
+    char wipower_status[PROPERTY_VALUE_MAX];
+    char emb_wp_mode[PROPERTY_VALUE_MAX];
+    char bt_version[PROPERTY_VALUE_MAX];
+    char lpm_config[PROPERTY_VALUE_MAX];
+    bool ignore_boot_prop = TRUE;
+#ifdef READ_BT_ADDR_FROM_PROP
+    int i = 0;
+    static char bd_addr[PROPERTY_VALUE_MAX];
+    uint8_t local_bd_addr_from_prop[6];
+    char* tok;
+#endif
+    bool skip_init = true;
+    int  opcode_init = opcode;
+    ALOGV("++%s opcode %d", __FUNCTION__, opcode);
+
+    switch(opcode_init)
+    {
+#ifdef FM_OVER_UART
+        case FM_VND_OP_POWER_CTRL:
+            {
+              is_fm_req = true;
+              if (is_soc_initialized()) {
+                  // add any FM specific actions  if needed in future
+                  break;
+              }
+            }
+#endif
+        case BT_VND_OP_POWER_CTRL:
+            {
+                if (!param) {
+                    ALOGE("opcode = %d: param is null", opcode_init);
+                    break;
+                }
+                nState = *(int *) param;
+                ALOGI("bt-vendor : BT_VND_OP_POWER_CTRL: %s",
+                        (nState == BT_VND_PWR_ON)? "On" : "Off" );
+
+                switch(q->soc_type)
+                {
+                    case BT_SOC_DEFAULT:
+                        if (readTrpState())
+                        {
+                           ALOGI("bt-vendor : resetting BT status");
+                           hw_config(BT_VND_PWR_OFF);
+                        }
+                        retval = hw_config(nState);
+                        if(nState == BT_VND_PWR_ON
+                           && retval == 0
+                           && is_hw_ready() == TRUE){
+                            retval = 0;
+                        }
+                        else {
+                            retval = -1;
+                        }
+                        break;
+                    case BT_SOC_ROME:
+                    case BT_SOC_AR3K:
+                    case BT_SOC_CHEROKEE:
+                        if (q->soc_type == BT_SOC_ROME)
+                        {
+                            if (nState == BT_VND_PWR_ON)
+                            {
+                                /* Always power BT off before power on. */
+                                ALOGI("bt-vendor: always power off before power on");
+                                bt_powerup(BT_VND_PWR_OFF);
+                            }
+                        }
+
+                        /* BT Chipset Power Control through Device Tree Node */
+                        retval = bt_powerup(nState);
+                    default:
+                        break;
+                }
+            }
+            break;
+
+        case BT_VND_OP_FW_CFG: {
+                /* call hciattach to initalize the stack */
+                if (q->soc_type == BT_SOC_ROME) {
+                    if (is_soc_initialized()) {
+                        ALOGI("Bluetooth FW and transport layer are initialized");
+                        q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+                    } else {
+                        ALOGE("bt_vendor_cbacks is null or SoC not initialized");
+                        ALOGE("Error : hci, smd initialization Error");
+                        retval = -1;
+                    }
+                } else {
+                    ALOGI("Bluetooth FW and transport layer are initialized");
+                    q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
+                }
+        }
+            break;
+
+        case BT_VND_OP_SCO_CFG:
+            q->cb->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); //dummy
+            break;
+#ifdef ENABLE_ANT
+        case BT_VND_OP_ANT_USERIAL_OPEN:
+                ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_OPEN");
+                is_ant_req = true;
+                goto userial_open;
+#endif
+#ifdef FM_OVER_UART
+        case BT_VND_OP_FM_USERIAL_OPEN:
+                ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_OPEN");
+                is_fm_req = true;
+                goto userial_open;
+#endif
+userial_open:
+        case BT_VND_OP_USERIAL_OPEN:
+            {
+                if (!param) {
+                    ALOGE("opcode = %d: param is null", opcode_init);
+                    break;
+                }
+                int (*fd_array)[] = (int (*)[]) param;
+                int idx, fd = -1, fd_filter = -1;
+                ALOGI("bt-vendor : BT_VND_OP_USERIAL_OPEN");
+                switch(q->soc_type)
+                {
+                    case BT_SOC_DEFAULT:
+                        {
+                            if(bt_hci_init_transport(q->fd) != -1){
+                                int (*fd_array)[] = (int (*) []) param;
+
+                                    (*fd_array)[CH_CMD] = q->fd[0];
+                                    (*fd_array)[CH_EVT] = q->fd[0];
+                                    (*fd_array)[CH_ACL_OUT] = q->fd[1];
+                                    (*fd_array)[CH_ACL_IN] = q->fd[1];
+                            }
+                            else {
+                                retval = -1;
+                                break;
+                            }
+                            retval = 2;
+                        }
+                        break;
+                    case BT_SOC_AR3K:
+                        {
+                            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;
+                            }
+                            else {
+                                retval = -1;
+                                break;
+                            }
+
+                            /* Vendor Specific Process should happened during userial_open process
+                                After userial_open, rx read thread is running immediately,
+                                so it will affect VS event read process.
+                            */
+                            if(ath3k_init(fd,3000000,115200,NULL,&vnd_userial.termios)<0)
+                                retval = -1;
+                        }
+                        break;
+                    case BT_SOC_ROME:
+                        {
+                            wait_for_patch_download(is_ant_req);
+                            property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
+                            if (!is_soc_initialized()) {
+                                char* dlnd_inprog = is_ant_req ? "ant" : "bt";
+                                if (property_set("wc_transport.patch_dnld_inprog", dlnd_inprog) < 0) {
+                                    ALOGE("%s: Failed to set dnld_inprog %s", __FUNCTION__, dlnd_inprog);
+                                }
+
+                                fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
+                                if (fd < 0) {
+                                    ALOGE("userial_vendor_open returns err");
+                                    retval = -1;
+                                    break;
+                                }
+
+                                /* Clock on */
+                                userial_clock_operation(fd, USERIAL_OP_CLK_ON);
+
+                                if(strcmp(emb_wp_mode, "true") == 0) {
+                                    property_get("ro.bluetooth.wipower", wipower_status, false);
+                                    if(strcmp(wipower_status, "true") == 0) {
+                                        check_embedded_mode(fd);
+                                    } else {
+                                        ALOGI("Wipower not enabled");
+                                    }
+                                }
+                                ALOGV("rome_soc_init is started");
+                                property_set("wc_transport.soc_initialized", "0");
+#ifdef READ_BT_ADDR_FROM_PROP
+                                /*Give priority to read BD address from boot property*/
+                                ignore_boot_prop = FALSE;
+                                if (property_get(BLUETOOTH_MAC_ADDR_BOOT_PROPERTY, bd_addr, NULL)) {
+                                    ALOGV("BD address read from Boot property: %s\n", bd_addr);
+                                    tok =  strtok(bd_addr, ":");
+                                    while (tok != NULL) {
+                                        ALOGV("bd add [%d]: %d ", i, strtol(tok, NULL, 16));
+                                        if (i>=6) {
+                                            ALOGE("bd property of invalid length");
+                                            ignore_boot_prop = TRUE;
+                                            break;
+                                        }
+                                        if (i == 6 && !ignore_boot_prop) {
+                                            ALOGV("Valid BD address read from prop");
+                                            memcpy(q->bdaddr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
+                                            ignore_boot_prop = FALSE;
+                                        } else {
+                                            ALOGE("There are not enough tokens in BD addr");
+                                            ignore_boot_prop = TRUE;
+                                            break;
+                                        }
+                                        local_bd_addr_from_prop[5-i] = strtol(tok, NULL, 16);
+                                        tok = strtok(NULL, ":");
+                                        i++;
+                                    }
+                                    if (i == 6 && !ignore_boot_prop) {
+                                        ALOGV("Valid BD address read from prop");
+                                        memcpy(vnd_local_bd_addr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
+                                        ignore_boot_prop = FALSE;
+                                    } else {
+                                        ALOGE("There are not enough tokens in BD addr");
+                                        ignore_boot_prop = TRUE;
+                                    }
+                                }
+                                else {
+                                     ALOGE("BD address boot property not set");
+                                     ignore_boot_prop = TRUE;
+                                }
+#endif //READ_BT_ADDR_FROM_PROP
+                                    /* Always read BD address from NV file */
+                                if(ignore_boot_prop && !bt_vendor_nv_read(1, q->bdaddr))
+                                {
+                                   /* Since the BD address is configured in boot time We should not be here */
+                                   ALOGI("Failed to read BD address. Use the one from bluedroid stack/ftm");
+                                }
+                                if(rome_soc_init(fd, (char*)q->bdaddr)<0) {
+                                    retval = -1;
+                                } else {
+                                    ALOGV("rome_soc_init is completed");
+                                    property_set("wc_transport.soc_initialized", "1");
+                                    skip_init = false;
+                                }
+                            }
+                            if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
+                                ALOGE("%s: Failed to set property", __FUNCTION__);
+                            }
+
+                            property_set("wc_transport.clean_up","0");
+                            if (retval != -1) {
+
+                                retval = start_hci_filter();
+                                if (retval < 0) {
+                                    ALOGE("%s: WCNSS_FILTER wouldn't have started in time\n", __func__);
+                                } else {
+#ifdef ENABLE_ANT
+                                    if (is_ant_req) {
+                                        ALOGI("%s: connect to ant channel", __func__);
+                                        q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
+                                    }
+                                    else
+#endif
+                                    {
+                                        ALOGI("%s: connect to bt channel", __func__);
+                                        vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
+                                    }
+
+                                    if (fd_filter != -1) {
+                                        ALOGI("%s: received the socket fd: %d is_ant_req: %d is_fm_req: %d\n",
+                                                             __func__, fd_filter, is_ant_req,is_fm_req);
+                                        if((strcmp(emb_wp_mode, "true") == 0) && !is_ant_req && !is_fm_req) {
+                                             if (chipset_ver >= ROME_VER_3_0) {
+                                                /* get rome supported feature request */
+                                                ALOGE("%s: %x08 %0x", __FUNCTION__,chipset_ver, ROME_VER_3_0);
+                                                rome_get_addon_feature_list(fd_filter);
+                                            }
+                                        }
+                                        if (!skip_init) {
+                                            /*Skip if already sent*/
+                                            enable_controller_log(fd_filter, (is_ant_req || is_fm_req) );
+                                            skip_init = true;
+                                        }
+                                        for (idx=0; idx < CH_MAX; idx++)
+                                            (*fd_array)[idx] = fd_filter;
+                                            retval = 1;
+                                    }
+                                    else {
+                                        if (is_ant_req)
+                                            ALOGE("Unable to connect to ANT Server Socket!!!");
+                                        else
+                                            ALOGE("Unable to connect to BT Server Socket!!!");
+                                        retval = -1;
+                                    }
+                                }
+                            } else {
+                                if (q->soc_type == BT_SOC_ROME)
+                                    ALOGE("Failed to initialize ROME Controller!!!");
+                            }
+
+                            if (fd >= 0) {
+                                userial_clock_operation(fd, USERIAL_OP_CLK_OFF);
+                                 /*Close the UART port*/
+                                 close(fd);
+                            }
+                        }
+                        break;
+                    case BT_SOC_CHEROKEE:
+                        {
+                            property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
+                            retval = start_hci_filter();
+                            if (retval < 0) {
+                                ALOGE("WCNSS_FILTER wouldn't have started in time\n");
+
+                            } else {
+#ifdef ENABLE_ANT
+                                if (is_ant_req) {
+                                    ALOGI("%s: connect to ant channel", __func__);
+                                    q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
+                                }
+                                else
+#endif
+#ifdef FM_OVER_UART
+                                if (is_fm_req && (q->soc_type >=BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED)) {
+                                    ALOGI("%s: connect to fm channel", __func__);
+                                    q->fm_fd = fd_filter = connect_to_local_socket("fm_sock");
+                                }
+                                else
+#endif
+                                {
+                                    ALOGI("%s: connect to bt channel", __func__);
+                                    vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
+
+                                }
+                                if (fd_filter != -1) {
+                                    ALOGV("%s: received the socket fd: %d \n",
+                                                             __func__, fd_filter);
+
+                                    for (idx=0; idx < CH_MAX; idx++) {
+                                        (*fd_array)[idx] = fd_filter;
+                                    }
+                                    retval = 1;
+                                }
+                                else {
+#ifdef ENABLE_ANT
+                                    if (is_ant_req)
+                                        ALOGE("Unable to connect to ANT Server Socket!!!");
+                                    else
+#endif
+#ifdef FM_OVER_UART
+                                    if (is_fm_req)
+                                        ALOGE("Unable to connect to FM Server Socket!!!");
+                                    else
+#endif
+                                        ALOGE("Unable to connect to BT Server Socket!!!");
+                                    retval = -1;
+                                }
+                            }
+                        }
+                        break;
+                    default:
+                        ALOGE("Unknown soc_type: 0x%x", q->soc_type);
+                        break;
+                  }
+            } break;
+#ifdef ENABLE_ANT
+        case BT_VND_OP_ANT_USERIAL_CLOSE:
+            {
+                ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_CLOSE");
+                property_set("wc_transport.clean_up","1");
+                if (q->ant_fd != -1) {
+                    ALOGE("closing ant_fd");
+                    close(q->ant_fd);
+                    q->ant_fd = -1;
+                }
+            }
+            break;
+#endif
+#ifdef FM_OVER_UART
+        case BT_VND_OP_FM_USERIAL_CLOSE:
+            {
+                ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_CLOSE");
+                property_set("wc_transport.clean_up","1");
+                if (q->fm_fd != -1) {
+                    ALOGE("closing fm_fd");
+                    close(q->fm_fd);
+                    q->fm_fd = -1;
+                }
+                break;
+            }
+#endif
+        case BT_VND_OP_USERIAL_CLOSE:
+            {
+                ALOGI("bt-vendor : BT_VND_OP_USERIAL_CLOSE soc_type: %d", q->soc_type);
+                switch(q->soc_type)
+                {
+                    case BT_SOC_DEFAULT:
+                        bt_hci_deinit_transport(q->fd);
+                        break;
+                    case BT_SOC_ROME:
+                    case BT_SOC_AR3K:
+                    case BT_SOC_CHEROKEE:
+                    {
+                        property_set("wc_transport.clean_up","1");
+                        userial_vendor_close();
+                        break;
+                    }
+                    default:
+                        ALOGE("Unknown soc_type: 0x%x", q->soc_type);
+                        break;
+                }
+            }
+            break;
+
+        case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
+            {
+                if (!param) {
+                    ALOGE("opcode = %d: param is null", opcode_init);
+                    break;
+                }
+                uint32_t *timeout_ms = (uint32_t *) param;
+                *timeout_ms = 1000;
+            }
+
+            break;
+
+        case BT_VND_OP_LPM_SET_MODE:
+            if (q->soc_type == BT_SOC_AR3K) {
+                if (!param) {
+                    ALOGE("opcode = %d: param is null", opcode_init);
+                    break;
+                }
+                uint8_t *mode = (uint8_t *) param;
+
+                if (*mode) {
+                    lpm_set_ar3k(UPIO_LPM_MODE, UPIO_ASSERT, 0);
+                }
+                else {
+                    lpm_set_ar3k(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
+                }
+                q->cb->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
+            } else {
+                int lpm_result = BT_VND_OP_RESULT_SUCCESS;
+
+                property_get("persist.service.bdroid.lpmcfg", lpm_config, "all");
+                ALOGI("%s: property_get: persist.service.bdroid.lpmcfg: %s",
+                            __func__, lpm_config);
+
+                if (!strcmp(lpm_config, "all")) {
+                    // respond with success since we want to hold wake lock through LPM
+                    lpm_result = BT_VND_OP_RESULT_SUCCESS;
+                }
+                else {
+                    lpm_result = BT_VND_OP_RESULT_FAIL;
+                }
+
+                q->cb->lpm_cb(lpm_result);
+            }
+            break;
+
+        case BT_VND_OP_LPM_WAKE_SET_STATE: {
+            switch(q->soc_type) {
+            case BT_SOC_CHEROKEE:
+            case BT_SOC_ROME: {
+                if (!param) {
+                    ALOGE("opcode = %d: param is null", opcode_init);
+                    break;
+                }
+                uint8_t *state = (uint8_t *) param;
+                uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
+                            BT_VND_LPM_WAKE_ASSERT : BT_VND_LPM_WAKE_DEASSERT;
+
+                if (wake_assert == 0)
+                    ALOGV("ASSERT: Waking up BT-Device");
+                else if (wake_assert == 1)
+                    ALOGV("DEASSERT: Allowing BT-Device to Sleep");
+
+#ifdef QCOM_BT_SIBS_ENABLE
+                ALOGI("Invoking HCI H4 callback function");
+                q->cb->lpm_set_state_cb(wake_assert);
+#endif
+            }
+            break;
+            case BT_SOC_AR3K: {
+                if (!param) {
+                    ALOGE("opcode = %d: param is null", opcode_init);
+                    break;
+                }
+                uint8_t *state = (uint8_t *) param;
+                uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
+                                                UPIO_ASSERT : UPIO_DEASSERT;
+                lpm_set_ar3k(UPIO_BT_WAKE, wake_assert, 0);
+            }
+            case BT_SOC_DEFAULT:
+                break;
+            default:
+                ALOGE("Unknown soc_type: 0x%x", q->soc_type);
+                break;
+            }
+        }
+            break;
+        case BT_VND_OP_EPILOG: {
+#if (HW_NEED_END_WITH_HCI_RESET == FALSE)
+            q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
+#else
+                switch(q->soc_type)
+                {
+                  case BT_SOC_CHEROKEE:
+                  case BT_SOC_ROME:
+                       {
+                           char value[PROPERTY_VALUE_MAX] = {'\0'};
+                           property_get("wc_transport.hci_filter_status", value, "0");
+                           if(is_soc_initialized()&& (strcmp(value,"1") == 0))
+                           {
+                              __hw_epilog_process();
+                           }
+                           else
+                           {
+                                q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
+                           }
+                       }
+                       break;
+                  default:
+                       __hw_epilog_process();
+                       break;
+                }
+#endif
+            }
+            break;
+        case BT_VND_OP_GET_LINESPEED:
+            {
+                retval = -1;
+                if(!is_soc_initialized()) {
+                     ALOGE("BT_VND_OP_GET_LINESPEED: error"
+                         " - transport driver not initialized!");
+                     break;
+                }
+
+                switch(q->soc_type)
+                {
+                    case BT_SOC_CHEROKEE:
+                            retval = 3200000;
+                        break;
+                    case BT_SOC_ROME:
+                            retval = 3000000;
+                        break;
+                    default:
+                        retval = userial_vendor_get_baud();
+                        break;
+                 }
+                break;
+            }
+    }
+
+out:
+    ALOGV("--%s", __FUNCTION__);
+    return retval;
+}
+
+static int op(bt_vendor_opcode_t opcode, void *param)
+{
+    int ret;
+    ALOGV("++%s", __FUNCTION__);
+#ifdef BT_THREADLOCK_SAFE
+    pthread_mutex_lock(&q_lock);
+#endif
+    if (!q) {
+        ALOGE("op called with NULL context");
+        ret = -BT_STATUS_INVAL;
+        goto out;
+    }
+    ret = __op(opcode, param);
+out:
+#ifdef BT_THREADLOCK_SAFE
+    pthread_mutex_unlock(&q_lock);
+#endif
+    ALOGV("--%s ret = 0x%x", __FUNCTION__, ret);
+    return ret;
+}
+
+static void ssr_cleanup(int reason)
+{
+    int pwr_state = BT_VND_PWR_OFF;
+    int ret;
+    unsigned char trig_ssr = 0xEE;
+
+    ALOGI("++%s", __FUNCTION__);
+
+    pthread_mutex_lock(&q_lock);
+    if (!q) {
+        ALOGE("ssr_cleanup called with NULL context");
+        goto out;
+    }
+    if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
+        ALOGE("Failed to set property");
+    }
+
+    if (q->soc_type >= BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED) {
+#ifdef ENABLE_ANT
+        /*Indicate to filter by sending special byte */
+        if (reason == CMD_TIMEOUT) {
+            trig_ssr = 0xEE;
+            ret = write (vnd_userial.fd, &trig_ssr, 1);
+            ALOGI("Trig_ssr is being sent to BT socket, ret %d err %s",
+                        ret, strerror(errno));
+
+            if (is_debug_force_special_bytes()) {
+                /*
+                 * Then we should send special byte to crash SOC in
+                 * WCNSS_Filter, so we do not need to power off UART here.
+                 */
+                goto out;
+            }
+        }
+
+        /* Close both ANT channel */
+        __op(BT_VND_OP_ANT_USERIAL_CLOSE, NULL);
+#endif
+        /* Close both BT channel */
+        __op(BT_VND_OP_USERIAL_CLOSE, NULL);
+
+#ifdef FM_OVER_UART
+        __op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
+#endif
+        /*CTRL OFF twice to make sure hw
+         * turns off*/
+#ifdef ENABLE_ANT
+        __op(BT_VND_OP_POWER_CTRL, &pwr_state);
+#endif
+    }
+    /*Generally switching of chip should be enough*/
+    __op(BT_VND_OP_POWER_CTRL, &pwr_state);
+
+out:
+    pthread_mutex_unlock(&q_lock);
+    ALOGI("--%s", __FUNCTION__);
+}
+
+/** Closes the interface */
+static void cleanup(void)
+{
+    ALOGI("cleanup");
+
+    pthread_mutex_lock(&q_lock);
+    q->cb = NULL;
+    free(q);
+    q = NULL;
+    pthread_mutex_unlock(&q_lock);
+
+#ifdef WIFI_BT_STATUS_SYNC
+    isInit = 0;
+#endif /* WIFI_BT_STATUS_SYNC */
+}
+
+/* Check for one of the cients ANT/BT patch download is already in
+** progress if yes wait till complete
+*/
+void wait_for_patch_download(bool is_ant_req) {
+    ALOGV("%s:", __FUNCTION__);
+    char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
+    while (1) {
+        property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
+
+        if(is_ant_req && !(strcmp(inProgress,"bt"))) {
+           //ANT request, wait for BT to finish
+           usleep(50000);
+        }
+        else if(!is_ant_req && !(strcmp(inProgress,"ant"))) {
+          //BT request, wait for ANT to finish
+           usleep(50000);
+        }
+        else {
+           ALOGI("%s: patch download completed", __FUNCTION__);
+           break;
+        }
+    }
+}
+
+bool is_download_progress () {
+    char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
+    bool retval = false;
+
+    ALOGV("%s:", __FUNCTION__);
+
+    if ((q->soc_type = get_bt_soc_type()) < 0) {
+        ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__);
+        return -1;
+    }
+
+    switch(q->soc_type)
+    {
+        case BT_SOC_ROME:
+            ALOGI("%s: ROME case", __func__);
+            property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
+            if(strcmp(inProgress,"null") == 0) {
+                retval = false;
+            } else {
+                 retval = true;
+            }
+            break;
+        case BT_SOC_CHEROKEE:
+            ALOGI("%s: CHEROKEE case", __func__);
+            break;
+        case BT_SOC_DEFAULT:
+            break;
+        default:
+            ALOGE("Unknown btSocType: 0x%x", q->soc_type);
+            break;
+    }
+    return retval;
+}
+
+static bool is_debug_force_special_bytes() {
+    int ret = 0;
+    char value[PROPERTY_VALUE_MAX] = {'\0'};
+    bool enabled = false;
+#ifdef ENABLE_DBG_FLAGS
+    enabled = true;
+#endif
+
+    ret = property_get("wc_transport.force_special_byte", value, NULL);
+
+    if (ret) {
+        enabled = (strcmp(value, "false") ==0) ? false : true;
+        ALOGV("%s: wc_transport.force_special_byte: %s, enabled: %d ",
+            __func__, value, enabled);
+    }
+
+    return enabled;
+}
+
+// Entry point of DLib
+/* Remove 'ssr_cleanup' because it's not defined in 'bt_vendor_interface_t'. */
+const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
+    sizeof(bt_vendor_interface_t),
+    init,
+    op,
+    cleanup
+};
diff --git a/sdm845/libbt-vendor/src/hardware.c b/sdm845/libbt-vendor/src/hardware.c
new file mode 100644
index 0000000..90db801
--- /dev/null
+++ b/sdm845/libbt-vendor/src/hardware.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * 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_vendor"
+
+#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_qcom.h"
+#include <string.h>
+#define MAX_CNT_RETRY 100
+
+int hw_config(int nState)
+{
+    char *szState[] = {"true", "false"};
+    char *szReqSt = NULL;
+    char szBtSocStatus[PROPERTY_VALUE_MAX] = {'\0', };
+
+    if(nState == BT_VND_PWR_OFF)
+        szReqSt = szState[1];
+    else
+        szReqSt = szState[0];
+
+    if((property_get("bluetooth.status", szBtSocStatus, "") <= 0))
+    {
+       if(nState == BT_VND_PWR_ON ) {
+          ALOGW("Hw_config: First Time BT on after boot.Starting hciattach daemon BTStatus=%s",szBtSocStatus);
+          if (property_set("bluetooth.hciattach", szReqSt) < 0)
+          {
+              ALOGE("Hw_config: Property Setting fail");
+              return -1;
+          }
+       }
+    } else if( !(strncmp(szBtSocStatus, "on", strlen("on")))) {
+          //BTSOC is already on
+          ALOGW("Hw_config: nState = %d", nState);
+    } else {
+          ALOGW("Hw_config: trigerring hciattach");
+          if (property_set("bluetooth.hciattach", szReqSt) < 0)
+          {
+              ALOGE("Hw_config: Property Setting fail");
+              return -1;
+          }
+    }
+
+    return 0;
+}
+
+int readTrpState()
+{
+    char szBtStatus[PROPERTY_VALUE_MAX] = {0, };
+    if(property_get("bluetooth.status", szBtStatus, "") < 0){
+        ALOGE("Fail to get bluetooth status");
+        return FALSE;
+    }
+
+    if(!strncmp(szBtStatus, "on", strlen("on"))){
+        ALOGI("bluetooth status is on");
+        return TRUE;
+    }
+    return FALSE;
+}
+
+int is_hw_ready()
+{
+    int i=0;
+    char szStatus[10] = {0,};
+
+    for(i=MAX_CNT_RETRY; i>0; i--){
+       //TODO :: checking routine
+       if(readTrpState()==TRUE){
+           break;
+       }
+       usleep(50*1000);
+    }
+    return (i==0)? FALSE:TRUE;
+}
+
+#if (HW_NEED_END_WITH_HCI_RESET == TRUE)
+/*******************************************************************************
+**
+** Function         hw_epilog_cback
+**
+** Description      Callback function for Command Complete Events from HCI
+**                  commands sent in epilog process.
+**
+** Returns          None
+**
+*******************************************************************************/
+void hw_epilog_cback(void *p_mem)
+{
+    HC_BT_HDR *p_evt_buf = (HC_BT_HDR *) p_mem;
+    char        *p_name, *p_tmp;
+    uint8_t     *p, status;
+    uint16_t    opcode;
+
+    status = *((uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_STATUS_RET_BYTE);
+    p = (uint8_t *)(p_evt_buf + 1) + HCI_EVT_CMD_CMPL_OPCODE;
+    STREAM_TO_UINT16(opcode,p);
+
+    ALOGI("%s Opcode:0x%04X Status: %d", __FUNCTION__, opcode, status);
+
+#ifdef BT_THREADLOCK_SAFE
+    pthread_mutex_lock(&q_lock);
+#endif
+    if (!q) {
+        ALOGE("hw_epilog_cback called with NULL context");
+        goto out;
+    }
+    /* Must free the RX event buffer */
+    q->cb->dealloc(p_evt_buf);
+
+    /* Once epilog process is done, must call callback to notify caller */
+    q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
+out:
+#ifdef BT_THREADLOCK_SAFE
+    pthread_mutex_unlock(&q_lock);
+#endif
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         hw_epilog_process
+**
+** Description      Sample implementation of epilog process. This process is
+**                  called with q_lock held and q->cb is assumed to be valid.
+**
+** Returns          None
+**
+*******************************************************************************/
+void __hw_epilog_process(void)
+{
+    HC_BT_HDR  *p_buf = NULL;
+    uint8_t     *p;
+
+    ALOGI("hw_epilog_process");
+
+    /* Sending a HCI_RESET */
+    /* Must allocate command buffer via HC's alloc API */
+    p_buf = (HC_BT_HDR *) q->cb->alloc(BT_HC_HDR_SIZE + HCI_CMD_PREAMBLE_SIZE);
+    if (p_buf)
+    {
+        p_buf->event = MSG_STACK_TO_HC_HCI_CMD;
+        p_buf->offset = 0;
+        p_buf->layer_specific = 0;
+        p_buf->len = HCI_CMD_PREAMBLE_SIZE;
+
+        p = (uint8_t *) (p_buf + 1);
+        UINT16_TO_STREAM(p, HCI_RESET);
+        *p = 0; /* parameter length */
+
+        /* Send command via HC's xmit_cb API */
+        q->cb->xmit_cb(HCI_RESET, p_buf, hw_epilog_cback);
+    }
+    else
+    {
+        ALOGE("vendor lib epilog process aborted [no buffer]");
+        q->cb->epilog_cb(BT_VND_OP_RESULT_FAIL);
+    }
+}
+#endif // (HW_NEED_END_WITH_HCI_RESET == TRUE)
diff --git a/sdm845/libbt-vendor/src/hci_smd.c b/sdm845/libbt-vendor/src/hci_smd.c
new file mode 100644
index 0000000..7e5b16d
--- /dev/null
+++ b/sdm845/libbt-vendor/src/hci_smd.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * 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:      hci_smd.c
+ *
+ *  Description:   Contains vendor-specific userial functions
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_vendor"
+
+#include <utils/Log.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include "bt_vendor_qcom.h"
+#include "hci_smd.h"
+#include <string.h>
+#include <cutils/properties.h>
+
+/*****************************************************************************
+**   Macros & Constants
+*****************************************************************************/
+#define NUM_OF_DEVS 2
+static char *s_pszDevSmd[] = {
+    "/dev/smd3",
+    "/dev/smd2"
+};
+
+/******************************************************************************
+**  Externs
+******************************************************************************/
+extern int is_bt_ssr_hci;
+
+
+/*****************************************************************************
+**   Functions
+*****************************************************************************/
+
+int bt_hci_init_transport_id (int chId )
+{
+  struct termios   term;
+  int fd = -1;
+  int retry = 0;
+  char ssrvalue[92]= {'\0'};
+
+  ssrvalue[0] = '0';
+  if(chId >= 2 || chId <0)
+     return -1;
+
+  fd = open(s_pszDevSmd[chId], (O_RDWR | O_NOCTTY));
+
+  while ((-1 == fd) && (retry < 7)) {
+    ALOGE("init_transport: Cannot open %s: %s\n. Retry after 2 seconds",
+        s_pszDevSmd[chId], strerror(errno));
+    usleep(2000000);
+    fd = open(s_pszDevSmd[chId], (O_RDWR | O_NOCTTY));
+    retry++;
+  }
+
+  if (-1 == fd)
+  {
+    ALOGE("init_transport: Cannot open %s: %s\n",
+        s_pszDevSmd[chId], strerror(errno));
+    return -1;
+  }
+
+  /* Sleep (0.5sec) added giving time for the smd port to be successfully
+     opened internally. Currently successful return from open doesn't
+     ensure the smd port is successfully opened.
+     TODO: Following sleep to be removed once SMD port is successfully
+     opened immediately on return from the aforementioned open call */
+
+  property_get("bluetooth.isSSR", ssrvalue, "");
+
+  if(ssrvalue[0] == '1')
+  {
+      /*reset the SSR flag */
+      if(chId == 1)
+      {
+          if(property_set("bluetooth.isSSR", "0") < 0)
+          {
+              ALOGE("SSR: hci_smd.c:SSR case : error in setting up property new\n ");
+          }
+          else
+          {
+              ALOGE("SSR: hci_smd.c:SSR case : Reset the SSr Flag new\n ");
+          }
+      }
+      ALOGE("hci_smd.c:IN SSR sleep for 500 msec New \n");
+      usleep(500000);
+  }
+
+  if (tcflush(fd, TCIOFLUSH) < 0)
+  {
+    ALOGE("init_uart: Cannot flush %s\n", s_pszDevSmd[chId]);
+    close(fd);
+    return -1;
+  }
+
+  if (tcgetattr(fd, &term) < 0)
+  {
+    ALOGE("init_uart: Error while getting attributes\n");
+    close(fd);
+    return -1;
+  }
+
+  cfmakeraw(&term);
+
+  /* JN: Do I need to make flow control configurable, since 4020 cannot
+   * disable it?
+   */
+  term.c_cflag |= (CRTSCTS | CLOCAL);
+
+  if (tcsetattr(fd, TCSANOW, &term) < 0)
+  {
+    ALOGE("init_uart: Error while getting attributes\n");
+    close(fd);
+    return -1;
+  }
+
+  ALOGI("Done intiailizing UART\n");
+  return fd;
+}
+
+int bt_hci_init_transport(int *pFd)
+{
+  int i = 0;
+  int fd;
+  for(i=0; i < NUM_OF_DEVS; i++){
+    fd = bt_hci_init_transport_id(i);
+    if(fd < 0 ){
+      return -1;
+    }
+    pFd[i] = fd;
+   }
+   return 0;
+}
+
+int bt_hci_deinit_transport(int *pFd)
+{
+    close(pFd[0]);
+    close(pFd[1]);
+    return TRUE;
+}
diff --git a/sdm845/libbt-vendor/src/hci_uart.c b/sdm845/libbt-vendor/src/hci_uart.c
new file mode 100644
index 0000000..2aeace8
--- /dev/null
+++ b/sdm845/libbt-vendor/src/hci_uart.c
@@ -0,0 +1,526 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ * Copyright 2012 The Android Open Source Project
+ *
+ * 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_vendor"
+
+#include <utils/Log.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include "bt_vendor_qcom.h"
+#include "hci_uart.h"
+#include <string.h>
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+
+#ifndef VNDUSERIAL_DBG
+#define VNDUSERIAL_DBG TRUE
+#endif
+
+#if (VNDUSERIAL_DBG == TRUE)
+#define VNDUSERIALDBG(param, ...) {ALOGI(param, ## __VA_ARGS__);}
+#else
+#define VNDUSERIALDBG(param, ...) {}
+#endif
+
+#define RESERVED(p)  if(p) ALOGI( "%s: reserved param", __FUNCTION__);
+
+/******************************************************************************
+**  Global variables
+******************************************************************************/
+vnd_userial_cb_t vnd_userial;
+
+/*****************************************************************************
+**   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;
+}
+
+/*******************************************************************************
+**
+** Function        userial_to_baud_tcio
+**
+** Description     helper function converts TCIO baud rate into integer
+**
+** Returns         uint32_t
+**
+*******************************************************************************/
+int userial_tcio_baud_to_int(uint32_t baud)
+{
+    int baud_rate =0;
+
+    switch (baud)
+    {
+        case B600:
+            baud_rate = 600;
+            break;
+        case B1200:
+            baud_rate = 1200;
+            break;
+        case B9600:
+            baud_rate = 9600;
+            break;
+        case B19200:
+            baud_rate = 19200;
+            break;
+        case B57600:
+            baud_rate = 57600;
+            break;
+        case B115200:
+            baud_rate = 115200;
+            break;
+        case B230400:
+            baud_rate = 230400;
+            break;
+        case B460800:
+            baud_rate = 460800;
+            break;
+        case B921600:
+            baud_rate = 921600;
+            break;
+        case B1000000:
+            baud_rate = 1000000;
+            break;
+        case B2000000:
+            baud_rate = 2000000;
+            break;
+        case B3000000:
+            baud_rate = 3000000;
+            break;
+        case B4000000:
+            baud_rate = 4000000;
+            break;
+        default:
+            ALOGE( "%s: unsupported baud %d", __FUNCTION__, baud);
+            break;
+    }
+
+    ALOGI( "%s: Current Baudrate = %d bps", __FUNCTION__, baud_rate);
+    return baud_rate;
+}
+
+
+#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", BT_HS_UART_DEVICE);
+}
+
+/*******************************************************************************
+**
+** 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|O_NOCTTY)) == -1)
+    {
+        ALOGE("userial vendor open: unable to open %s: %s(%d)", vnd_userial.port_name,
+            strerror(errno), errno);
+        return -1;
+    }
+
+    tcflush(vnd_userial.fd, TCIOFLUSH);
+
+    tcgetattr(vnd_userial.fd, &vnd_userial.termios);
+    cfmakeraw(&vnd_userial.termios);
+
+    /* Set UART Control Modes */
+    vnd_userial.termios.c_cflag |= CLOCAL;
+    vnd_userial.termios.c_cflag |= (CRTSCTS | stop_bits);
+
+    tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+
+    /* set input/output baudrate */
+    cfsetospeed(&vnd_userial.termios, baud);
+    cfsetispeed(&vnd_userial.termios, baud);
+    tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+
+    tcflush(vnd_userial.fd, TCIOFLUSH);
+
+#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;
+
+    VNDUSERIALDBG("## userial_vendor_set_baud: %d", userial_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, TCSADRAIN, &vnd_userial.termios); /* don't change speed until last write done */
+//    tcflush(vnd_userial.fd, TCIOFLUSH);
+}
+
+/*******************************************************************************
+**
+** Function        userial_vendor_get_baud
+**
+** Description     Get current baud rate
+**
+** Returns         int
+**
+*******************************************************************************/
+int userial_vendor_get_baud(void)
+{
+    if (vnd_userial.fd == -1)
+    {
+        ALOGE( "%s: uart port(%s) has not been opened", __FUNCTION__, BT_HS_UART_DEVICE );
+        return -1;
+    }
+
+    return userial_tcio_baud_to_int(cfgetispeed(&vnd_userial.termios));
+}
+
+/*******************************************************************************
+**
+** Function        userial_vendor_ioctl
+**
+** Description     ioctl inteface
+**
+** Returns         None
+**
+*******************************************************************************/
+int userial_vendor_ioctl(userial_vendor_ioctl_op_t op, int *p_data)
+{
+    int err = -1;
+
+    switch(op)
+    {
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+        case USERIAL_OP_ASSERT_BT_WAKE:
+            VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##");
+            err = 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 ##");
+            err = ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL);
+            break;
+
+        case USERIAL_OP_GET_BT_WAKE_STATE:
+            err = ioctl(vnd_userial.fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data);
+            break;
+#endif  //  (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+        case USERIAL_OP_FLOW_ON:
+            ALOGI("## userial_vendor_ioctl: UART Flow On ");
+            *p_data |=TIOCM_RTS;
+            err = ioctl(vnd_userial.fd, TIOCMSET, p_data);
+            break;
+
+        case USERIAL_OP_FLOW_OFF:
+            ALOGI("## userial_vendor_ioctl: UART Flow Off ");
+            ioctl(vnd_userial.fd, TIOCMGET, p_data);
+            *p_data &= ~TIOCM_RTS;
+            err = ioctl(vnd_userial.fd, TIOCMSET, p_data);
+            break;
+
+        default:
+            break;
+    }
+
+    return err;
+}
+
+/*******************************************************************************
+**
+** 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)
+{
+    RESERVED(p_conf_name);
+    RESERVED(param);
+    strlcpy(vnd_userial.port_name, p_conf_value, VND_PORT_NAME_MAXLEN);
+
+    return 0;
+}
+
+/*******************************************************************************
+**
+** Function        read_hci_event
+**
+** Description     Read HCI event during vendor initialization
+**
+** Returns         int: size to read
+**
+*******************************************************************************/
+int read_hci_event(int fd, unsigned char* buf, int size)
+{
+    int remain, r;
+    int count = 0;
+
+    if (size <= 0) {
+        ALOGE("Invalid size arguement!");
+        return -1;
+    }
+
+    ALOGI("%s: Wait for Command Compete Event from SOC", __FUNCTION__);
+
+    /* The first byte identifies the packet type. For HCI event packets, it
+     * should be 0x04, so we read until we get to the 0x04. */
+    while (1) {
+            r = read(fd, buf, 1);
+            if (r <= 0)
+                    return -1;
+            if (buf[0] == 0x04)
+                    break;
+    }
+    count++;
+
+    /* The next two bytes are the event code and parameter total length. */
+    while (count < 3) {
+            r = read(fd, buf + count, 3 - count);
+            if (r <= 0)
+                    return -1;
+            count += r;
+    }
+
+    /* Now we read the parameters. */
+    if (buf[2] < (size - 3))
+            remain = buf[2];
+    else
+            remain = size - 3;
+
+    while ((count - 3) < remain) {
+            r = read(fd, buf + count, remain - (count - 3));
+            if (r <= 0)
+                    return -1;
+            count += r;
+    }
+    return count;
+}
+
+int userial_clock_operation(int fd, int cmd)
+{
+    int ret = 0;
+
+    switch (cmd)
+    {
+        case USERIAL_OP_CLK_ON:
+        case USERIAL_OP_CLK_OFF:
+             ioctl(fd, cmd);
+             break;
+        case USERIAL_OP_CLK_STATE:
+             ret = ioctl(fd, cmd);
+             break;
+    }
+
+    return ret;
+}
diff --git a/sdm845/libbt-vendor/src/hw_ar3k.c b/sdm845/libbt-vendor/src/hw_ar3k.c
new file mode 100644
index 0000000..cc54db8
--- /dev/null
+++ b/sdm845/libbt-vendor/src/hw_ar3k.c
@@ -0,0 +1,1488 @@
+/*
+ *
+ *  Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  Not a Contribution.
+ *
+ *  Copyright 2012 The Android Open Source Project
+ *
+ *  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:      hw_ar3k.c
+ *
+ *  Description:   Contains controller-specific functions, like
+ *                      firmware patch download
+ *                      low power mode operations
+ *
+ ******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LOG_TAG "bt_vendor"
+
+#include <sys/socket.h>
+#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 <termios.h>
+#include <string.h>
+
+#include "bt_hci_bdroid.h"
+#include "bt_vendor_qcom.h"
+#include "hci_uart.h"
+#include "hw_ar3k.h"
+
+/******************************************************************************
+**  Variables
+******************************************************************************/
+int cbstat = 0;
+#define PATCH_LOC_STRING_LEN   8
+char ARbyte[3];
+char ARptr[MAX_PATCH_CMD + 1];
+int byte_cnt;
+int patch_count = 0;
+char patch_loc[PATCH_LOC_STRING_LEN + 1];
+int PSCounter=0;
+
+uint32_t dev_type = 0;
+uint32_t rom_version = 0;
+uint32_t build_version = 0;
+
+char patch_file[PATH_MAX];
+char ps_file[PATH_MAX];
+FILE *stream;
+int tag_count=0;
+
+/* for friendly debugging outpout string */
+static char *lpm_mode[] = {
+    "UNKNOWN",
+    "disabled",
+    "enabled"
+};
+
+static char *lpm_state[] = {
+    "UNKNOWN",
+    "de-asserted",
+    "asserted"
+};
+
+static uint8_t upio_state[UPIO_MAX_COUNT];
+struct ps_cfg_entry ps_list[MAX_TAGS];
+
+#define PS_EVENT_LEN 100
+
+#ifdef __cplusplus
+}
+#endif
+
+#define RESERVED(p)  if(p) ALOGI( "%s: reserved param", __FUNCTION__);
+
+/*****************************************************************************
+**   Functions
+*****************************************************************************/
+
+int is_bt_soc_ath() {
+    int ret = 0;
+    char bt_soc_type[PROPERTY_VALUE_MAX];
+    ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL);
+    if (ret != 0) {
+        ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type);
+        if (!strncasecmp(bt_soc_type, "ath3k", sizeof("ath3k")))
+            return 1;
+    } else {
+        ALOGI("qcom.bluetooth.soc not set, so using default.\n");
+    }
+
+    return 0;
+}
+
+/*
+ * Send HCI command and wait for command complete event.
+ * The event buffer has to be freed by the caller.
+ */
+
+static int send_hci_cmd_sync(int dev, uint8_t *cmd, int len, uint8_t **event)
+{
+    int err;
+    uint8_t *hci_event;
+    uint8_t pkt_type = HCI_COMMAND_PKT;
+
+    if (len == 0)
+    return len;
+
+    if (write(dev, &pkt_type, 1) != 1)
+        return -EILSEQ;
+    if (write(dev, (unsigned char *)cmd, len) != len)
+        return -EILSEQ;
+
+    hci_event = (uint8_t *)malloc(PS_EVENT_LEN);
+    if (!hci_event)
+        return -ENOMEM;
+
+    err = read_hci_event(dev, (unsigned char *)hci_event, PS_EVENT_LEN);
+    if (err > 0) {
+        *event = hci_event;
+    } else {
+        free(hci_event);
+        return -EILSEQ;
+    }
+
+    return len;
+}
+
+static void convert_bdaddr(char *str_bdaddr, char *bdaddr)
+{
+    char bdbyte[3];
+    char *str_byte = str_bdaddr;
+    int i, j;
+    int colon_present = 0;
+
+    if (strstr(str_bdaddr, ":"))
+        colon_present = 1;
+
+    bdbyte[2] = '\0';
+
+    /* Reverse the BDADDR to LSB first */
+    for (i = 0, j = 5; i < 6; i++, j--) {
+        bdbyte[0] = str_byte[0];
+        bdbyte[1] = str_byte[1];
+        bdaddr[j] = strtol(bdbyte, NULL, 16);
+
+        if (colon_present == 1)
+            str_byte += 3;
+        else
+            str_byte += 2;
+    }
+}
+
+static int uart_speed(int s)
+{
+    switch (s) {
+        case 9600:
+            return B9600;
+        case 19200:
+            return B19200;
+        case 38400:
+            return B38400;
+        case 57600:
+            return B57600;
+        case 115200:
+            return B115200;
+        case 230400:
+            return B230400;
+        case 460800:
+            return B460800;
+        case 500000:
+            return B500000;
+        case 576000:
+            return B576000;
+        case 921600:
+            return B921600;
+        case 1000000:
+            return B1000000;
+        case 1152000:
+            return B1152000;
+        case 1500000:
+            return B1500000;
+        case 2000000:
+            return B2000000;
+#ifdef B2500000
+        case 2500000:
+            return B2500000;
+#endif
+#ifdef B3000000
+        case 3000000:
+            return B3000000;
+#endif
+#ifdef B3500000
+        case 3500000:
+            return B3500000;
+#endif
+#ifdef B4000000
+        case 4000000:
+            return B4000000;
+#endif
+        default:
+            return B57600;
+    }
+}
+
+int set_speed(int fd, struct termios *ti, int speed)
+{
+    if (cfsetospeed(ti, uart_speed(speed)) < 0)
+        return -errno;
+
+    if (cfsetispeed(ti, uart_speed(speed)) < 0)
+        return -errno;
+
+    if (tcsetattr(fd, TCSANOW, ti) < 0)
+        return -errno;
+
+    return 0;
+}
+
+static void load_hci_ps_hdr(uint8_t *cmd, uint8_t ps_op, int len, int index)
+{
+    hci_command_hdr *ch = (void *)cmd;
+
+    ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+        HCI_PS_CMD_OCF));
+    ch->plen = len + PS_HDR_LEN;
+    cmd += HCI_COMMAND_HDR_SIZE;
+
+    cmd[0] = ps_op;
+    cmd[1] = index;
+    cmd[2] = index >> 8;
+    cmd[3] = len;
+}
+
+
+static int read_ps_event(uint8_t *event, uint16_t ocf)
+{
+    hci_event_hdr *eh;
+    uint16_t opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, ocf));
+
+    event++;
+
+    eh = (void *)event;
+    event += HCI_EVENT_HDR_SIZE;
+
+    if (eh->evt == EVT_CMD_COMPLETE) {
+        evt_cmd_complete *cc = (void *)event;
+
+        event += EVT_CMD_COMPLETE_SIZE;
+
+        if (cc->opcode == opcode && event[0] == HCI_EV_SUCCESS)
+            return 0;
+        else
+            return -EILSEQ;
+    }
+
+    return -EILSEQ;
+}
+
+#define PS_WRITE           1
+#define PS_RESET           2
+#define WRITE_PATCH        8
+#define ENABLE_PATCH       11
+
+#define HCI_PS_CMD_HDR_LEN 7
+
+static int write_cmd(int fd, uint8_t *buffer, int len)
+{
+    uint8_t *event;
+    int err;
+
+    err = send_hci_cmd_sync(fd, buffer, len, &event);
+    if (err < 0)
+        return err;
+
+    err = read_ps_event(event, HCI_PS_CMD_OCF);
+
+    free(event);
+
+    return err;
+}
+
+#define PS_RESET_PARAM_LEN 6
+#define PS_RESET_CMD_LEN   (HCI_PS_CMD_HDR_LEN + PS_RESET_PARAM_LEN)
+
+#define PS_ID_MASK         0xFF
+
+/* Sends PS commands using vendor specficic HCI commands */
+static int write_ps_cmd(int fd, uint8_t opcode, uint32_t ps_param)
+{
+    uint8_t cmd[HCI_MAX_CMD_SIZE];
+    uint32_t i;
+
+    switch (opcode) {
+        case ENABLE_PATCH:
+            load_hci_ps_hdr(cmd, opcode, 0, 0x00);
+
+            if (write_cmd(fd, cmd, HCI_PS_CMD_HDR_LEN) < 0)
+                return -EILSEQ;
+            break;
+
+        case PS_RESET:
+            load_hci_ps_hdr(cmd, opcode, PS_RESET_PARAM_LEN, 0x00);
+
+            cmd[7] = 0x00;
+            cmd[PS_RESET_CMD_LEN - 2] = ps_param & PS_ID_MASK;
+            cmd[PS_RESET_CMD_LEN - 1] = (ps_param >> 8) & PS_ID_MASK;
+
+            if (write_cmd(fd, cmd, PS_RESET_CMD_LEN) < 0)
+                return -EILSEQ;
+            break;
+
+        case PS_WRITE:
+            for (i = 0; i < ps_param; i++) {
+                load_hci_ps_hdr(cmd, opcode, ps_list[i].len,
+                ps_list[i].id);
+
+                memcpy(&cmd[HCI_PS_CMD_HDR_LEN], ps_list[i].data,
+                ps_list[i].len);
+
+                if (write_cmd(fd, cmd, ps_list[i].len +
+                    HCI_PS_CMD_HDR_LEN) < 0)
+                    return -EILSEQ;
+            }
+            break;
+    }
+
+    return 0;
+}
+
+#define PS_ASIC_FILE    "PS_ASIC.pst"
+#define PS_FPGA_FILE    "PS_FPGA.pst"
+#define MAXPATHLEN  4096
+static void get_ps_file_name(uint32_t devtype, uint32_t rom_version,char *path)
+{
+    char *filename;
+
+    if (devtype == 0xdeadc0de)
+        filename = PS_ASIC_FILE;
+    else
+        filename = PS_FPGA_FILE;
+
+    snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, filename);
+}
+
+#define PATCH_FILE        "RamPatch.txt"
+#define FPGA_ROM_VERSION  0x99999999
+#define ROM_DEV_TYPE      0xdeadc0de
+
+static void get_patch_file_name(uint32_t dev_type, uint32_t rom_version,
+    uint32_t build_version, char *path)
+{
+    if (rom_version == FPGA_ROM_VERSION && dev_type != ROM_DEV_TYPE
+            &&dev_type != 0 && build_version == 1)
+        path[0] = '\0';
+    else
+        snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, PATCH_FILE);
+}
+
+static int set_cntrlr_baud(int fd, int speed)
+{
+    int baud;
+    struct timespec tm = { 0, 500000};
+    unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE];
+    unsigned char *ptr = cmd + 1;
+    hci_command_hdr *ch = (void *)ptr;
+
+    cmd[0] = HCI_COMMAND_PKT;
+
+    /* set controller baud rate to user specified value */
+    ptr = cmd + 1;
+    ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+    HCI_CHG_BAUD_CMD_OCF));
+    ch->plen = 2;
+    ptr += HCI_COMMAND_HDR_SIZE;
+
+    baud = speed/100;
+    ptr[0] = (char)baud;
+    ptr[1] = (char)(baud >> 8);
+
+    if (write(fd, cmd, WRITE_BAUD_CMD_LEN) != WRITE_BAUD_CMD_LEN) {
+        ALOGI("Failed to write change baud rate command");
+        return -ETIMEDOUT;
+    }
+
+    nanosleep(&tm, NULL);
+
+    if (read_hci_event(fd, rsp, sizeof(rsp)) < 0)
+        return -ETIMEDOUT;
+
+    return 0;
+}
+
+#define PS_UNDEF   0
+#define PS_ID      1
+#define PS_LEN     2
+#define PS_DATA    3
+
+#define PS_MAX_LEN         500
+#define LINE_SIZE_MAX      (PS_MAX_LEN * 2)
+#define ENTRY_PER_LINE     16
+
+#define __check_comment(buf) (((buf)[0] == '/') && ((buf)[1] == '/'))
+#define __skip_space(str)      while (*(str) == ' ') ((str)++)
+
+
+#define __is_delim(ch) ((ch) == ':')
+#define MAX_PREAMBLE_LEN 4
+
+/* Parse PS entry preamble of format [X:X] for main type and subtype */
+static int get_ps_type(char *ptr, int index, char *type, char *sub_type)
+{
+    int i;
+    int delim = FALSE;
+
+    if (index > MAX_PREAMBLE_LEN)
+        return -EILSEQ;
+
+    for (i = 1; i < index; i++) {
+        if (__is_delim(ptr[i])) {
+            delim = TRUE;
+            continue;
+        }
+
+        if (isalpha(ptr[i])) {
+            if (delim == FALSE)
+                (*type) = toupper(ptr[i]);
+            else
+                (*sub_type)	= toupper(ptr[i]);
+        }
+    }
+
+    return 0;
+}
+
+#define ARRAY   'A'
+#define STRING  'S'
+#define DECIMAL 'D'
+#define BINARY  'B'
+
+#define PS_HEX           0
+#define PS_DEC           1
+
+static int get_input_format(char *buf, struct ps_entry_type *format)
+{
+    char *ptr = NULL;
+    char type = '\0';
+    char sub_type = '\0';
+
+    format->type = PS_HEX;
+    format->array = TRUE;
+
+    if (strstr(buf, "[") != buf)
+        return 0;
+
+    ptr = strstr(buf, "]");
+    if (!ptr)
+        return -EILSEQ;
+
+    if (get_ps_type(buf, ptr - buf, &type, &sub_type) < 0)
+        return -EILSEQ;
+
+    /* Check is data type is of array */
+    if (type == ARRAY || sub_type == ARRAY)
+        format->array = TRUE;
+
+    if (type == STRING || sub_type == STRING)
+        format->array = FALSE;
+
+    if (type == DECIMAL || type == BINARY)
+        format->type = PS_DEC;
+    else
+        format->type = PS_HEX;
+
+    return 0;
+}
+
+
+
+#define UNDEFINED 0xFFFF
+
+static unsigned int read_data_in_section(char *buf, struct ps_entry_type type)
+{
+    char *ptr = buf;
+
+    if (!buf)
+        return UNDEFINED;
+
+    if (buf == strstr(buf, "[")) {
+        ptr = strstr(buf, "]");
+        if (!ptr)
+            return UNDEFINED;
+
+        ptr++;
+    }
+
+    if (type.type == PS_HEX && type.array != TRUE)
+        return strtol(ptr, NULL, 16);
+
+    return UNDEFINED;
+}
+
+
+/* Read PS entries as string, convert and add to Hex array */
+static void update_tag_data(struct ps_cfg_entry *tag,
+    struct tag_info *info, const char *ptr)
+{
+    char buf[3];
+
+    buf[2] = '\0';
+
+    strlcpy(buf, &ptr[info->char_cnt],sizeof(buf));
+    tag->data[info->byte_count] = strtol(buf, NULL, 16);
+    info->char_cnt += 3;
+    info->byte_count++;
+
+    strlcpy(buf, &ptr[info->char_cnt], sizeof(buf));
+    tag->data[info->byte_count] = strtol(buf, NULL, 16);
+    info->char_cnt += 3;
+    info->byte_count++;
+}
+
+static inline int update_char_count(const char *buf)
+{
+    char *end_ptr;
+
+    if (strstr(buf, "[") == buf) {
+        end_ptr = strstr(buf, "]");
+        if (!end_ptr)
+            return 0;
+        else
+            return(end_ptr - buf) +	1;
+    }
+
+    return 0;
+}
+
+#define PS_HEX           0
+#define PS_DEC           1
+
+static int ath_parse_ps(FILE *stream)
+{
+    char buf[LINE_SIZE_MAX + 1];
+    char *ptr;
+    uint8_t tag_cnt = 0;
+    int16_t byte_count = 0;
+    struct ps_entry_type format;
+    struct tag_info status = { 0, 0, 0, 0};
+
+    do {
+        int read_count;
+        struct ps_cfg_entry *tag;
+
+        ptr = fgets(buf, LINE_SIZE_MAX, stream);
+        if (!ptr)
+            break;
+
+        __skip_space(ptr);
+        if (__check_comment(ptr))
+            continue;
+
+        /* Lines with a '#' will be followed by new PS entry */
+        if (ptr == strstr(ptr, "#")) {
+            if (status.section != PS_UNDEF) {
+                return -EILSEQ;
+            } else {
+                status.section = PS_ID;
+                continue;
+            }
+        }
+
+        tag = &ps_list[tag_cnt];
+
+        switch (status.section) {
+            case PS_ID:
+                if (get_input_format(ptr, &format) < 0)
+                    return -EILSEQ;
+
+                tag->id = read_data_in_section(ptr, format);
+                status.section = PS_LEN;
+                break;
+
+            case PS_LEN:
+                if (get_input_format(ptr, &format) < 0)
+                    return -EILSEQ;
+
+                byte_count = read_data_in_section(ptr, format);
+                if (byte_count > PS_MAX_LEN)
+                    return -EILSEQ;
+
+                tag->len = byte_count;
+                tag->data = (uint8_t *)malloc(byte_count);
+
+                status.section = PS_DATA;
+                status.line_count = 0;
+                break;
+
+            case PS_DATA:
+            if (status.line_count == 0)
+                if (get_input_format(ptr, &format) < 0)
+                    return -EILSEQ;
+
+            __skip_space(ptr);
+
+            status.char_cnt = update_char_count(ptr);
+
+            read_count = (byte_count > ENTRY_PER_LINE) ?
+            ENTRY_PER_LINE : byte_count;
+
+            if (format.type == PS_HEX && format.array == TRUE) {
+                while (read_count > 0) {
+                    update_tag_data(tag, &status, ptr);
+                    read_count -= 2;
+                }
+
+                if (byte_count > ENTRY_PER_LINE)
+                    byte_count -= ENTRY_PER_LINE;
+                else
+                    byte_count = 0;
+            }
+
+            status.line_count++;
+
+            if (byte_count == 0)
+                memset(&status, 0x00, sizeof(struct tag_info));
+
+            if (status.section == PS_UNDEF)
+                tag_cnt++;
+
+            if (tag_cnt == MAX_TAGS)
+                return -EILSEQ;
+            break;
+        }
+    } while (ptr);
+
+    return tag_cnt;
+}
+
+#define PS_RAM_SIZE 2048
+
+static int ps_config_download(int fd, int tag_count)
+{
+    if (write_ps_cmd(fd, PS_RESET, PS_RAM_SIZE) < 0)
+        return -1;
+
+    if (tag_count > 0)
+        if (write_ps_cmd(fd, PS_WRITE, tag_count) < 0)
+            return -1;
+    return 0;
+}
+
+static int write_bdaddr(int pConfig, char *bdaddr)
+{
+    uint8_t *event;
+    int err;
+    uint8_t cmd[13];
+    uint8_t *ptr = cmd;
+    hci_command_hdr *ch = (void *)cmd;
+
+    memset(cmd, 0, sizeof(cmd));
+
+    ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+        HCI_PS_CMD_OCF));
+    ch->plen = 10;
+    ptr += HCI_COMMAND_HDR_SIZE;
+
+    ptr[0] = 0x01;
+    ptr[1] = 0x01;
+    ptr[2] = 0x00;
+    ptr[3] = 0x06;
+
+    convert_bdaddr(bdaddr, (char *)&ptr[4]);
+
+    err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event);
+    if (err < 0)
+        return err;
+
+    err = read_ps_event(event, HCI_PS_CMD_OCF);
+
+    free(event);
+
+    return err;
+}
+
+static void write_bdaddr_from_file(int rom_version, int fd)
+{
+    FILE *stream;
+    char bdaddr[PATH_MAX];
+    char bdaddr_file[PATH_MAX];
+
+    snprintf(bdaddr_file, MAXPATHLEN, "%s%x/%s",
+    FW_PATH, rom_version, BDADDR_FILE);
+
+    stream = fopen(bdaddr_file, "r");
+    if (!stream)
+       return;
+
+    if (fgets(bdaddr, PATH_MAX - 1, stream))
+        write_bdaddr(fd, bdaddr);
+
+    fclose(stream);
+}
+
+#define HCI_EVT_CMD_CMPL_OPCODE                 3
+#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE        5
+
+void baswap(bdaddr_t *dst, const bdaddr_t *src)
+{
+    register unsigned char *d = (unsigned char *) dst;
+    register const unsigned char *s = (const unsigned char *) src;
+    register int i;
+    for (i = 0; i < 6; i++)
+        d[i] = s[5-i];
+}
+
+
+int str2ba(const char *str, bdaddr_t *ba)
+{
+    uint8_t b[6];
+    const char *ptr = str;
+    int i;
+
+    for (i = 0; i < 6; i++) {
+        b[i] = (uint8_t) strtol(ptr, NULL, 16);
+        ptr = strchr(ptr, ':');
+        if (i != 5 && !ptr)
+            ptr = ":00:00:00:00:00";
+        ptr++;
+    }
+    baswap(ba, (bdaddr_t *) b);
+    return 0;
+}
+
+#define DEV_REGISTER      0x4FFC
+#define GET_DEV_TYPE_OCF  0x05
+
+static int get_device_type(int dev, uint32_t *code)
+{
+    uint8_t cmd[8] = {0};
+    uint8_t *event;
+    uint32_t reg;
+    int err;
+    uint8_t *ptr = cmd;
+    hci_command_hdr *ch = (void *)cmd;
+
+    ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+        GET_DEV_TYPE_OCF));
+    ch->plen = 5;
+    ptr += HCI_COMMAND_HDR_SIZE;
+
+    ptr[0] = (uint8_t)DEV_REGISTER;
+    ptr[1] = (uint8_t)DEV_REGISTER >> 8;
+    ptr[2] = (uint8_t)DEV_REGISTER >> 16;
+    ptr[3] = (uint8_t)DEV_REGISTER >> 24;
+    ptr[4] = 0x04;
+
+    err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event);
+    if (err < 0)
+        return err;
+
+    err = read_ps_event(event, GET_DEV_TYPE_OCF);
+    if (err < 0)
+        goto cleanup;
+
+    reg = event[10];
+    reg = (reg << 8) | event[9];
+    reg = (reg << 8) | event[8];
+    reg = (reg << 8) | event[7];
+    *code = reg;
+
+cleanup:
+    free(event);
+
+    return err;
+}
+
+#define GET_VERSION_OCF 0x1E
+
+static int read_ath3k_version(int pConfig, uint32_t *rom_version,
+    uint32_t *build_version)
+{
+    uint8_t cmd[3] = {0};
+    uint8_t *event;
+    int err;
+    int status;
+    hci_command_hdr *ch = (void *)cmd;
+
+    ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+    GET_VERSION_OCF));
+    ch->plen = 0;
+
+    err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event);
+    if (err < 0)
+        return err;
+
+    err = read_ps_event(event, GET_VERSION_OCF);
+    if (err < 0)
+        goto cleanup;
+
+    status = event[10];
+    status = (status << 8) | event[9];
+    status = (status << 8) | event[8];
+    status = (status << 8) | event[7];
+    *rom_version = status;
+
+    status = event[14];
+    status = (status << 8) | event[13];
+    status = (status << 8) | event[12];
+    status = (status << 8) | event[11];
+    *build_version = status;
+
+cleanup:
+    free(event);
+
+    return err;
+}
+
+#define VERIFY_CRC   9
+#define PS_REGION    1
+#define PATCH_REGION 2
+
+static int get_ath3k_crc(int dev)
+{
+    uint8_t cmd[7] = {0};
+    uint8_t *event;
+    int err;
+
+    load_hci_ps_hdr(cmd, VERIFY_CRC, 0, PS_REGION | PATCH_REGION);
+
+    err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event);
+    if (err < 0)
+        return err;
+    /* Send error code if CRC check patched */
+    if (read_ps_event(event, HCI_PS_CMD_OCF) >= 0)
+        err = -EILSEQ;
+
+    free(event);
+
+    return err;
+}
+
+#define SET_PATCH_RAM_ID        0x0D
+#define SET_PATCH_RAM_CMD_SIZE  11
+#define ADDRESS_LEN             4
+static int set_patch_ram(int dev, char *patch_loc, int len)
+{
+    int err;
+    uint8_t cmd[20] = {0};
+    int i, j;
+    char loc_byte[3];
+    uint8_t *event;
+    uint8_t *loc_ptr = &cmd[7];
+
+    RESERVED(len);
+
+    if (!patch_loc)
+        return -1;
+
+    loc_byte[2] = '\0';
+
+    load_hci_ps_hdr(cmd, SET_PATCH_RAM_ID, ADDRESS_LEN, 0);
+
+    for (i = 0, j = 3; i < 4; i++, j--) {
+        loc_byte[0] = patch_loc[0];
+        loc_byte[1] = patch_loc[1];
+        loc_ptr[j] = strtol(loc_byte, NULL, 16);
+        patch_loc += 2;
+    }
+
+    err = send_hci_cmd_sync(dev, cmd, SET_PATCH_RAM_CMD_SIZE, &event);
+    if (err < 0)
+        return err;
+
+    err = read_ps_event(event, HCI_PS_CMD_OCF);
+
+    free(event);
+
+    return err;
+}
+
+#define PATCH_LOC_KEY    "DA:"
+#define PATCH_LOC_STRING_LEN    8
+static int ps_patch_download(int fd, FILE *stream)
+{
+    char byte[3];
+    char ptr[MAX_PATCH_CMD + 1];
+    int byte_cnt;
+    int patch_count = 0;
+    char patch_loc[PATCH_LOC_STRING_LEN + 1];
+
+    byte[2] = '\0';
+
+    while (fgets(ptr, MAX_PATCH_CMD, stream)) {
+        if (strlen(ptr) <= 1)
+            continue;
+        else if (strstr(ptr, PATCH_LOC_KEY) == ptr) {
+            strlcpy(patch_loc, &ptr[sizeof(PATCH_LOC_KEY) - 1],
+                PATCH_LOC_STRING_LEN);
+            if (set_patch_ram(fd, patch_loc, sizeof(patch_loc)) < 0)
+                return -1;
+        } else if (isxdigit(ptr[0]))
+            break;
+        else
+        return -1;
+    }
+
+    byte_cnt = strtol(ptr, NULL, 16);
+
+    while (byte_cnt > 0) {
+        int i;
+        uint8_t cmd[HCI_MAX_CMD_SIZE] = {0};
+        struct patch_entry patch;
+
+        if (byte_cnt > MAX_PATCH_CMD)
+            patch.len = MAX_PATCH_CMD;
+        else
+            patch.len = byte_cnt;
+
+        for (i = 0; i < patch.len; i++) {
+            if (!fgets(byte, 3, stream))
+                return -1;
+
+            patch.data[i] = strtoul(byte, NULL, 16);
+        }
+
+        load_hci_ps_hdr(cmd, WRITE_PATCH, patch.len, patch_count);
+        memcpy(&cmd[HCI_PS_CMD_HDR_LEN], patch.data, patch.len);
+
+        if (write_cmd(fd, cmd, patch.len + HCI_PS_CMD_HDR_LEN) < 0)
+            return -1;
+
+        patch_count++;
+        byte_cnt = byte_cnt - MAX_PATCH_CMD;
+    }
+
+    if (write_ps_cmd(fd, ENABLE_PATCH, 0) < 0)
+        return -1;
+
+    return patch_count;
+}
+
+static int ath_ps_download(int fd)
+{
+    int err = 0;
+    int tag_count;
+    int patch_count = 0;
+    uint32_t rom_version = 0;
+    uint32_t build_version = 0;
+    uint32_t dev_type = 0;
+    char patch_file[PATH_MAX];
+    char ps_file[PATH_MAX];
+    FILE *stream;
+
+    /*
+    * Verfiy firmware version. depending on it select the PS
+    * config file to download.
+    */
+    if (get_device_type(fd, &dev_type) < 0) {
+        err = -EILSEQ;
+        goto download_cmplete;
+    }
+
+    if (read_ath3k_version(fd, &rom_version, &build_version) < 0) {
+        err = -EILSEQ;
+        goto download_cmplete;
+    }
+
+    /* Do not download configuration if CRC passes */
+    if (get_ath3k_crc(fd) < 0) {
+        err = 0;
+        goto download_cmplete;
+    }
+
+    get_ps_file_name(dev_type, rom_version, ps_file);
+    get_patch_file_name(dev_type, rom_version, build_version, patch_file);
+
+    stream = fopen(ps_file, "r");
+    if (!stream) {
+        ALOGI("firmware file open error:%s, ver:%x\n",ps_file, rom_version);
+        if (rom_version == 0x1020201)
+            err = 0;
+        else
+            err	= -EILSEQ;
+        goto download_cmplete;
+    }
+    tag_count = ath_parse_ps(stream);
+
+    fclose(stream);
+
+    if (tag_count < 0) {
+        err = -EILSEQ;
+        goto download_cmplete;
+    }
+
+    /*
+    * It is not necessary that Patch file be available,
+    * continue with PS Operations if patch file is not available.
+    */
+    if (patch_file[0] == '\0')
+        err = 0;
+
+    stream = fopen(patch_file, "r");
+    if (!stream)
+        err = 0;
+    else {
+        patch_count = ps_patch_download(fd, stream);
+        fclose(stream);
+
+        if (patch_count < 0) {
+            err = -EILSEQ;
+            goto download_cmplete;
+        }
+    }
+
+    err = ps_config_download(fd, tag_count);
+
+download_cmplete:
+    if (!err)
+        write_bdaddr_from_file(rom_version, fd);
+
+    return err;
+}
+
+int ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti)
+{
+    ALOGI(" %s ", __FUNCTION__);
+
+    int r;
+    int err = 0;
+    struct timespec tm = { 0, 500000};
+    unsigned char cmd[MAX_CMD_LEN] = {0};
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+    unsigned char *ptr = cmd + 1;
+    hci_command_hdr *ch = (void *)ptr;
+    int flags = 0;
+
+    if (ioctl(fd, TIOCMGET, &flags) < 0) {
+        ALOGI("TIOCMGET failed in init\n");
+        return -1;
+    }
+    flags |= TIOCM_RTS;
+    if (ioctl(fd, TIOCMSET, &flags) < 0) {
+        ALOGI("TIOCMSET failed in init: HW Flow-on error\n");
+        return -1;
+    }
+
+    /* set both controller and host baud rate to maximum possible value */
+    err = set_cntrlr_baud(fd, speed);
+    ALOGI("set_cntrlr_baud : ret:%d \n", err);
+    if (err < 0)
+        return err;
+
+    err = set_speed(fd, ti, speed);
+    if (err < 0) {
+        ALOGI("Can't set required baud rate");
+        return err;
+    }
+
+    /* Download PS and patch */
+    r = ath_ps_download(fd);
+    if (r < 0) {
+        ALOGI("Failed to Download configuration");
+        err = -ETIMEDOUT;
+        goto failed;
+    }
+
+    ALOGI("ath_ps_download is done\n");
+
+    cmd[0] = HCI_COMMAND_PKT;
+    /* Write BDADDR */
+    if (bdaddr) {
+        ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF,
+        HCI_PS_CMD_OCF));
+        ch->plen = 10;
+        ptr += HCI_COMMAND_HDR_SIZE;
+
+        ptr[0] = 0x01;
+        ptr[1] = 0x01;
+        ptr[2] = 0x00;
+        ptr[3] = 0x06;
+        str2ba(bdaddr, (bdaddr_t *)(ptr + 4));
+
+        if (write(fd, cmd, WRITE_BDADDR_CMD_LEN) !=
+                WRITE_BDADDR_CMD_LEN) {
+            ALOGI("Failed to write BD_ADDR command\n");
+            err = -ETIMEDOUT;
+            goto failed;
+        }
+
+        if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) {
+            ALOGI("Failed to set BD_ADDR\n");
+            err = -ETIMEDOUT;
+            goto failed;
+        }
+    }
+
+    /* Send HCI Reset */
+    cmd[1] = 0x03;
+    cmd[2] = 0x0C;
+    cmd[3] = 0x00;
+
+    r = write(fd, cmd, 4);
+    if (r != 4) {
+        err = -ETIMEDOUT;
+        goto failed;
+    }
+
+    nanosleep(&tm, NULL);
+    if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) {
+        err = -ETIMEDOUT;
+        goto failed;
+    }
+
+    ALOGI("HCI Reset is done\n");
+    err = set_cntrlr_baud(fd, speed);
+    if (err < 0)
+        ALOGI("set_cntrlr_baud0:%d,%d\n", speed, err);
+
+failed:
+    if (err < 0) {
+        set_cntrlr_baud(fd, init_speed);
+        set_speed(fd, ti, init_speed);
+    }
+
+    return err;
+
+}
+#define BTPROTO_HCI 1
+
+/* Open HCI device.
+ * Returns device descriptor (dd). */
+int hci_open_dev(int dev_id)
+{
+    struct sockaddr_hci a;
+    int dd, err;
+
+    /* Create HCI socket */
+    dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+    if (dd < 0)
+        return dd;
+
+    /* Bind socket to the HCI device */
+    memset(&a, 0, sizeof(a));
+    a.hci_family = AF_BLUETOOTH;
+    a.hci_dev = dev_id;
+    if (bind(dd, (struct sockaddr *) &a, sizeof(a)) < 0)
+        goto failed;
+
+    return dd;
+
+failed:
+    err = errno;
+    close(dd);
+    errno = err;
+
+    return -1;
+}
+
+int hci_close_dev(int dd)
+{
+    return close(dd);
+}
+
+/* HCI functions that require open device
+ * dd - Device descriptor returned by hci_open_dev. */
+
+int hci_send_cmd(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, void *param)
+{
+    uint8_t type = HCI_COMMAND_PKT;
+    hci_command_hdr hc;
+    struct iovec iv[3];
+    int ivn;
+
+    hc.opcode = htobs(cmd_opcode_pack(ogf, ocf));
+    hc.plen= plen;
+
+    iv[0].iov_base = &type;
+    iv[0].iov_len  = 1;
+    iv[1].iov_base = &hc;
+    iv[1].iov_len  = HCI_COMMAND_HDR_SIZE;
+    ivn = 2;
+
+    if (plen) {
+        iv[2].iov_base = param;
+        iv[2].iov_len  = plen;
+        ivn = 3;
+    }
+
+    while (writev(dd, iv, ivn) < 0) {
+        if (errno == EAGAIN || errno == EINTR)
+            continue;
+        return -1;
+    }
+    return 0;
+}
+
+#define HCI_SLEEP_CMD_OCF     0x04
+#define TIOCSETD 0x5423
+#define HCIUARTSETFLAGS _IOW('U', 204, int)
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+#define HCIUARTGETDEVICE _IOW('U', 202, int)
+/*
+ * Atheros AR300x specific initialization post callback
+ */
+int ath3k_post(int fd, int pm)
+{
+    int dev_id, dd;
+    struct timespec tm = { 0, 50000};
+
+    sleep(1);
+
+    dev_id = ioctl(fd, HCIUARTGETDEVICE, 0);
+    if (dev_id < 0) {
+        perror("cannot get device id");
+        return dev_id;
+    }
+
+    dd = hci_open_dev(dev_id);
+    if (dd < 0) {
+        perror("HCI device open failed");
+        return dd;
+    }
+
+    if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) {
+        perror("hci down:Power management Disabled");
+        hci_close_dev(dd);
+        return -1;
+    }
+
+    /* send vendor specific command with Sleep feature Enabled */
+    if (hci_send_cmd(dd, OGF_VENDOR_CMD, HCI_SLEEP_CMD_OCF, 1, &pm) < 0)
+        perror("PM command failed, power management Disabled");
+
+    nanosleep(&tm, NULL);
+    hci_close_dev(dd);
+
+    return 0;
+}
+
+
+
+#define FLOW_CTL    0x0001
+#define ENABLE_PM   1
+#define DISABLE_PM  0
+
+/* Initialize UART driver */
+static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)
+{
+    ALOGI(" %s ", __FUNCTION__);
+
+    struct termios ti;
+
+    int i, fd;
+    unsigned long flags = 0;
+
+    if (raw)
+        flags |= 1 << HCI_UART_RAW_DEVICE;
+
+
+    fd = open(dev, O_RDWR | O_NOCTTY);
+
+    if (fd < 0) {
+        ALOGI("Can't open serial port");
+        return -1;
+    }
+
+
+    tcflush(fd, TCIOFLUSH);
+
+    if (tcgetattr(fd, &ti) < 0) {
+        ALOGI("Can't get port settings: %d\n", errno);
+        return -1;
+    }
+
+    cfmakeraw(&ti);
+
+    ti.c_cflag |= CLOCAL;
+    if (u->flags & FLOW_CTL)
+        ti.c_cflag |= CRTSCTS;
+    else
+        ti.c_cflag &= ~CRTSCTS;
+
+    if (tcsetattr(fd, TCSANOW, &ti) < 0) {
+        ALOGI("Can't set port settings");
+        return -1;
+    }
+
+    if (set_speed(fd, &ti, u->init_speed) < 0) {
+        ALOGI("Can't set initial baud rate");
+        return -1;
+    }
+
+    tcflush(fd, TCIOFLUSH);
+
+    if (send_break) {
+        tcsendbreak(fd, 0);
+        usleep(500000);
+    }
+
+    ath3k_init(fd,u->speed,u->init_speed,u->bdaddr, &ti);
+
+    ALOGI("Device setup complete\n");
+
+
+    tcflush(fd, TCIOFLUSH);
+
+    // Set actual baudrate
+    /*
+    if (set_speed(fd, &ti, u->speed) < 0) {
+        perror("Can't set baud rate");
+        return -1;
+    }
+
+    i = N_HCI;
+    if (ioctl(fd, TIOCSETD, &i) < 0) {
+        perror("Can't set line discipline");
+        return -1;
+    }
+
+    if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) {
+        perror("Can't set UART flags");
+        return -1;
+    }
+
+    if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) {
+        perror("Can't set device");
+        return -1;
+    }
+
+#if !defined(SW_BOARD_HAVE_BLUETOOTH_RTK)
+    ath3k_post(fd, u->pm);
+#endif
+    */
+
+    return fd;
+}
+
+
+int hw_config_ath3k(char *port_name)
+{
+    ALOGI(" %s ", __FUNCTION__);
+    PSCounter=0;
+    struct sigaction sa;
+    struct uart_t u ;
+    int n=0,send_break=0,raw=0;
+
+    memset(&u, 0, sizeof(u));
+    u.speed =3000000;
+    u.init_speed =115200;
+    u.flags |= FLOW_CTL;
+    u.pm = DISABLE_PM;
+
+    n = init_uart(port_name, &u, send_break, raw);
+    if (n < 0) {
+        ALOGI("Can't initialize device");
+    }
+
+    return n;
+}
+
+void lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity)
+{
+    int rc;
+    int fd = -1;
+    char buffer;
+
+    ALOGI("lpm mode: %d  action: %d", pio, action);
+
+    RESERVED(polarity);
+
+    switch (pio)
+    {
+        case UPIO_LPM_MODE:
+            if (upio_state[UPIO_LPM_MODE] == action)
+            {
+                ALOGI("LPM is %s already", lpm_mode[action]);
+                return;
+            }
+
+            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';
+            }
+
+            if (write(fd, &buffer, 1) < 0)
+            {
+                ALOGE("upio_set : write(%s) failed: %s (%d)",
+                VENDOR_LPM_PROC_NODE, strerror(errno),errno);
+            }
+            else
+            {
+                upio_state[UPIO_LPM_MODE] = action;
+                ALOGI("LPM is set to %s", lpm_mode[action]);
+            }
+
+            if (fd >= 0)
+                close(fd);
+
+            break;
+
+        case UPIO_BT_WAKE:
+            /* UPIO_DEASSERT should be allowed because in Rx case assert occur
+            * from the remote side where as deassert  will be initiated from Host
+            */
+            if ((action == UPIO_ASSERT) && (upio_state[UPIO_BT_WAKE] == action))
+            {
+                ALOGI("BT_WAKE is %s already", lpm_state[action]);
+
+                return;
+            }
+
+            if (action == UPIO_DEASSERT)
+                buffer = '0';
+            else
+                buffer = '1';
+
+            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;
+            }
+
+            if (write(fd, &buffer, 1) < 0)
+            {
+                ALOGE("upio_set : write(%s) failed: %s (%d)",
+                VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno);
+            }
+            else
+            {
+                upio_state[UPIO_BT_WAKE] = action;
+                ALOGI("BT_WAKE is set to %s", lpm_state[action]);
+            }
+
+            ALOGI("proc btwrite assertion");
+
+            if (fd >= 0)
+                close(fd);
+
+            break;
+
+        case UPIO_HOST_WAKE:
+            ALOGI("upio_set: UPIO_HOST_WAKE");
+            break;
+    }
+
+}
diff --git a/sdm845/libbt-vendor/src/hw_rome.c b/sdm845/libbt-vendor/src/hw_rome.c
new file mode 100644
index 0000000..ccfb137
--- /dev/null
+++ b/sdm845/libbt-vendor/src/hw_rome.c
@@ -0,0 +1,1950 @@
+/*
+ *
+ *  Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  Not a Contribution.
+ *
+ *  Copyright 2012 The Android Open Source Project
+ *
+ *  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:      hw_rome.c
+ *
+ *  Description:   Contains controller-specific functions, like
+ *                      firmware patch download
+ *                      low power mode operations
+ *
+ ******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LOG_TAG "bt_vendor"
+
+#include <sys/socket.h>
+#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 <termios.h>
+#include <string.h>
+#include <stdbool.h>
+#include "bt_hci_bdroid.h"
+#include "bt_vendor_qcom.h"
+#include "hci_uart.h"
+#include "hw_rome.h"
+
+#define BT_VERSION_FILEPATH "/data/misc/bluedroid/bt_fw_version.txt"
+
+#ifdef __cplusplus
+}
+#endif
+
+#define RESERVED(p)  if(p) ALOGI( "%s: reserved param", __FUNCTION__);
+
+int read_vs_hci_event(int fd, unsigned char* buf, int size);
+
+/******************************************************************************
+**  Variables
+******************************************************************************/
+FILE *file;
+unsigned char *phdr_buffer;
+unsigned char *pdata_buffer = NULL;
+patch_info rampatch_patch_info;
+int chipset_ver = 0;
+unsigned char gTlv_type;
+unsigned char gTlv_dwndCfg;
+static unsigned int wipower_flag = 0;
+static unsigned int wipower_handoff_ready = 0;
+char *rampatch_file_path = NULL;
+char *nvm_file_path = NULL;
+char *fw_su_info = NULL;
+unsigned short fw_su_offset =0;
+extern char enable_extldo;
+unsigned char wait_vsc_evt = TRUE;
+bool patch_dnld_pending = FALSE;
+int dnld_fd = -1;
+
+/******************************************************************************
+**  Extern variables
+******************************************************************************/
+
+/*****************************************************************************
+**   Functions
+*****************************************************************************/
+int do_write(int fd, unsigned char *buf,int len)
+{
+    int ret = 0;
+    int write_offset = 0;
+    int write_len = len;
+    do {
+        ret = write(fd,buf+write_offset,write_len);
+        if (ret < 0)
+        {
+            ALOGE("%s, write failed ret = %d err = %s",__func__,ret,strerror(errno));
+            return -1;
+        } else if (ret == 0) {
+            ALOGE("%s, write failed with ret 0 err = %s",__func__,strerror(errno));
+            return 0;
+        } else {
+            if (ret < write_len) {
+                ALOGD("%s, Write pending,do write ret = %d err = %s",__func__,ret,
+                       strerror(errno));
+                write_len = write_len - ret;
+                write_offset = ret;
+            } else {
+                ALOGV("Write successful");
+                break;
+            }
+        }
+    } while(1);
+    return len;
+}
+
+int get_vs_hci_event(unsigned char *rsp)
+{
+    int err = 0;
+    unsigned char paramlen = 0;
+    unsigned char EMBEDDED_MODE_CHECK = 0x02;
+    FILE *btversionfile = 0;
+    unsigned int soc_id = 0;
+    unsigned int productid = 0;
+    unsigned short patchversion = 0;
+    char build_label[255];
+    int build_lbl_len;
+    unsigned short buildversion = 0;
+
+    if( (rsp[EVENTCODE_OFFSET] == VSEVENT_CODE) || (rsp[EVENTCODE_OFFSET] == EVT_CMD_COMPLETE))
+        ALOGI("%s: Received HCI-Vendor Specific event", __FUNCTION__);
+    else {
+        ALOGI("%s: Failed to receive HCI-Vendor Specific event", __FUNCTION__);
+        err = -EIO;
+        goto failed;
+    }
+
+    ALOGI("%s: Parameter Length: 0x%x", __FUNCTION__, paramlen = rsp[EVT_PLEN]);
+    ALOGI("%s: Command response: 0x%x", __FUNCTION__, rsp[CMD_RSP_OFFSET]);
+    ALOGI("%s: Response type   : 0x%x", __FUNCTION__, rsp[RSP_TYPE_OFFSET]);
+
+    /* Check the status of the operation */
+    switch ( rsp[CMD_RSP_OFFSET] )
+    {
+        case EDL_CMD_REQ_RES_EVT:
+        ALOGI("%s: Command Request Response", __FUNCTION__);
+        switch(rsp[RSP_TYPE_OFFSET])
+        {
+            case EDL_PATCH_VER_RES_EVT:
+            case EDL_APP_VER_RES_EVT:
+                ALOGI("\t Current Product ID\t\t: 0x%08x",
+                    productid = (unsigned int)(rsp[PATCH_PROD_ID_OFFSET +3] << 24 |
+                                        rsp[PATCH_PROD_ID_OFFSET+2] << 16 |
+                                        rsp[PATCH_PROD_ID_OFFSET+1] << 8 |
+                                        rsp[PATCH_PROD_ID_OFFSET]  ));
+
+                /* Patch Version indicates FW patch version */
+                ALOGI("\t Current Patch Version\t\t: 0x%04x",
+                    (patchversion = (unsigned short)(rsp[PATCH_PATCH_VER_OFFSET + 1] << 8 |
+                                            rsp[PATCH_PATCH_VER_OFFSET] )));
+
+                /* ROM Build Version indicates ROM build version like 1.0/1.1/2.0 */
+                ALOGI("\t Current ROM Build Version\t: 0x%04x", buildversion =
+                    (int)(rsp[PATCH_ROM_BUILD_VER_OFFSET + 1] << 8 |
+                                            rsp[PATCH_ROM_BUILD_VER_OFFSET] ));
+
+                /* In case rome 1.0/1.1, there is no SOC ID version available */
+                if (paramlen - 10)
+                {
+                    ALOGI("\t Current SOC Version\t\t: 0x%08x", soc_id =
+                        (unsigned int)(rsp[PATCH_SOC_VER_OFFSET +3] << 24 |
+                                                rsp[PATCH_SOC_VER_OFFSET+2] << 16 |
+                                                rsp[PATCH_SOC_VER_OFFSET+1] << 8 |
+                                                rsp[PATCH_SOC_VER_OFFSET]  ));
+                }
+
+                if (NULL != (btversionfile = fopen(BT_VERSION_FILEPATH, "wb"))) {
+                    fprintf(btversionfile, "Bluetooth Controller Product ID    : 0x%08x\n", productid);
+                    fprintf(btversionfile, "Bluetooth Controller Patch Version : 0x%04x\n", patchversion);
+                    fprintf(btversionfile, "Bluetooth Controller Build Version : 0x%04x\n", buildversion);
+                    fprintf(btversionfile, "Bluetooth Controller SOC Version   : 0x%08x\n", soc_id);
+                    fclose(btversionfile);
+                }else {
+                    ALOGI("Failed to dump SOC version info. Errno:%d", errno);
+                }
+                /* Rome Chipset Version can be decided by Patch version and SOC version,
+                Upper 2 bytes will be used for Patch version and Lower 2 bytes will be
+                used for SOC as combination for BT host driver */
+                chipset_ver = (buildversion << 16) |(soc_id & 0x0000ffff);
+
+                break;
+            case EDL_TVL_DNLD_RES_EVT:
+            case EDL_CMD_EXE_STATUS_EVT:
+                switch (err = rsp[CMD_STATUS_OFFSET])
+                    {
+                    case HCI_CMD_SUCCESS:
+                        ALOGI("%s: Download Packet successfully!", __FUNCTION__);
+                        break;
+                    case PATCH_LEN_ERROR:
+                        ALOGI("%s: Invalid patch length argument passed for EDL PATCH "
+                        "SET REQ cmd", __FUNCTION__);
+                        break;
+                    case PATCH_VER_ERROR:
+                        ALOGI("%s: Invalid patch version argument passed for EDL PATCH "
+                        "SET REQ cmd", __FUNCTION__);
+                        break;
+                    case PATCH_CRC_ERROR:
+                        ALOGI("%s: CRC check of patch failed!!!", __FUNCTION__);
+                        break;
+                    case PATCH_NOT_FOUND:
+                        ALOGI("%s: Invalid patch data!!!", __FUNCTION__);
+                        break;
+                    case TLV_TYPE_ERROR:
+                        ALOGI("%s: TLV Type Error !!!", __FUNCTION__);
+                        break;
+                    default:
+                        ALOGI("%s: Undefined error (0x%x)", __FUNCTION__, err);
+                        break;
+                    }
+            break;
+            case HCI_VS_GET_BUILD_VER_EVT:
+                build_lbl_len = rsp[5];
+                memcpy (build_label, &rsp[6], build_lbl_len);
+                *(build_label+build_lbl_len) = '\0';
+
+                ALOGI("BT SoC FW SU Build info: %s, %d", build_label, build_lbl_len);
+                if (NULL != (btversionfile = fopen(BT_VERSION_FILEPATH, "a+b"))) {
+                    fprintf(btversionfile, "Bluetooth Contoller SU Build info  : %s\n", build_label);
+                    fclose(btversionfile);
+                } else {
+                    ALOGI("Failed to dump  FW SU build info. Errno:%d", errno);
+                }
+            break;
+        }
+        break;
+
+        case NVM_ACCESS_CODE:
+            ALOGI("%s: NVM Access Code!!!", __FUNCTION__);
+            err = HCI_CMD_SUCCESS;
+            break;
+        case EDL_SET_BAUDRATE_RSP_EVT:
+            /* Rome 1.1 has bug with the response, so it should ignore it. */
+            if (rsp[BAUDRATE_RSP_STATUS_OFFSET] != BAUDRATE_CHANGE_SUCCESS)
+            {
+                ALOGE("%s: Set Baudrate request failed - 0x%x", __FUNCTION__,
+                    rsp[CMD_STATUS_OFFSET]);
+                err = -1;
+            }
+            break;
+       case EDL_WIP_QUERY_CHARGING_STATUS_EVT:
+            /* Query charging command has below return values
+            0 - in embedded mode not charging
+            1 - in embedded mode and charging
+            2 - hadofff completed and in normal mode
+            3 - no wipower supported on mtp. so irrepective of charging
+            handoff command has to be sent if return values are 0 or 1.
+            These change include logic to enable generic BT turn on sequence.*/
+            if (rsp[4] < EMBEDDED_MODE_CHECK)
+            {
+               ALOGI("%s: WiPower Charging in Embedded Mode!!!", __FUNCTION__);
+               wipower_handoff_ready = rsp[4];
+               wipower_flag = 1;
+            }
+            break;
+        case EDL_WIP_START_HANDOFF_TO_HOST_EVENT:
+            /*TODO: rsp code 00 mean no charging
+            this is going to change in FW soon*/
+            if (rsp[4] == NON_WIPOWER_MODE)
+            {
+               ALOGE("%s: WiPower Charging hand off not ready!!!", __FUNCTION__);
+            }
+            break;
+        case HCI_VS_GET_ADDON_FEATURES_EVENT:
+            if ((rsp[4] & ADDON_FEATURES_EVT_WIPOWER_MASK))
+            {
+               ALOGD("%s: WiPower feature supported!!", __FUNCTION__);
+               property_set("persist.bluetooth.a4wp", "true");
+            }
+            break;
+        case HCI_VS_STRAY_EVT:
+            /* WAR to handle stray Power Apply EVT during patch download */
+            ALOGD("%s: Stray HCI VS EVENT", __FUNCTION__);
+            if (patch_dnld_pending && dnld_fd != -1)
+            {
+                unsigned char rsp[HCI_MAX_EVENT_SIZE];
+                memset(rsp, 0x00, HCI_MAX_EVENT_SIZE);
+                read_vs_hci_event(dnld_fd, rsp, HCI_MAX_EVENT_SIZE);
+            }
+            else
+            {
+                ALOGE("%s: Not a valid status!!!", __FUNCTION__);
+                err = -1;
+            }
+            break;
+        default:
+            ALOGE("%s: Not a valid status!!!", __FUNCTION__);
+            err = -1;
+            break;
+    }
+
+failed:
+    return err;
+}
+
+
+/*
+ * Read an VS HCI event from the given file descriptor.
+ */
+int read_vs_hci_event(int fd, unsigned char* buf, int size)
+{
+    int remain, r;
+    int count = 0, i;
+
+    if (size <= 0) {
+        ALOGE("Invalid size arguement!");
+        return -1;
+    }
+
+    ALOGI("%s: Wait for HCI-Vendor Specfic Event from SOC", __FUNCTION__);
+
+    /* The first byte identifies the packet type. For HCI event packets, it
+     * should be 0x04, so we read until we get to the 0x04. */
+    /* It will keep reading until find 0x04 byte */
+    while (1) {
+            r = read(fd, buf, 1);
+            if (r <= 0)
+                    return -1;
+            if (buf[0] == 0x04)
+                    break;
+    }
+    count++;
+
+    /* The next two bytes are the event code and parameter total length. */
+    while (count < 3) {
+            r = read(fd, buf + count, 3 - count);
+            if ((r <= 0) || (buf[1] != 0xFF )) {
+                ALOGE("It is not VS event !! ret: %d, EVT: %d", r, buf[1]);
+                return -1;
+            }
+            count += r;
+    }
+
+    /* Now we read the parameters. */
+    if (buf[2] < (size - 3))
+            remain = buf[2];
+    else
+            remain = size - 3;
+
+    while ((count - 3) < remain) {
+            r = read(fd, buf + count, remain - (count - 3));
+            if (r <= 0)
+                    return -1;
+            count += r;
+    }
+
+     /* Check if the set patch command is successful or not */
+    if(get_vs_hci_event(buf) != HCI_CMD_SUCCESS)
+        return -1;
+
+    return count;
+}
+
+/*
+ * For Hand-Off related Wipower commands, Command complete arrives first and
+ * the followd with VS event
+ *
+ */
+int hci_send_wipower_vs_cmd(int fd, unsigned char *cmd, unsigned char *rsp, int size)
+{
+    int ret = 0;
+    int err = 0;
+
+    /* Send the HCI command packet to UART for transmission */
+    ret = do_write(fd, cmd, size);
+    if (ret != size) {
+        ALOGE("%s: WP Send failed with ret value: %d", __FUNCTION__, ret);
+        goto failed;
+    }
+
+    /* Wait for command complete event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        ALOGE("%s: Failed to charging status cmd on Controller", __FUNCTION__);
+        goto failed;
+    }
+
+    ALOGI("%s: WP Received HCI command complete Event from SOC", __FUNCTION__);
+failed:
+    return ret;
+}
+
+
+int hci_send_vs_cmd(int fd, unsigned char *cmd, unsigned char *rsp, int size)
+{
+    int ret = 0;
+
+    /* Send the HCI command packet to UART for transmission */
+    ret = do_write(fd, cmd, size);
+    if (ret != size) {
+        ALOGE("%s: Send failed with ret value: %d", __FUNCTION__, ret);
+        goto failed;
+    }
+
+    if (wait_vsc_evt) {
+        /* Check for response from the Controller */
+        if (read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE) < 0) {
+           ret = -ETIMEDOUT;
+           ALOGI("%s: Failed to get HCI-VS Event from SOC", __FUNCTION__);
+           goto failed;
+        }
+        ALOGI("%s: Received HCI-Vendor Specific Event from SOC", __FUNCTION__);
+    }
+
+failed:
+    return ret;
+}
+
+void frame_hci_cmd_pkt(
+    unsigned char *cmd,
+    int edl_cmd, unsigned int p_base_addr,
+    int segtNo, int size
+    )
+{
+    int offset = 0;
+    hci_command_hdr *cmd_hdr;
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+
+    cmd[0]      = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, HCI_PATCH_CMD_OCF);
+    cmd_hdr->plen   = size;
+    cmd[4]      = edl_cmd;
+
+    switch (edl_cmd)
+    {
+        case EDL_PATCH_SET_REQ_CMD:
+            /* Copy the patch header info as CMD params */
+            memcpy(&cmd[5], phdr_buffer, PATCH_HDR_LEN);
+            ALOGD("%s: Sending EDL_PATCH_SET_REQ_CMD", __FUNCTION__);
+            ALOGD("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x",
+                segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+            break;
+        case EDL_PATCH_DLD_REQ_CMD:
+            offset = ((segtNo - 1) * MAX_DATA_PER_SEGMENT);
+            p_base_addr += offset;
+            cmd_hdr->plen   = (size + 6);
+            cmd[5]  = (size + 4);
+            cmd[6]  = EXTRACT_BYTE(p_base_addr, 0);
+            cmd[7]  = EXTRACT_BYTE(p_base_addr, 1);
+            cmd[8]  = EXTRACT_BYTE(p_base_addr, 2);
+            cmd[9]  = EXTRACT_BYTE(p_base_addr, 3);
+            memcpy(&cmd[10], (pdata_buffer + offset), size);
+
+            ALOGD("%s: Sending EDL_PATCH_DLD_REQ_CMD: size: %d bytes",
+                __FUNCTION__, size);
+            ALOGD("HCI-CMD %d:\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t"
+                "0x%x\t0x%x\t0x%x\t\n", segtNo, cmd[0], cmd[1], cmd[2],
+                cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9]);
+            break;
+        case EDL_PATCH_ATCH_REQ_CMD:
+            ALOGD("%s: Sending EDL_PATCH_ATTACH_REQ_CMD", __FUNCTION__);
+            ALOGD("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x",
+            segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+            break;
+        case EDL_PATCH_RST_REQ_CMD:
+            ALOGD("%s: Sending EDL_PATCH_RESET_REQ_CMD", __FUNCTION__);
+            ALOGD("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x",
+            segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+            break;
+        case EDL_PATCH_VER_REQ_CMD:
+            ALOGD("%s: Sending EDL_PATCH_VER_REQ_CMD", __FUNCTION__);
+            ALOGD("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x",
+            segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+            break;
+        case EDL_PATCH_TLV_REQ_CMD:
+            ALOGD("%s: Sending EDL_PATCH_TLV_REQ_CMD", __FUNCTION__);
+            /* Parameter Total Length */
+            cmd[3] = size +2;
+
+            /* TLV Segment Length */
+            cmd[5] = size;
+            ALOGD("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x \t0x%x",
+            segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]);
+            offset = (segtNo * MAX_SIZE_PER_TLV_SEGMENT);
+            memcpy(&cmd[6], (pdata_buffer + offset), size);
+            break;
+        case EDL_GET_BUILD_INFO:
+            ALOGD("%s: Sending EDL_GET_BUILD_INFO", __FUNCTION__);
+            ALOGD("HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x",
+                segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+            break;
+        default:
+            ALOGE("%s: Unknown EDL CMD !!!", __FUNCTION__);
+    }
+}
+
+void rome_extract_patch_header_info(unsigned char *buf)
+{
+    int index;
+
+    /* Extract patch id */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_id |=
+            (LSH(buf[index + P_ID_OFFSET], (index * 8)));
+
+    /* Extract (ROM and BUILD) version information */
+    for (index = 0; index < 2; index++)
+        rampatch_patch_info.patch_ver.rom_version |=
+            (LSH(buf[index + P_ROME_VER_OFFSET], (index * 8)));
+
+    for (index = 0; index < 2; index++)
+        rampatch_patch_info.patch_ver.build_version |=
+            (LSH(buf[index + P_BUILD_VER_OFFSET], (index * 8)));
+
+    /* Extract patch base and entry addresses */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_base_addr |=
+            (LSH(buf[index + P_BASE_ADDR_OFFSET], (index * 8)));
+
+    /* Patch BASE & ENTRY addresses are same */
+    rampatch_patch_info.patch_entry_addr = rampatch_patch_info.patch_base_addr;
+
+    /* Extract total length of the patch payload */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_length |=
+            (LSH(buf[index + P_LEN_OFFSET], (index * 8)));
+
+    /* Extract the CRC checksum of the patch payload */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_crc |=
+            (LSH(buf[index + P_CRC_OFFSET], (index * 8)));
+
+    /* Extract patch control value */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_ctrl |=
+            (LSH(buf[index + P_CONTROL_OFFSET], (index * 8)));
+
+    ALOGI("PATCH_ID\t : 0x%x", rampatch_patch_info.patch_id);
+    ALOGI("ROM_VERSION\t : 0x%x", rampatch_patch_info.patch_ver.rom_version);
+    ALOGI("BUILD_VERSION\t : 0x%x", rampatch_patch_info.patch_ver.build_version);
+    ALOGI("PATCH_LENGTH\t : 0x%x", rampatch_patch_info.patch_length);
+    ALOGI("PATCH_CRC\t : 0x%x", rampatch_patch_info.patch_crc);
+    ALOGI("PATCH_CONTROL\t : 0x%x\n", rampatch_patch_info.patch_ctrl);
+    ALOGI("PATCH_BASE_ADDR\t : 0x%x\n", rampatch_patch_info.patch_base_addr);
+
+}
+
+int rome_edl_set_patch_request(int fd)
+{
+    int size, err;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    /* Frame the HCI CMD to be sent to the Controller */
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_SET_REQ_CMD, 0,
+        -1, PATCH_HDR_LEN + 1);
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+
+    /* Send HCI Command packet to Controller */
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to set the patch info to the Controller!");
+        goto error;
+    }
+
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        ALOGE("%s: Failed to set patch info on Controller", __FUNCTION__);
+        goto error;
+    }
+    ALOGI("%s: Successfully set patch info on the Controller", __FUNCTION__);
+error:
+    return err;
+}
+
+int rome_edl_patch_download_request(int fd)
+{
+    int no_of_patch_segment;
+    int index = 1, err = 0, size = 0;
+    unsigned int p_base_addr;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    no_of_patch_segment = (rampatch_patch_info.patch_length /
+        MAX_DATA_PER_SEGMENT);
+    ALOGI("%s: %d patch segments to be d'loaded from patch base addr: 0x%x",
+        __FUNCTION__, no_of_patch_segment,
+    rampatch_patch_info.patch_base_addr);
+
+    /* Initialize the patch base address from the one read from bin file */
+    p_base_addr = rampatch_patch_info.patch_base_addr;
+
+    /*
+    * Depending upon size of the patch payload, download the patches in
+    * segments with a max. size of 239 bytes
+    */
+    for (index = 1; index <= no_of_patch_segment; index++) {
+
+        ALOGI("%s: Downloading patch segment: %d", __FUNCTION__, index);
+
+        /* Frame the HCI CMD PKT to be sent to Controller*/
+        frame_hci_cmd_pkt(cmd, EDL_PATCH_DLD_REQ_CMD, p_base_addr,
+        index, MAX_DATA_PER_SEGMENT);
+
+        /* Total length of the packet to be sent to the Controller */
+        size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+
+        /* Initialize the RSP packet everytime to 0 */
+        memset(rsp, 0x0, HCI_MAX_EVENT_SIZE);
+
+        /* Send HCI Command packet to Controller */
+        err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+        if ( err != size) {
+            ALOGE("Failed to send the patch payload to the Controller!");
+            goto error;
+        }
+
+        /* Read Command Complete Event */
+        err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+        if ( err < 0) {
+            ALOGE("%s: Failed to downlaod patch segment: %d!",
+            __FUNCTION__, index);
+            goto error;
+        }
+        ALOGI("%s: Successfully downloaded patch segment: %d",
+        __FUNCTION__, index);
+    }
+
+    /* Check if any pending patch data to be sent */
+    size = (rampatch_patch_info.patch_length < MAX_DATA_PER_SEGMENT) ?
+        rampatch_patch_info.patch_length :
+        (rampatch_patch_info.patch_length  % MAX_DATA_PER_SEGMENT);
+
+    if (size)
+    {
+        /* Frame the HCI CMD PKT to be sent to Controller*/
+        frame_hci_cmd_pkt(cmd, EDL_PATCH_DLD_REQ_CMD, p_base_addr, index, size);
+
+        /* Initialize the RSP packet everytime to 0 */
+        memset(rsp, 0x0, HCI_MAX_EVENT_SIZE);
+
+        /* Total length of the packet to be sent to the Controller */
+        size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+
+        /* Send HCI Command packet to Controller */
+        err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+        if ( err != size) {
+            ALOGE("Failed to send the patch payload to the Controller!");
+            goto error;
+        }
+
+        /* Read Command Complete Event */
+        err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+        if ( err < 0) {
+            ALOGE("%s: Failed to downlaod patch segment: %d!",
+                __FUNCTION__, index);
+            goto error;
+        }
+
+        ALOGI("%s: Successfully downloaded patch segment: %d",
+        __FUNCTION__, index);
+    }
+
+error:
+    return err;
+}
+
+static int rome_download_rampatch(int fd)
+{
+    int c, tmp, size, index, ret = -1;
+
+    ALOGI("%s: ", __FUNCTION__);
+
+    /* Get handle to the RAMPATCH binary file */
+    ALOGI("%s: Getting handle to the RAMPATCH binary file from %s", __FUNCTION__, ROME_FW_PATH);
+    file = fopen(ROME_FW_PATH, "r");
+    if (file == NULL) {
+        ALOGE("%s: Failed to get handle to the RAMPATCH bin file!",
+        __FUNCTION__);
+        return -ENFILE;
+    }
+
+    /* Allocate memory for the patch headder info */
+    ALOGI("%s: Allocating memory for the patch header", __FUNCTION__);
+    phdr_buffer = (unsigned char *) malloc(PATCH_HDR_LEN + 1);
+    if (phdr_buffer == NULL) {
+        ALOGE("%s: Failed to allocate memory for patch header",
+        __FUNCTION__);
+        goto phdr_alloc_failed;
+    }
+    for (index = 0; index < PATCH_HDR_LEN + 1; index++)
+        phdr_buffer[index] = 0x0;
+
+    /* Read 28 bytes of patch header information */
+    ALOGI("%s: Reading patch header info", __FUNCTION__);
+    index = 0;
+    do {
+        c = fgetc (file);
+        phdr_buffer[index++] = (unsigned char)c;
+    } while (index != PATCH_HDR_LEN);
+
+    /* Save the patch header info into local structure */
+    ALOGI("%s: Saving patch hdr. info", __FUNCTION__);
+    rome_extract_patch_header_info((unsigned char *)phdr_buffer);
+
+    /* Set the patch header info onto the Controller */
+    ret = rome_edl_set_patch_request(fd);
+    if (ret < 0) {
+        ALOGE("%s: Error setting the patchheader info!", __FUNCTION__);
+        goto pdata_alloc_failed;
+    }
+
+    /* Allocate memory for the patch payload */
+    ALOGI("%s: Allocating memory for patch payload", __FUNCTION__);
+    size = rampatch_patch_info.patch_length;
+    pdata_buffer = (unsigned char *) malloc(size+1);
+    if (pdata_buffer == NULL) {
+        ALOGE("%s: Failed to allocate memory for patch payload",
+            __FUNCTION__);
+        goto pdata_alloc_failed;
+    }
+    for (index = 0; index < size+1; index++)
+        pdata_buffer[index] = 0x0;
+
+    /* Read the patch data from Rampatch binary image */
+    ALOGI("%s: Reading patch payload from RAMPATCH file", __FUNCTION__);
+    index = 0;
+    do {
+        c = fgetc (file);
+        pdata_buffer[index++] = (unsigned char)c;
+    } while (c != EOF);
+
+    /* Downloading patches in segments to controller */
+    ret = rome_edl_patch_download_request(fd);
+    if (ret < 0) {
+        ALOGE("%s: Error downloading patch segments!", __FUNCTION__);
+        goto cleanup;
+    }
+cleanup:
+    free(pdata_buffer);
+pdata_alloc_failed:
+    free(phdr_buffer);
+phdr_alloc_failed:
+    fclose(file);
+error:
+    return ret;
+}
+
+int rome_attach_rampatch(int fd)
+{
+    int size, err;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    /* Frame the HCI CMD to be sent to the Controller */
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_ATCH_REQ_CMD, 0,
+        -1, EDL_PATCH_CMD_LEN);
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+
+    /* Send HCI Command packet to Controller */
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to attach the patch payload to the Controller!");
+        goto error;
+    }
+
+    /* Read Command Complete Event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        ALOGE("%s: Failed to attach the patch segment(s)", __FUNCTION__);
+        goto error;
+    }
+error:
+    return err;
+}
+
+int rome_rampatch_reset(int fd)
+{
+    int size, err = 0, flags;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    struct timespec tm = { 0, 100*1000*1000 }; /* 100 ms */
+
+    /* Frame the HCI CMD to be sent to the Controller */
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_RST_REQ_CMD, 0,
+                                        -1, EDL_PATCH_CMD_LEN);
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN);
+
+    /* Send HCI Command packet to Controller */
+    err = do_write(fd, cmd, size);
+    if (err != size) {
+        ALOGE("%s: Send failed with ret value: %d", __FUNCTION__, err);
+        goto error;
+    }
+
+    /*
+    * Controller doesn't sends any response for the patch reset
+    * command. HOST has to wait for 100ms before proceeding.
+    */
+    nanosleep(&tm, NULL);
+
+error:
+    return err;
+}
+
+/* This function is called with q_lock held and q is non-NULL */
+int rome_get_tlv_file(char *file_path)
+{
+    FILE * pFile;
+    long fileSize;
+    int readSize, err = 0, total_segment, remain_size, nvm_length, nvm_index, i;
+    unsigned short nvm_tag_len;
+    tlv_patch_info *ptlv_header;
+    tlv_nvm_hdr *nvm_ptr;
+    unsigned char data_buf[PRINT_BUF_SIZE]={0,};
+    unsigned char *nvm_byte_ptr;
+
+    ALOGI("File Open (%s)", file_path);
+    pFile = fopen ( file_path , "r" );
+    if (pFile==NULL) {;
+        ALOGE("%s File Open Fail", file_path);
+        return -1;
+    }
+
+    /* Get File Size */
+    fseek (pFile , 0 , SEEK_END);
+    fileSize = ftell (pFile);
+    rewind (pFile);
+
+    pdata_buffer = (unsigned char*) malloc (sizeof(char)*fileSize);
+    if (pdata_buffer == NULL) {
+        ALOGE("Allocated Memory failed");
+        fclose (pFile);
+        return -1;
+    }
+
+    /* Copy file into allocated buffer */
+    readSize = fread (pdata_buffer,1,fileSize,pFile);
+
+    /* File Close */
+    fclose (pFile);
+
+    if (readSize != fileSize) {
+        ALOGE("Read file size(%d) not matched with actual file size (%ld bytes)",readSize,fileSize);
+        return -1;
+    }
+
+    ptlv_header = (tlv_patch_info *) pdata_buffer;
+
+    /* To handle different event between rampatch and NVM */
+    gTlv_type = ptlv_header->tlv_type;
+    gTlv_dwndCfg = ptlv_header->tlv.patch.dwnd_cfg;
+
+    if(ptlv_header->tlv_type == TLV_TYPE_PATCH){
+        ALOGI("====================================================");
+        ALOGI("TLV Type\t\t\t : 0x%x", ptlv_header->tlv_type);
+        ALOGI("Length\t\t\t : %d bytes", (ptlv_header->tlv_length1) |
+                                                    (ptlv_header->tlv_length2 << 8) |
+                                                    (ptlv_header->tlv_length3 << 16));
+        ALOGI("Total Length\t\t\t : %d bytes", ptlv_header->tlv.patch.tlv_data_len);
+        ALOGI("Patch Data Length\t\t\t : %d bytes",ptlv_header->tlv.patch.tlv_patch_data_len);
+        ALOGI("Signing Format Version\t : 0x%x", ptlv_header->tlv.patch.sign_ver);
+        ALOGI("Signature Algorithm\t\t : 0x%x", ptlv_header->tlv.patch.sign_algorithm);
+        ALOGI("Event Handling\t\t\t : 0x%x", ptlv_header->tlv.patch.dwnd_cfg);
+        ALOGI("Reserved\t\t\t : 0x%x", ptlv_header->tlv.patch.reserved1);
+        ALOGI("Product ID\t\t\t : 0x%04x\n", ptlv_header->tlv.patch.prod_id);
+        ALOGI("Rom Build Version\t\t : 0x%04x\n", ptlv_header->tlv.patch.build_ver);
+        ALOGI("Patch Version\t\t : 0x%04x\n", ptlv_header->tlv.patch.patch_ver);
+        ALOGI("Reserved\t\t\t : 0x%x\n", ptlv_header->tlv.patch.reserved2);
+        ALOGI("Patch Entry Address\t\t : 0x%x\n", (ptlv_header->tlv.patch.patch_entry_addr));
+        ALOGI("====================================================");
+
+    } else if(ptlv_header->tlv_type == TLV_TYPE_NVM) {
+        ALOGI("====================================================");
+        ALOGI("TLV Type\t\t\t : 0x%x", ptlv_header->tlv_type);
+        ALOGI("Length\t\t\t : %d bytes",  nvm_length = (ptlv_header->tlv_length1) |
+                                                    (ptlv_header->tlv_length2 << 8) |
+                                                    (ptlv_header->tlv_length3 << 16));
+
+        if(nvm_length <= 0)
+            return readSize;
+
+       for(nvm_byte_ptr=(unsigned char *)(nvm_ptr = &(ptlv_header->tlv.nvm)), nvm_index=0;
+             nvm_index < nvm_length ; nvm_ptr = (tlv_nvm_hdr *) nvm_byte_ptr)
+       {
+            ALOGI("TAG ID\t\t\t : %d", nvm_ptr->tag_id);
+            ALOGI("TAG Length\t\t\t : %d", nvm_tag_len = nvm_ptr->tag_len);
+            ALOGI("TAG Pointer\t\t\t : %d", nvm_ptr->tag_ptr);
+            ALOGI("TAG Extended Flag\t\t : %d", nvm_ptr->tag_ex_flag);
+
+            /* Increase nvm_index to NVM data */
+            nvm_index+=sizeof(tlv_nvm_hdr);
+            nvm_byte_ptr+=sizeof(tlv_nvm_hdr);
+
+            /* Write BD Address */
+            if(nvm_ptr->tag_id == TAG_NUM_2){
+                memcpy(nvm_byte_ptr, q->bdaddr, 6);
+                ALOGI("BD Address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x",
+                    *nvm_byte_ptr, *(nvm_byte_ptr+1), *(nvm_byte_ptr+2),
+                    *(nvm_byte_ptr+3), *(nvm_byte_ptr+4), *(nvm_byte_ptr+5));
+            }
+
+            for(i =0;(i<nvm_ptr->tag_len && (i*3 + 2) <PRINT_BUF_SIZE);i++)
+                snprintf((char *) data_buf, PRINT_BUF_SIZE, "%s%.02x ", (char *)data_buf, *(nvm_byte_ptr + i));
+
+            ALOGI("TAG Data\t\t\t : %s", data_buf);
+
+            /* Clear buffer */
+            memset(data_buf, 0x0, PRINT_BUF_SIZE);
+
+            /* increased by tag_len */
+            nvm_index+=nvm_ptr->tag_len;
+            nvm_byte_ptr +=nvm_ptr->tag_len;
+        }
+
+        ALOGI("====================================================");
+
+    } else {
+        ALOGI("TLV Header type is unknown (%d) ", ptlv_header->tlv_type);
+    }
+
+    return readSize;
+}
+
+int rome_tlv_dnld_segment(int fd, int index, int seg_size, unsigned char wait_cc_evt)
+{
+    int size=0, err = -1;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    ALOGI("%s: Downloading TLV Patch segment no.%d, size:%d", __FUNCTION__, index, seg_size);
+
+    /* Frame the HCI CMD PKT to be sent to Controller*/
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_TLV_REQ_CMD, 0, index, seg_size);
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+
+    /* Initialize the RSP packet everytime to 0 */
+    memset(rsp, 0x0, HCI_MAX_EVENT_SIZE);
+
+    /* Send HCI Command packet to Controller */
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to send the patch payload to the Controller! 0x%x", err);
+        return err;
+    }
+
+    if(wait_cc_evt) {
+        err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+        if ( err < 0) {
+            ALOGE("%s: Failed to downlaod patch segment: %d!",  __FUNCTION__, index);
+            return err;
+        }
+    }
+
+    ALOGI("%s: Successfully downloaded patch segment: %d", __FUNCTION__, index);
+    return err;
+}
+
+int rome_tlv_dnld_req(int fd, int tlv_size)
+{
+    int  total_segment, remain_size, i, err = -1;
+    unsigned char wait_cc_evt = TRUE;
+
+    total_segment = tlv_size/MAX_SIZE_PER_TLV_SEGMENT;
+    remain_size = (tlv_size < MAX_SIZE_PER_TLV_SEGMENT)?\
+        tlv_size: (tlv_size%MAX_SIZE_PER_TLV_SEGMENT);
+
+    ALOGI("%s: TLV size: %d, Total Seg num: %d, remain size: %d",
+        __FUNCTION__,tlv_size, total_segment, remain_size);
+
+    if (gTlv_type == TLV_TYPE_PATCH) {
+       /* Prior to Rome version 3.2(including inital few rampatch release of Rome 3.2), the event
+        * handling mechanism is ROME_SKIP_EVT_NONE. After few release of rampatch for Rome 3.2, the
+        * mechamism is changed to ROME_SKIP_EVT_VSE_CC. Rest of the mechanism is not used for now
+        */
+       switch(gTlv_dwndCfg)
+       {
+           case ROME_SKIP_EVT_NONE:
+              wait_vsc_evt = TRUE;
+              wait_cc_evt = TRUE;
+              ALOGI("Event handling type: ROME_SKIP_EVT_NONE");
+              break;
+           case ROME_SKIP_EVT_VSE_CC:
+              wait_vsc_evt = FALSE;
+              wait_cc_evt = FALSE;
+              ALOGI("Event handling type: ROME_SKIP_EVT_VSE_CC");
+              break;
+           /* Not handled for now */
+           case ROME_SKIP_EVT_VSE:
+           case ROME_SKIP_EVT_CC:
+           default:
+              ALOGE("Unsupported Event handling: %d", gTlv_dwndCfg);
+              break;
+       }
+    } else {
+        wait_vsc_evt = TRUE;
+        wait_cc_evt = TRUE;
+    }
+
+    for(i=0;i<total_segment ;i++){
+        if ((i+1) == total_segment) {
+             if ((chipset_ver >= ROME_VER_1_1) && (chipset_ver < ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+               /* If the Rome version is from 1.1 to 3.1
+                * 1. No CCE for the last command segment but all other segment
+                * 2. All the command segments get VSE including the last one
+                */
+                wait_cc_evt = !remain_size ? FALSE: TRUE;
+             } else if ((chipset_ver >= ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+                /* If the Rome version is 3.2
+                 * 1. None of the command segments receive CCE
+                 * 2. No command segments receive VSE except the last one
+                 * 3. If gTlv_dwndCfg is ROME_SKIP_EVT_NONE then the logic is
+                 *    same as Rome 2.1, 2.2, 3.0
+                 */
+                 if (gTlv_dwndCfg == ROME_SKIP_EVT_NONE) {
+                    wait_cc_evt = !remain_size ? FALSE: TRUE;
+                 } else if (gTlv_dwndCfg == ROME_SKIP_EVT_VSE_CC) {
+                    wait_vsc_evt = !remain_size ? TRUE: FALSE;
+                 }
+             }
+        }
+
+        patch_dnld_pending = TRUE;
+        if((err = rome_tlv_dnld_segment(fd, i, MAX_SIZE_PER_TLV_SEGMENT, wait_cc_evt )) < 0)
+            goto error;
+        patch_dnld_pending = FALSE;
+    }
+
+    if ((chipset_ver >= ROME_VER_1_1) && (chipset_ver < ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+       /* If the Rome version is from 1.1 to 3.1
+        * 1. No CCE for the last command segment but all other segment
+        * 2. All the command segments get VSE including the last one
+        */
+        wait_cc_evt = remain_size ? FALSE: TRUE;
+    } else if ((chipset_ver >= ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+        /* If the Rome version is 3.2
+         * 1. None of the command segments receive CCE
+         * 2. No command segments receive VSE except the last one
+         * 3. If gTlv_dwndCfg is ROME_SKIP_EVT_NONE then the logic is
+         *    same as Rome 2.1, 2.2, 3.0
+         */
+        if (gTlv_dwndCfg == ROME_SKIP_EVT_NONE) {
+           wait_cc_evt = remain_size ? FALSE: TRUE;
+        } else if (gTlv_dwndCfg == ROME_SKIP_EVT_VSE_CC) {
+           wait_vsc_evt = remain_size ? TRUE: FALSE;
+        }
+    }
+    patch_dnld_pending = TRUE;
+    if(remain_size) err =rome_tlv_dnld_segment(fd, i, remain_size, wait_cc_evt);
+    patch_dnld_pending = FALSE;
+error:
+    if(patch_dnld_pending) patch_dnld_pending = FALSE;
+    return err;
+}
+
+int rome_download_tlv_file(int fd)
+{
+    int tlv_size, err = -1;
+
+    /* Rampatch TLV file Downloading */
+    pdata_buffer = NULL;
+    if((tlv_size = rome_get_tlv_file(rampatch_file_path)) < 0)
+        goto error;
+
+    if((err =rome_tlv_dnld_req(fd, tlv_size)) <0 )
+        goto error;
+
+    if (pdata_buffer != NULL){
+        free (pdata_buffer);
+        pdata_buffer = NULL;
+    }
+nvm_download:
+    if(!nvm_file_path) {
+        ALOGI("%s: nvm file is not available", __FUNCTION__);
+        err = 0; // in case of nvm/rampatch is not available
+        goto error;
+    }
+
+   /* NVM TLV file Downloading */
+    if((tlv_size = rome_get_tlv_file(nvm_file_path)) <= 0)
+        goto error;
+
+    if((err =rome_tlv_dnld_req(fd, tlv_size)) <0 )
+        goto error;
+
+error:
+    if (pdata_buffer != NULL)
+        free (pdata_buffer);
+
+    return err;
+}
+
+int rome_1_0_nvm_tag_dnld(int fd)
+{
+    int i, size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+#if (NVM_VERSION >= ROME_1_0_100019)
+    unsigned char cmds[MAX_TAG_CMD][HCI_MAX_CMD_SIZE] =
+    {
+        /* Tag 2 */ /* BD Address */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     9,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     2,
+            /* Tag Len */      6,
+            /* Tag Value */   0x77,0x78,0x23,0x01,0x56,0x22
+         },
+        /* Tag 6 */ /* Bluetooth Support Features */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     11,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     6,
+            /* Tag Len */      8,
+            /* Tag Value */   0xFF,0xFE,0x8B,0xFE,0xD8,0x3F,0x5B,0x8B
+         },
+        /* Tag 17 */ /* HCI Transport Layer Setting */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     11,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     17,
+            /* Tag Len */      8,
+            /* Tag Value */   0x82,0x01,0x0E,0x08,0x04,0x32,0x0A,0x00
+         },
+        /* Tag 35 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     58,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     35,
+            /* Tag Len */      55,
+            /* Tag Value */   0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x58, 0x59,
+                                      0x0E, 0x0E, 0x16, 0x16, 0x16, 0x1E, 0x26, 0x5F, 0x2F, 0x5F,
+                                      0x0E, 0x0E, 0x16, 0x16, 0x16, 0x1E, 0x26, 0x5F, 0x2F, 0x5F,
+                                      0x0C, 0x18, 0x14, 0x24, 0x40, 0x4C, 0x70, 0x80, 0x80, 0x80,
+                                      0x0C, 0x18, 0x14, 0x24, 0x40, 0x4C, 0x70, 0x80, 0x80, 0x80,
+                                      0x1B, 0x14, 0x01, 0x04, 0x48
+         },
+        /* Tag 36 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     15,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     36,
+            /* Tag Len */      12,
+            /* Tag Value */   0x0F,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x04,0x00
+         },
+        /* Tag 39 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     7,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     39,
+            /* Tag Len */      4,
+            /* Tag Value */   0x12,0x00,0x00,0x00
+         },
+        /* Tag 41 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     91,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     41,
+            /* Tag Len */      88,
+            /* Tag Value */   0x15, 0x00, 0x00, 0x00, 0xF6, 0x02, 0x00, 0x00, 0x76, 0x00,
+                                      0x1E, 0x00, 0x29, 0x02, 0x1F, 0x00, 0x61, 0x00, 0x1A, 0x00,
+                                      0x76, 0x00, 0x1E, 0x00, 0x7D, 0x00, 0x40, 0x00, 0x91, 0x00,
+                                      0x06, 0x00, 0x92, 0x00, 0x03, 0x00, 0xA6, 0x01, 0x50, 0x00,
+                                      0xAA, 0x01, 0x15, 0x00, 0xAB, 0x01, 0x0A, 0x00, 0xAC, 0x01,
+                                      0x00, 0x00, 0xB0, 0x01, 0xC5, 0x00, 0xB3, 0x01, 0x03, 0x00,
+                                      0xB4, 0x01, 0x13, 0x00, 0xB5, 0x01, 0x0C, 0x00, 0xC5, 0x01,
+                                      0x0D, 0x00, 0xC6, 0x01, 0x10, 0x00, 0xCA, 0x01, 0x2B, 0x00,
+                                      0xCB, 0x01, 0x5F, 0x00, 0xCC, 0x01, 0x48, 0x00
+         },
+        /* Tag 42 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     63,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     42,
+            /* Tag Len */      60,
+            /* Tag Value */   0xD7, 0xC0, 0x00, 0x00, 0x8F, 0x5C, 0x02, 0x00, 0x80, 0x47,
+                                      0x60, 0x0C, 0x70, 0x4C, 0x00, 0x00, 0x00, 0x01, 0x1F, 0x01,
+                                      0x42, 0x01, 0x69, 0x01, 0x95, 0x01, 0xC7, 0x01, 0xFE, 0x01,
+                                      0x3D, 0x02, 0x83, 0x02, 0xD1, 0x02, 0x29, 0x03, 0x00, 0x0A,
+                                      0x10, 0x00, 0x1F, 0x00, 0x3F, 0x00, 0x7F, 0x00, 0xFD, 0x00,
+                                      0xF9, 0x01, 0xF1, 0x03, 0xDE, 0x07, 0x00, 0x00, 0x9A, 0x01
+         },
+        /* Tag 84 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     153,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     84,
+            /* Tag Len */      150,
+            /* Tag Value */   0x7C, 0x6A, 0x59, 0x47, 0x19, 0x36, 0x35, 0x25, 0x25, 0x28,
+                                      0x2C, 0x2B, 0x2B, 0x28, 0x2C, 0x28, 0x29, 0x28, 0x29, 0x28,
+                                      0x29, 0x29, 0x2C, 0x29, 0x2C, 0x29, 0x2C, 0x28, 0x29, 0x28,
+                                      0x29, 0x28, 0x29, 0x2A, 0x00, 0x00, 0x2C, 0x2A, 0x2C, 0x18,
+                                      0x98, 0x98, 0x98, 0x98, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E,
+                                      0x1E, 0x13, 0x1E, 0x1E, 0x1E, 0x1E, 0x13, 0x13, 0x11, 0x13,
+                                      0x1E, 0x1E, 0x13, 0x12, 0x12, 0x12, 0x11, 0x12, 0x1F, 0x12,
+                                      0x12, 0x12, 0x10, 0x0C, 0x18, 0x0D, 0x01, 0x01, 0x01, 0x01,
+                                      0x01, 0x01, 0x01, 0x0C, 0x01, 0x01, 0x01, 0x01, 0x0D, 0x0D,
+                                      0x0E, 0x0D, 0x01, 0x01, 0x0D, 0x0D, 0x0D, 0x0D, 0x0F, 0x0D,
+                                      0x10, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, 0x05, 0x10, 0x03, 0x00,
+                                      0x7E, 0x7B, 0x7B, 0x72, 0x71, 0x50, 0x50, 0x50, 0x00, 0x40,
+                                      0x60, 0x60, 0x30, 0x08, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00,
+                                      0x00, 0x00, 0x00, 0x00, 0x08, 0x16, 0x16, 0x08, 0x08, 0x00,
+                                      0x00, 0x00, 0x1E, 0x34, 0x2B, 0x1B, 0x23, 0x2B, 0x15, 0x0D
+         },
+        /* Tag 85 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     119,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     85,
+            /* Tag Len */      116,
+            /* Tag Value */   0x03, 0x00, 0x38, 0x00, 0x45, 0x77, 0x00, 0xE8, 0x00, 0x59,
+                                      0x01, 0xCA, 0x01, 0x3B, 0x02, 0xAC, 0x02, 0x1D, 0x03, 0x8E,
+                                      0x03, 0x00, 0x89, 0x01, 0x0E, 0x02, 0x5C, 0x02, 0xD7, 0x02,
+                                      0xF8, 0x08, 0x01, 0x00, 0x1F, 0x00, 0x0A, 0x02, 0x55, 0x02,
+                                      0x00, 0x35, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xD7, 0x00, 0x00,
+                                      0x00, 0x1E, 0xDE, 0x00, 0x00, 0x00, 0x14, 0x0F, 0x0A, 0x0F,
+                                      0x0A, 0x0C, 0x0C, 0x0C, 0x0C, 0x04, 0x04, 0x04, 0x0C, 0x0C,
+                                      0x0C, 0x0C, 0x06, 0x06, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+                                      0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00,
+                                      0x06, 0x0F, 0x14, 0x05, 0x47, 0xCF, 0x77, 0x00, 0x00, 0x00,
+                                      0x00, 0x00, 0x00, 0xAC, 0x7C, 0xFF, 0x40, 0x00, 0x00, 0x00,
+                                      0x12, 0x04, 0x04, 0x01, 0x04, 0x03
+         },
+        {TAG_END}
+    };
+#elif (NVM_VERSION == ROME_1_0_6002)
+    unsigned char cmds[MAX_TAG_CMD][HCI_MAX_CMD_SIZE] =
+    {
+        /* Tag 2 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     9,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     2,
+            /* Tag Len */      6,
+            /* Tag Value */   0x77,0x78,0x23,0x01,0x56,0x22 /* BD Address */
+         },
+        /* Tag 6 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     11,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     6,
+            /* Tag Len */      8,
+            /* Tag Value */   0xFF,0xFE,0x8B,0xFE,0xD8,0x3F,0x5B,0x8B
+         },
+        /* Tag 17 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     11,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     17,
+            /* Tag Len */      8,
+            /* Tag Value */   0x82,0x01,0x0E,0x08,0x04,0x32,0x0A,0x00
+         },
+        /* Tag 36 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     15,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     36,
+            /* Tag Len */      12,
+            /* Tag Value */   0x0F,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x04,0x00
+         },
+
+        /* Tag 39 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     7,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     39,
+            /* Tag Len */      4,
+            /* Tag Value */   0x12,0x00,0x00,0x00
+         },
+
+        /* Tag 41 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     199,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     41,
+            /* Tag Len */      196,
+            /* Tag Value */   0x30,0x00,0x00,0x00,0xD5,0x00,0x0E,0x00,0xD6,0x00,0x0E,0x00,
+                                      0xD7,0x00,0x16,0x00,0xD8,0x00,0x16,0x00,0xD9,0x00,0x16,0x00,
+                                      0xDA,0x00,0x1E,0x00,0xDB,0x00,0x26,0x00,0xDC,0x00,0x5F,0x00,
+                                      0xDD,0x00,0x2F,0x00,0xDE,0x00,0x5F,0x00,0xE0,0x00,0x0E,0x00,
+                                      0xE1,0x00,0x0E,0x00,0xE2,0x00,0x16,0x00,0xE3,0x00,0x16,0x00,
+                                      0xE4,0x00,0x16,0x00,0xE5,0x00,0x1E,0x00,0xE6,0x00,0x26,0x00,
+                                      0xE7,0x00,0x5F,0x00,0xE8,0x00,0x2F,0x00,0xE9,0x00,0x5F,0x00,
+                                      0xEC,0x00,0x0C,0x00,0xED,0x00,0x08,0x00,0xEE,0x00,0x14,0x00,
+                                      0xEF,0x00,0x24,0x00,0xF0,0x00,0x40,0x00,0xF1,0x00,0x4C,0x00,
+                                      0xF2,0x00,0x70,0x00,0xF3,0x00,0x80,0x00,0xF4,0x00,0x80,0x00,
+                                      0xF5,0x00,0x80,0x00,0xF8,0x00,0x0C,0x00,0xF9,0x00,0x18,0x00,
+                                      0xFA,0x00,0x14,0x00,0xFB,0x00,0x24,0x00,0xFC,0x00,0x40,0x00,
+                                      0xFD,0x00,0x4C,0x00,0xFE,0x00,0x70,0x00,0xFF,0x00,0x80,0x00,
+                                      0x00,0x01,0x80,0x00,0x01,0x01,0x80,0x00,0x04,0x01,0x1B,0x00,
+                                      0x05,0x01,0x14,0x00,0x06,0x01,0x01,0x00,0x07,0x01,0x04,0x00,
+                                      0x08,0x01,0x00,0x00,0x09,0x01,0x00,0x00,0x0A,0x01,0x03,0x00,
+                                      0x0B,0x01,0x03,0x00
+         },
+
+        /* Tag 44 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     44,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     44,
+            /* Tag Len */      41,
+            /* Tag Value */   0x6F,0x0A,0x00,0x00,0x00,0x00,0x00,0x50,0xFF,0x10,0x02,0x02,
+                                      0x01,0x00,0x14,0x01,0x06,0x28,0xA0,0x62,0x03,0x64,0x01,0x01,
+                                      0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xFF,0x10,0x02,0x01,
+                                      0x00,0x14,0x01,0x02,0x03
+         },
+        {TAG_END}
+    };
+#endif
+
+    ALOGI("%s: Start sending NVM Tags (ver: 0x%x)", __FUNCTION__, (unsigned int) NVM_VERSION);
+
+    for (i=0; (i < MAX_TAG_CMD) && (cmds[i][0] != TAG_END); i++)
+    {
+        /* Write BD Address */
+        if(cmds[i][TAG_NUM_OFFSET] == TAG_NUM_2){
+            memcpy(&cmds[i][TAG_BDADDR_OFFSET], q->bdaddr, 6);
+            ALOGI("BD Address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+                cmds[i][TAG_BDADDR_OFFSET ], cmds[i][TAG_BDADDR_OFFSET + 1],
+                cmds[i][TAG_BDADDR_OFFSET + 2], cmds[i][TAG_BDADDR_OFFSET + 3],
+                cmds[i][TAG_BDADDR_OFFSET + 4], cmds[i][TAG_BDADDR_OFFSET + 5]);
+        }
+        size = cmds[i][3] + HCI_COMMAND_HDR_SIZE + 1;
+        /* Send HCI Command packet to Controller */
+        err = hci_send_vs_cmd(fd, (unsigned char *)&cmds[i][0], rsp, size);
+        if ( err != size) {
+            ALOGE("Failed to attach the patch payload to the Controller!");
+            goto error;
+        }
+
+        /* Read Command Complete Event - This is extra routine for ROME 1.0. From ROM 2.0, it should be removed. */
+        err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+        if ( err < 0) {
+            ALOGE("%s: Failed to get patch version(s)", __FUNCTION__);
+            goto error;
+        }
+    }
+
+error:
+    return err;
+}
+
+
+
+int rome_patch_ver_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    /* Frame the HCI CMD to be sent to the Controller */
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_VER_REQ_CMD, 0,
+    -1, EDL_PATCH_CMD_LEN);
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN);
+
+    /* Send HCI Command packet to Controller */
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to attach the patch payload to the Controller!");
+        goto error;
+    }
+
+    /* Read Command Complete Event - This is extra routine for ROME 1.0. From ROM 2.0, it should be removed. */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        ALOGE("%s: Failed to get patch version(s)", __FUNCTION__);
+        goto error;
+    }
+error:
+    return err;
+
+}
+
+int rome_get_build_info_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    /* Frame the HCI CMD to be sent to the Controller */
+    frame_hci_cmd_pkt(cmd, EDL_GET_BUILD_INFO, 0,
+    -1, EDL_PATCH_CMD_LEN);
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN);
+
+    /* Send HCI Command packet to Controller */
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to send get build info cmd to the SoC!");
+        goto error;
+    }
+
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        ALOGE("%s: Failed to get build info", __FUNCTION__);
+        goto error;
+    }
+error:
+    return err;
+
+}
+
+
+int rome_set_baudrate_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+    hci_command_hdr *cmd_hdr;
+    int flags;
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+    cmd[0]  = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, EDL_SET_BAUDRATE_CMD_OCF);
+    cmd_hdr->plen     = VSC_SET_BAUDRATE_REQ_LEN;
+    cmd[4]  = BAUDRATE_3000000;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + VSC_SET_BAUDRATE_REQ_LEN);
+
+    /* Flow off during baudrate change */
+    if ((err = userial_vendor_ioctl(USERIAL_OP_FLOW_OFF , &flags)) < 0)
+    {
+      ALOGE("%s: HW Flow-off error: 0x%x\n", __FUNCTION__, err);
+      goto error;
+    }
+
+    /* Send the HCI command packet to UART for transmission */
+    err = do_write(fd, cmd, size);
+    if (err != size) {
+        ALOGE("%s: Send failed with ret value: %d", __FUNCTION__, err);
+        goto error;
+    }
+
+    /* Change Local UART baudrate to high speed UART */
+    userial_vendor_set_baud(USERIAL_BAUD_3M);
+
+    /* Flow on after changing local uart baudrate */
+    if ((err = userial_vendor_ioctl(USERIAL_OP_FLOW_ON , &flags)) < 0)
+    {
+        ALOGE("%s: HW Flow-on error: 0x%x \n", __FUNCTION__, err);
+        return err;
+    }
+
+    /* Check for response from the Controller */
+    if ((err =read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE)) < 0) {
+            ALOGE("%s: Failed to get HCI-VS Event from SOC", __FUNCTION__);
+            goto error;
+    }
+
+    ALOGI("%s: Received HCI-Vendor Specific Event from SOC", __FUNCTION__);
+
+    /* Wait for command complete event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        ALOGE("%s: Failed to set patch info on Controller", __FUNCTION__);
+        goto error;
+    }
+
+error:
+    return err;
+
+}
+
+
+int rome_hci_reset_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+    hci_command_hdr *cmd_hdr;
+    int flags;
+
+    ALOGI("%s: HCI RESET ", __FUNCTION__);
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+    cmd[0]  = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = HCI_RESET;
+    cmd_hdr->plen   = 0;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE);
+
+    /* Flow off during baudrate change */
+    if ((err = userial_vendor_ioctl(USERIAL_OP_FLOW_OFF , &flags)) < 0)
+    {
+      ALOGE("%s: HW Flow-off error: 0x%x\n", __FUNCTION__, err);
+      goto error;
+    }
+
+    /* Send the HCI command packet to UART for transmission */
+    ALOGI("%s: HCI CMD: 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, cmd[0], cmd[1], cmd[2], cmd[3]);
+    err = do_write(fd, cmd, size);
+    if (err != size) {
+        ALOGE("%s: Send failed with ret value: %d", __FUNCTION__, err);
+        goto error;
+    }
+
+    /* Change Local UART baudrate to high speed UART */
+    userial_vendor_set_baud(USERIAL_BAUD_3M);
+
+    /* Flow on after changing local uart baudrate */
+    if ((err = userial_vendor_ioctl(USERIAL_OP_FLOW_ON , &flags)) < 0)
+    {
+        ALOGE("%s: HW Flow-on error: 0x%x \n", __FUNCTION__, err);
+        return err;
+    }
+
+    /* Wait for command complete event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        ALOGE("%s: Failed to set patch info on Controller", __FUNCTION__);
+        goto error;
+    }
+
+error:
+    return err;
+
+}
+
+
+int rome_hci_reset(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+    hci_command_hdr *cmd_hdr;
+    int flags;
+
+    ALOGI("%s: HCI RESET ", __FUNCTION__);
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+    cmd[0]  = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = HCI_RESET;
+    cmd_hdr->plen   = 0;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE);
+    err = do_write(fd, cmd, size);
+    if (err != size) {
+        ALOGE("%s: Send failed with ret value: %d", __FUNCTION__, err);
+        err = -1;
+        goto error;
+    }
+
+    /* Wait for command complete event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        ALOGE("%s: Failed to set patch info on Controller", __FUNCTION__);
+        goto error;
+    }
+
+error:
+    return err;
+
+}
+
+int rome_wipower_current_charging_status_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+    hci_command_hdr *cmd_hdr;
+    int flags;
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+    cmd[0]  = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, EDL_WIPOWER_VS_CMD_OCF);
+    cmd_hdr->plen     = EDL_WIP_QUERY_CHARGING_STATUS_LEN;
+    cmd[4]  = EDL_WIP_QUERY_CHARGING_STATUS_CMD;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_WIP_QUERY_CHARGING_STATUS_LEN);
+
+    ALOGD("%s: Sending EDL_WIP_QUERY_CHARGING_STATUS_CMD", __FUNCTION__);
+    ALOGD("HCI-CMD: \t0x%x \t0x%x \t0x%x \t0x%x \t0x%x", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+
+    err = hci_send_wipower_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to send EDL_WIP_QUERY_CHARGING_STATUS_CMD command!");
+        goto error;
+    }
+
+    /* Check for response from the Controller */
+    if (read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE) < 0) {
+        err = -ETIMEDOUT;
+        ALOGI("%s: WP Failed to get HCI-VS Event from SOC", __FUNCTION__);
+        goto error;
+    }
+
+    /* Read Command Complete Event - This is extra routine for ROME 1.0. From ROM 2.0, it should be removed. */
+    if (rsp[4] >= NON_WIPOWER_MODE) {
+        err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+        if (err < 0) {
+            ALOGE("%s: Failed to get charging status", __FUNCTION__);
+            goto error;
+        }
+    }
+
+error:
+    return err;
+}
+
+int addon_feature_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+    hci_command_hdr *cmd_hdr;
+    int flags;
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+    cmd[0]  = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, HCI_VS_GET_ADDON_FEATURES_SUPPORT);
+    cmd_hdr->plen     = 0x00;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE);
+
+    ALOGD("%s: Sending HCI_VS_GET_ADDON_FEATURES_SUPPORT", __FUNCTION__);
+    ALOGD("HCI-CMD: \t0x%x \t0x%x \t0x%x \t0x%x", cmd[0], cmd[1], cmd[2], cmd[3]);
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to send HCI_VS_GET_ADDON_FEATURES_SUPPORT command!");
+        goto error;
+    }
+
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if (err < 0) {
+        ALOGE("%s: Failed to get feature request", __FUNCTION__);
+        goto error;
+    }
+error:
+    return err;
+}
+
+
+int check_embedded_mode(int fd) {
+    int err = 0;
+
+    wipower_flag = 0;
+    /* Get current wipower charging status */
+    if ((err = rome_wipower_current_charging_status_req(fd)) < 0)
+    {
+        ALOGI("%s: Wipower status req failed (0x%x)", __FUNCTION__, err);
+    }
+    usleep(500);
+
+    ALOGE("%s: wipower_flag: %d", __FUNCTION__, wipower_flag);
+
+    return wipower_flag;
+}
+
+int rome_get_addon_feature_list(int fd) {
+    int err = 0;
+
+    /* Get addon features that are supported by FW */
+    if ((err = addon_feature_req(fd)) < 0)
+    {
+        ALOGE("%s: failed (0x%x)", __FUNCTION__, err);
+    }
+    return err;
+}
+
+int rome_wipower_forward_handoff_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+    hci_command_hdr *cmd_hdr;
+    int flags;
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+    cmd[0]  = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, EDL_WIPOWER_VS_CMD_OCF);
+    cmd_hdr->plen     = EDL_WIP_START_HANDOFF_TO_HOST_LEN;
+    cmd[4]  = EDL_WIP_START_HANDOFF_TO_HOST_CMD;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_WIP_START_HANDOFF_TO_HOST_LEN);
+
+    ALOGD("%s: Sending EDL_WIP_START_HANDOFF_TO_HOST_CMD", __FUNCTION__);
+    ALOGD("HCI-CMD: \t0x%x \t0x%x \t0x%x \t0x%x \t0x%x", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+    err = hci_send_wipower_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to send EDL_WIP_START_HANDOFF_TO_HOST_CMD command!");
+        goto error;
+    }
+
+    /* Check for response from the Controller */
+    if (read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE) < 0) {
+        err = -ETIMEDOUT;
+        ALOGI("%s: WP Failed to get HCI-VS Event from SOC", __FUNCTION__);
+        goto error;
+    }
+
+error:
+    return err;
+}
+
+
+void enable_controller_log (int fd, unsigned char wait_for_evt)
+{
+   int ret = 0;
+   /* VS command to enable controller logging to the HOST. By default it is disabled */
+   unsigned char cmd[6] = {0x01, 0x17, 0xFC, 0x02, 0x00, 0x00};
+   unsigned char rsp[HCI_MAX_EVENT_SIZE];
+   char value[PROPERTY_VALUE_MAX] = {'\0'};
+
+   property_get("persist.service.bdroid.soclog", value, "false");
+
+   // value at cmd[5]: 1 - to enable, 0 - to disable
+   ret = (strcmp(value, "true") == 0) ? cmd[5] = 0x01: 0;
+   ALOGI("%s: %d", __func__, ret);
+   /* Ignore vsc evt if wait_for_evt is true */
+   if (wait_for_evt) wait_vsc_evt = FALSE;
+
+   ret = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, 6);
+   if (ret != 6) {
+       ALOGE("%s: command failed", __func__);
+   }
+   /*Ignore hci_event if wait_for_evt is true*/
+   if (wait_for_evt)
+       goto end;
+   ret = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+   if (ret < 0) {
+       ALOGE("%s: Failed to get CC for enable SoC log", __FUNCTION__);
+   }
+end:
+   wait_vsc_evt = TRUE;
+   return;
+}
+
+
+/* This function is called with q_lock held and q is non-NULL */
+static int disable_internal_ldo(int fd)
+{
+    int ret = 0;
+    if (q->enable_extldo) {
+        unsigned char cmd[5] = {0x01, 0x0C, 0xFC, 0x01, 0x32};
+        unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+        ALOGI(" %s ", __FUNCTION__);
+        ret = do_write(fd, cmd, 5);
+        if (ret != 5) {
+            ALOGE("%s: Send failed with ret value: %d", __FUNCTION__, ret);
+            ret = -1;
+        } else {
+            /* Wait for command complete event */
+            ret = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+            if ( ret < 0) {
+                ALOGE("%s: Failed to get response from controller", __FUNCTION__);
+            }
+        }
+    }
+    return ret;
+}
+
+int rome_soc_init(int fd, char *bdaddr)
+{
+    int err = -1, size = 0;
+    dnld_fd = fd;
+    ALOGI(" %s ", __FUNCTION__);
+    RESERVED(bdaddr);
+
+    /* If wipower charging is going on in embedded mode then start hand off req */
+    if (wipower_flag == WIPOWER_IN_EMBEDDED_MODE && wipower_handoff_ready != NON_WIPOWER_MODE)
+    {
+        wipower_flag = 0;
+        wipower_handoff_ready = 0;
+        if ((err = rome_wipower_forward_handoff_req(fd)) < 0)
+        {
+            ALOGI("%s: Wipower handoff failed (0x%x)", __FUNCTION__, err);
+        }
+    }
+
+    /* Get Rome version information */
+    if((err = rome_patch_ver_req(fd)) <0){
+        ALOGI("%s: Fail to get Rome Version (0x%x)", __FUNCTION__, err);
+        goto error;
+    }
+
+    ALOGI("%s: Chipset Version (0x%08x)", __FUNCTION__, chipset_ver);
+
+    switch (chipset_ver){
+        case ROME_VER_1_0:
+            {
+                /* Set and Download the RAMPATCH */
+                ALOGI("%s: Setting Patch Header & Downloading Patches", __FUNCTION__);
+                err = rome_download_rampatch(fd);
+                if (err < 0) {
+                    ALOGE("%s: DOWNLOAD RAMPATCH failed!", __FUNCTION__);
+                    goto error;
+                }
+                ALOGI("%s: DOWNLOAD RAMPTACH complete", __FUNCTION__);
+
+                /* Attach the RAMPATCH */
+                ALOGI("%s: Attaching the patches", __FUNCTION__);
+                err = rome_attach_rampatch(fd);
+                if (err < 0) {
+                    ALOGE("%s: ATTACH RAMPATCH failed!", __FUNCTION__);
+                    goto error;
+                }
+                ALOGI("%s: ATTACH RAMPTACH complete", __FUNCTION__);
+
+                /* Send Reset */
+                size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN);
+                err = rome_rampatch_reset(fd);
+                if ( err < 0 ) {
+                    ALOGE("Failed to RESET after RAMPATCH upgrade!");
+                    goto error;
+                }
+
+                /* NVM download */
+                ALOGI("%s: Downloading NVM", __FUNCTION__);
+                err = rome_1_0_nvm_tag_dnld(fd);
+                if ( err <0 ) {
+                    ALOGE("Downloading NVM Failed !!");
+                    goto error;
+                }
+
+                /* Change baud rate 115.2 kbps to 3Mbps*/
+                err = rome_hci_reset_req(fd);
+                if (err < 0) {
+                    ALOGE("HCI Reset Failed !!");
+                    goto error;
+                }
+
+                ALOGI("HCI Reset is done\n");
+            }
+            break;
+        case ROME_VER_1_1:
+            rampatch_file_path = ROME_RAMPATCH_TLV_PATH;
+            nvm_file_path = ROME_NVM_TLV_PATH;
+            goto download;
+        case ROME_VER_1_3:
+            rampatch_file_path = ROME_RAMPATCH_TLV_1_0_3_PATH;
+            nvm_file_path = ROME_NVM_TLV_1_0_3_PATH;
+            goto download;
+        case ROME_VER_2_1:
+            rampatch_file_path = ROME_RAMPATCH_TLV_2_0_1_PATH;
+            nvm_file_path = ROME_NVM_TLV_2_0_1_PATH;
+            goto download;
+        case ROME_VER_3_0:
+            rampatch_file_path = ROME_RAMPATCH_TLV_3_0_0_PATH;
+            nvm_file_path = ROME_NVM_TLV_3_0_0_PATH;
+            fw_su_info = ROME_3_1_FW_SU;
+            fw_su_offset = ROME_3_1_FW_SW_OFFSET;
+            goto download;
+        case ROME_VER_3_2:
+            rampatch_file_path = ROME_RAMPATCH_TLV_3_0_2_PATH;
+            nvm_file_path = ROME_NVM_TLV_3_0_2_PATH;
+            fw_su_info = ROME_3_2_FW_SU;
+            fw_su_offset =  ROME_3_2_FW_SW_OFFSET;
+
+download:
+            /* Change baud rate 115.2 kbps to 3Mbps*/
+            err = rome_set_baudrate_req(fd);
+            if (err < 0) {
+                ALOGE("%s: Baud rate change failed!", __FUNCTION__);
+                goto error;
+            }
+            ALOGI("%s: Baud rate changed successfully ", __FUNCTION__);
+            /* Donwload TLV files (rampatch, NVM) */
+            err = rome_download_tlv_file(fd);
+            if (err < 0) {
+                ALOGE("%s: Download TLV file failed!", __FUNCTION__);
+                goto error;
+            }
+            ALOGI("%s: Download TLV file successfully ", __FUNCTION__);
+
+            /* Get SU FM label information */
+            if((err = rome_get_build_info_req(fd)) <0){
+                ALOGI("%s: Fail to get Rome FW SU Build info (0x%x)", __FUNCTION__, err);
+                //Ignore the failure of ROME FW SU label information
+                err = 0;
+            }
+
+            /* Disable internal LDO to use external LDO instead*/
+            err = disable_internal_ldo(fd);
+
+            /* Send HCI Reset */
+            err = rome_hci_reset(fd);
+            if ( err <0 ) {
+                ALOGE("HCI Reset Failed !!");
+                goto error;
+            }
+
+            ALOGI("HCI Reset is done\n");
+
+            break;
+        default:
+            ALOGI("%s: Detected unknown SoC version: 0x%08x", __FUNCTION__, chipset_ver);
+            err = -1;
+            break;
+    }
+
+error:
+    dnld_fd = -1;
+    return err;
+}
diff --git a/sdm845/libbt-vendor/vnd_buildcfg.mk b/sdm845/libbt-vendor/vnd_buildcfg.mk
new file mode 100644
index 0000000..d18e121
--- /dev/null
+++ b/sdm845/libbt-vendor/vnd_buildcfg.mk
@@ -0,0 +1,32 @@
+#
+# Copyright 2012 The Android Open Source Project
+#
+# 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.
+#
+
+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)