bluetooth: enable lpm support for atheros SoC.
Low power mode support is enabled for Atheros SoC
Change-Id: I2bf753898a52a205cc9d074b4e1962c5e50e78a1
diff --git a/libbt-vendor/Android.mk b/libbt-vendor/Android.mk
index c446d02..445bbd6 100644
--- a/libbt-vendor/Android.mk
+++ b/libbt-vendor/Android.mk
@@ -34,6 +34,11 @@
$(LOCAL_PATH)/include \
$(BDROID_DIR)/hci/include
+ifeq ($(BOARD_HAS_QCA_BT_AR3002), true)
+LOCAL_C_FLAGS := \
+ -DBT_WAKE_VIA_PROC
+endif #BOARD_HAS_QCA_BT_AR3002
+
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog
diff --git a/libbt-vendor/include/bt_vendor_ar3k.h b/libbt-vendor/include/bt_vendor_ar3k.h
index 646948d..038f454 100644
--- a/libbt-vendor/include/bt_vendor_ar3k.h
+++ b/libbt-vendor/include/bt_vendor_ar3k.h
@@ -34,6 +34,16 @@
#define TRUE (!FALSE)
#endif
+/* proc fs node for enable/disable lpm mode */
+#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
+
// File discriptor using Transport
extern int fd;
diff --git a/libbt-vendor/src/bt_vendor_qcom.c b/libbt-vendor/src/bt_vendor_qcom.c
index d388b89..0d18764 100644
--- a/libbt-vendor/src/bt_vendor_qcom.c
+++ b/libbt-vendor/src/bt_vendor_qcom.c
@@ -48,6 +48,7 @@
** Variables
******************************************************************************/
int pFd[2] = {0,};
+
bt_hci_transport_device_type bt_hci_transport_device;
bt_vendor_callbacks_t *bt_vendor_cbacks = NULL;
@@ -78,16 +79,16 @@
{
ALOGI("bt-vendor : init");
btSocAth = is_bt_soc_ath();
- if (p_cb == NULL)
- {
+
+ if (p_cb == NULL) {
ALOGE("init failed with no user callbacks!");
return -1;
}
- if(btSocAth)
- {
- userial_vendor_init();
- }
- //upio_init();
+
+ if(btSocAth) {
+ userial_vendor_init();
+ upio_init();
+ }
//vnd_load_conf(VENDOR_LIB_CONF_FILE);
@@ -114,42 +115,42 @@
{
case BT_VND_OP_POWER_CTRL:
{
- if(btSocAth) {
- ALOGI("AR3002 ::BT_VND_OP_POWER_CTRL");
- int *state = (int *) param;
+ if (btSocAth) {
+ int *state = (int *) param;
- if (*state == BT_VND_PWR_OFF) {
- ALOGI("[//]AR3002 UPIO_BT_POWER_OFF");
- upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
- }
- else if (*state == BT_VND_PWR_ON){
- ALOGI("[//]AR3002 UPIO_BT_POWER_ON");
- upio_set_bluetooth_power(UPIO_BT_POWER_ON);
- }
- }
- else {
- nState = *(int *) param;
- retval = hw_config(nState);
- if(nState == BT_VND_PWR_ON
- && retval == 0
- && is_hw_ready() == TRUE){
- retval = 0;
+ ALOGI("BT_VND_OP_POWER_CTRL State: %d ", *state);
+
+ if (*state == BT_VND_PWR_OFF) {
+ upio_set_bluetooth_power(UPIO_BT_POWER_OFF);
+ }
+ else if (*state == BT_VND_PWR_ON) {
+ upio_set_bluetooth_power(UPIO_BT_POWER_ON);
+ }
}
else {
- retval = -1;
+ nState = *(int *) param;
+
+ retval = hw_config(nState);
+ if (nState == BT_VND_PWR_ON
+ && retval == 0
+ && is_hw_ready() == TRUE) {
+ retval = 0;
+ }
+ else {
+ retval = -1;
+ }
}
}
- }
break;
case BT_VND_OP_FW_CFG:
{
// call hciattach to initalize the stack
- if(bt_vendor_cbacks){
- ALOGI("Bluetooth Firmware and smd is initialized");
+ if (bt_vendor_cbacks) {
+ ALOGI("Bluetooth Firmware and transport is initialized");
bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
}
- else{
+ else {
ALOGE("Error : hci, smd initialization Error");
bt_vendor_cbacks->fwcfg_cb(BT_VND_OP_RESULT_FAIL);
}
@@ -164,58 +165,87 @@
case BT_VND_OP_USERIAL_OPEN:
{
- if(btSocAth) {
- ALOGI("AR3002 ::BT_VND_OP_USERIAL_OPEN ");
- int (*fd_array)[] = (int (*)[]) param;
- int fd, idx;
- fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
- if (fd != -1) {
- for (idx=0; idx < CH_MAX; idx++)
- (*fd_array)[idx] = fd;
+ if (btSocAth) {
+ int (*fd_array)[] = (int (*)[]) param;
+ int fd, idx;
- retval = 1;
+ ALOGI("BT_VND_OP_USERIAL_OPEN ");
+ 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{
- if(bt_hci_init_transport(pFd) != -1){
- int (*fd_array)[] = (int (*) []) param;
+ else {
+ if (bt_hci_init_transport(pFd) != -1) {
+ int (*fd_array)[] = (int (*) []) param;
- (*fd_array)[CH_CMD] = pFd[0];
- (*fd_array)[CH_EVT] = pFd[0];
- (*fd_array)[CH_ACL_OUT] = pFd[1];
- (*fd_array)[CH_ACL_IN] = pFd[1];
- }
- else {
- retval = -1;
- break;
- }
- retval = 2;
- }
+ (*fd_array)[CH_CMD] = pFd[0];
+ (*fd_array)[CH_EVT] = pFd[0];
+ (*fd_array)[CH_ACL_OUT] = pFd[1];
+ (*fd_array)[CH_ACL_IN] = pFd[1];
+ }
+ else {
+ retval = -1;
+ break;
+ }
+ retval = 2;
+ }
}
break;
case BT_VND_OP_USERIAL_CLOSE:
- { if(btSocAth) {
- ALOGI("AR3002 ::BT_VND_OP_USERIAL_CLOSE ");
- userial_vendor_close();
- }
- else {
- bt_hci_deinit_transport(pFd);
- }
+ {
+ if (btSocAth) {
+ ALOGI("AR3002 ::BT_VND_OP_USERIAL_CLOSE ");
+ userial_vendor_close();
+ }
+ else {
+ bt_hci_deinit_transport(pFd);
+ }
}
break;
case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
+ {
+ if (btSocAth) {
+ uint32_t *timeout_ms = (uint32_t *) param;
+ *timeout_ms = 1000;
+ }
+ }
break;
case BT_VND_OP_LPM_SET_MODE:
- {
+ ALOGI("BT_VND_OP_LPM_SET_MODE");
+
+ if(btSocAth) {
+ 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);
+ }
+
+ bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
+ }
+ else {
bt_vendor_cbacks->lpm_cb(BT_VND_OP_RESULT_SUCCESS); //dummy
}
break;
case BT_VND_OP_LPM_WAKE_SET_STATE:
+
+ if(btSocAth) {
+ 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);
+ }
break;
case BT_VND_OP_EPILOG:
{
@@ -239,8 +269,9 @@
{
ALOGI("cleanup");
- //upio_cleanup();
-
+ if(btSocAth) {
+ upio_cleanup();
+ }
bt_vendor_cbacks = NULL;
}
diff --git a/libbt-vendor/src/hardware_ar3k.c b/libbt-vendor/src/hardware_ar3k.c
index 28c81a3..99aa446 100644
--- a/libbt-vendor/src/hardware_ar3k.c
+++ b/libbt-vendor/src/hardware_ar3k.c
@@ -50,6 +50,7 @@
#include "bt_hci_bdroid.h"
#include "bt_vendor_ar3k.h"
+#include "upio.h"
#define MAX_CNT_RETRY 100
@@ -163,6 +164,21 @@
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];
+
typedef struct {
uint8_t b[6];
} __attribute__((packed)) bdaddr_t;
@@ -234,6 +250,8 @@
}
#endif
+int read_hci_event(int fd, unsigned char* buf, int size);
+
int is_bt_soc_ath() {
int ret = 0;
char bt_soc_type[PROPERTY_VALUE_MAX];
@@ -1562,3 +1580,104 @@
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);
+
+ 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;
+ }
+
+}
+