summaryrefslogtreecommitdiffstats
path: root/libbt-vendor
diff options
context:
space:
mode:
Diffstat (limited to 'libbt-vendor')
-rw-r--r--libbt-vendor/Android.mk4
-rw-r--r--libbt-vendor/src/bt_vendor_qcom.c169
2 files changed, 172 insertions, 1 deletions
diff --git a/libbt-vendor/Android.mk b/libbt-vendor/Android.mk
index 1091239..d57ae57 100644
--- a/libbt-vendor/Android.mk
+++ b/libbt-vendor/Android.mk
@@ -45,6 +45,10 @@ 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 \
diff --git a/libbt-vendor/src/bt_vendor_qcom.c b/libbt-vendor/src/bt_vendor_qcom.c
index 6ac4abb..bf8c69f 100644
--- a/libbt-vendor/src/bt_vendor_qcom.c
+++ b/libbt-vendor/src/bt_vendor_qcom.c
@@ -69,6 +69,20 @@ static const tUSERIAL_CFG userial_init_cfg =
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 */
/******************************************************************************
** Local type definitions
@@ -78,6 +92,82 @@ void hw_epilog_process(void);
/******************************************************************************
** 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()
@@ -203,6 +293,11 @@ static int bt_powerup(int en )
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 */
@@ -217,6 +312,12 @@ static int bt_powerup(int en )
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;(rfkill_id == -1) && (rfkill_state == NULL);i++)
{
@@ -224,6 +325,11 @@ static int bt_powerup(int en )
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;
}
@@ -241,11 +347,20 @@ static int bt_powerup(int en )
if ((fd = open(rfkill_state, O_RDWR)) < 0)
{
ALOGE("open(%s) for write failed: %s (%d)",rfkill_state, strerror(errno), errno);
+#ifdef WIFI_BT_STATUS_SYNC
+ bt_semaphore_release(lock_fd);
+ bt_semaphore_destroy(lock_fd);
+#endif
+
return -1;
}
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;
}
@@ -254,7 +369,11 @@ static int bt_powerup(int en )
/* Write value to control rfkill */
if ((size = write(fd, &on, 1)) < 0) {
ALOGE("write(%s) failed: %s (%d)",rfkill_state, strerror(errno),errno);
- return -1;
+#ifdef WIFI_BT_STATUS_SYNC
+ bt_semaphore_release(lock_fd);
+ bt_semaphore_destroy(lock_fd);
+#endif
+ return -1;
}
if(on == '0'){
@@ -263,6 +382,45 @@ static int bt_powerup(int en )
property_set("wc_transport.soc_initialized", "0");
}
+#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);
@@ -322,6 +480,11 @@ static int init(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr)
vnd_local_bd_addr[3],
vnd_local_bd_addr[4],
vnd_local_bd_addr[5]);
+
+#ifdef WIFI_BT_STATUS_SYNC
+ isInit = 1;
+#endif /* WIFI_BT_STATUS_SYNC */
+
return 0;
}
@@ -681,6 +844,10 @@ static void cleanup( void )
{
ALOGI("cleanup");
bt_vendor_cbacks = NULL;
+
+#ifdef WIFI_BT_STATUS_SYNC
+ isInit = 0;
+#endif /* WIFI_BT_STATUS_SYNC */
}
// Entry point of DLib