Bluetooth: load btaddr from NV if QCOM_BT_USE_BTNV is set

- OSS builds never set QCPATH, so we should instead use libdl
  so devices that need to read btaddr from NV can still build
  from source.

Change-Id: Ib38dc356c7a3458f57935d113e068e6637d4795f
diff --git a/libbt-vendor/Android.mk b/libbt-vendor/Android.mk
index 6ef6902..e3a9dfb 100644
--- a/libbt-vendor/Android.mk
+++ b/libbt-vendor/Android.mk
@@ -77,10 +77,15 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)
 endif
 
-ifneq ($(QCPATH),)
+ifeq ($(QCOM_BT_USE_BTNV),true)
 LOCAL_CFLAGS += -DBT_NV_SUPPORT
+ifeq ($(QCPATH),)
+LOCAL_SHARED_LIBRARIES += libdl
+LOCAL_CFLAGS += -DBT_NV_SUPPORT_DL
+else
 LOCAL_SHARED_LIBRARIES += libbtnv
 endif
+endif
 
 LOCAL_CFLAGS += -Wno-unused-variable
 LOCAL_CFLAGS += -Wno-unused-label
diff --git a/libbt-vendor/src/bt_vendor_persist.cpp b/libbt-vendor/src/bt_vendor_persist.cpp
index 519e826..db895fd 100644
--- a/libbt-vendor/src/bt_vendor_persist.cpp
+++ b/libbt-vendor/src/bt_vendor_persist.cpp
@@ -27,7 +27,27 @@
 #include "bt_vendor_persist.h"
 
 #ifdef BT_NV_SUPPORT
+#ifdef BT_NV_SUPPORT_DL
+#include <dlfcn.h>
+// All figured out through investigation of this code...
+typedef struct {
+   unsigned char bd_addr[6];
+   // This is a bit dangerous, but this struct
+   // is unknown (however not used outside of this context)
+   unsigned char unknown[58];
+} nv_persist_item_type;
+typedef enum {
+  NV_SUCCESS = 0,
+} nv_persist_stat_enum_type;
+#define TRUE 1
+#define FALSE 0
+#define NV_BD_ADDR_I 1
+// ...except this, which was found through experimentation
+#define NV_READ_F 0
+#else
 #include "bt_nv.h"
+#endif
+#define LOG_TAG "QCOM-BTNV"
 #include <utils/Log.h>
 
 /*===========================================================================
@@ -56,11 +76,28 @@
   nv_persist_item_type my_nv_item;
   nv_persist_stat_enum_type cmd_result;
   boolean result = FALSE;
+#ifdef BT_NV_SUPPORT_DL
+  int (*bt_nv_cmd)(int, int, nv_persist_item_type *, int);
+  void *lib = dlopen("libbtnv.so", RTLD_NOW);
+
+  if (!lib) {
+    ALOGE("Failed to open libbtnv.so: %s", dlerror());
+    return FALSE;
+  }
+
+  bt_nv_cmd = (int (*)(int, int, nv_persist_item_type *, int))dlsym(lib, "bt_nv_cmd");
+  if (!bt_nv_cmd) {
+    ALOGE("Failed to find bt_nv_cmd: %s", dlerror());
+    dlclose(lib);
+    return FALSE;
+  }
+#endif
 
   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);
+      // A strange default parameter is used here. A debugger shows 4 parameters being passed.
+      cmd_result = (nv_persist_stat_enum_type)bt_nv_cmd(NV_READ_F,  NV_BD_ADDR_I, &my_nv_item, 0);
       ALOGI("CMD result: %d", cmd_result);
       if (NV_SUCCESS != cmd_result)
       {
@@ -86,6 +123,9 @@
       }
       break;
   }
+#ifdef BT_NV_SUPPORT_DL
+  dlclose(lib);
+#endif
   return result;
 }
 #endif /* End of BT_NV_SUPPORT */