summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2017-12-06 23:18:30 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-12-06 23:18:30 +0000
commitc8fdc0c1310af6aa6c2f3ffc081d81e90dcc3768 (patch)
tree59fdfdf8f2f4b63726eddf061e57f6e6ed4ffe9c
parent3c54d85c5b99a3dc9efecaf1856bbdbbff439923 (diff)
parent9490ad1f699812d07a429bd002070dc4e05f18c3 (diff)
downloadbt-c8fdc0c1310af6aa6c2f3ffc081d81e90dcc3768.tar.gz
Merge "DO NOT MERGE: Merge Oreo MR1 into master"
-rw-r--r--Android.mk24
-rw-r--r--msm8998/libbt-vendor/Android.mk3
-rw-r--r--msm8998/libbt-vendor/include/hci_uart.h1
-rw-r--r--msm8998/libbt-vendor/include/hw_ar3k.h2
-rw-r--r--msm8998/libbt-vendor/src/bt_vendor_qcom.c24
-rw-r--r--msm8998/libbt-vendor/src/hardware.c22
-rw-r--r--msm8998/libbt-vendor/src/hci_smd.c13
-rw-r--r--msm8998/libbt-vendor/src/hci_uart.c14
-rw-r--r--msm8998/libbt-vendor/src/hw_ar3k.c33
-rw-r--r--msm8998/libbt-vendor/src/hw_rome.c33
-rw-r--r--sdm845/Android.mk3
-rwxr-xr-xsdm845/CleanSpec.mk54
-rw-r--r--sdm845/libbt-vendor/Android.mk88
-rw-r--r--sdm845/libbt-vendor/NOTICE190
-rw-r--r--sdm845/libbt-vendor/include/bt_vendor_persist.h69
-rw-r--r--sdm845/libbt-vendor/include/bt_vendor_qcom.h97
-rw-r--r--sdm845/libbt-vendor/include/hci_smd.h37
-rw-r--r--sdm845/libbt-vendor/include/hci_uart.h263
-rw-r--r--sdm845/libbt-vendor/include/hw_ar3k.h164
-rw-r--r--sdm845/libbt-vendor/include/hw_rome.h290
-rw-r--r--sdm845/libbt-vendor/include/vnd_generic.txt9
-rw-r--r--sdm845/libbt-vendor/include/vnd_mako.txt9
-rw-r--r--sdm845/libbt-vendor/src/bt_vendor_persist.cpp91
-rwxr-xr-xsdm845/libbt-vendor/src/bt_vendor_qcom.c1483
-rw-r--r--sdm845/libbt-vendor/src/hardware.c194
-rw-r--r--sdm845/libbt-vendor/src/hci_smd.c161
-rw-r--r--sdm845/libbt-vendor/src/hci_uart.c526
-rw-r--r--sdm845/libbt-vendor/src/hw_ar3k.c1488
-rw-r--r--sdm845/libbt-vendor/src/hw_rome.c1950
-rw-r--r--sdm845/libbt-vendor/vnd_buildcfg.mk32
30 files changed, 7289 insertions, 78 deletions
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 841c3c4..2bb2283 100644
--- a/msm8998/libbt-vendor/Android.mk
+++ b/msm8998/libbt-vendor/Android.mk
@@ -66,6 +66,9 @@ LOCAL_SHARED_LIBRARIES := \
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 @@ static int init(const bt_vendor_callbacks_t *cb, unsigned char *bdaddr)
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 "bt_hci_bdroid.h"
+#include "bt_vendor_qcom.h"
+#include <ctype.h>
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <cutils/properties.h>
+#include <signal.h>
#include <stdlib.h>
-#include "bt_hci_bdroid.h"
-#include "bt_vendor_qcom.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 @@ extern "C" {
#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 "bt_hci_bdroid.h"
+#include "bt_vendor_qcom.h"
+#include "bt_vendor_qcom.h"
+#include "hci_uart.h"
+#include "hw_ar3k.h"
+
+#include <ctype.h>
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <cutils/properties.h>
+#include <signal.h>
#include <stdlib.h>
-#include <termios.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 "bt_hci_bdroid.h"
-#include "bt_vendor_qcom.h"
-#include "hci_uart.h"
-#include "hw_ar3k.h"
-#include "bt_vendor_qcom.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 @@ extern "C" {
#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)