am f772565c: am 105961eb: Add new user-to-kernel interface for Bluetooth low power mode control (1/2)
* commit 'f772565c73c429652045d83307fc34be2148b234':
Add new user-to-kernel interface for Bluetooth low power mode control (1/2)
diff --git a/libbt/include/bt_vendor_brcm.h b/libbt/include/bt_vendor_brcm.h
index fff1925..858b71b 100644
--- a/libbt/include/bt_vendor_brcm.h
+++ b/libbt/include/bt_vendor_brcm.h
@@ -202,6 +202,13 @@
#define BT_WAKE_VIA_USERIAL_IOCTL FALSE
#endif
+/* BT_WAKE_VIA_PROC
+
+ LPM & BT_WAKE control through PROC nodes
+*/
+#ifndef BT_WAKE_VIA_PROC
+#define BT_WAKE_VIA_PROC FALSE
+#endif
/* SCO_CFG_INCLUDED
diff --git a/libbt/include/upio.h b/libbt/include/upio.h
index 32920e6..aa4fadc 100644
--- a/libbt/include/upio.h
+++ b/libbt/include/upio.h
@@ -38,6 +38,7 @@
enum {
UPIO_BT_WAKE = 0,
UPIO_HOST_WAKE,
+ UPIO_LPM_MODE,
UPIO_MAX_COUNT
};
diff --git a/libbt/include/vnd_crespo.txt b/libbt/include/vnd_crespo.txt
index 3596b6f..2ba0780 100644
--- a/libbt/include/vnd_crespo.txt
+++ b/libbt/include/vnd_crespo.txt
@@ -1,6 +1,5 @@
BLUETOOTH_UART_DEVICE_PORT = "/dev/s3c2410_serial0"
FW_PATCHFILE_LOCATION = "/vendor/firmware/"
-BT_WAKE_VIA_USERIAL_IOCTL = TRUE
LPM_IDLE_TIMEOUT_MULTIPLE = 5
SCO_PCM_IF_CLOCK_RATE = 0
BTVND_DBG = FALSE
diff --git a/libbt/include/vnd_crespo4g.txt b/libbt/include/vnd_crespo4g.txt
index 3596b6f..2ba0780 100644
--- a/libbt/include/vnd_crespo4g.txt
+++ b/libbt/include/vnd_crespo4g.txt
@@ -1,6 +1,5 @@
BLUETOOTH_UART_DEVICE_PORT = "/dev/s3c2410_serial0"
FW_PATCHFILE_LOCATION = "/vendor/firmware/"
-BT_WAKE_VIA_USERIAL_IOCTL = TRUE
LPM_IDLE_TIMEOUT_MULTIPLE = 5
SCO_PCM_IF_CLOCK_RATE = 0
BTVND_DBG = FALSE
diff --git a/libbt/include/vnd_generic.txt b/libbt/include/vnd_generic.txt
index 43e790c..18964f2 100644
--- a/libbt/include/vnd_generic.txt
+++ b/libbt/include/vnd_generic.txt
@@ -1,6 +1,5 @@
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
diff --git a/libbt/include/vnd_generic_x86.txt b/libbt/include/vnd_generic_x86.txt
index 43e790c..18964f2 100644
--- a/libbt/include/vnd_generic_x86.txt
+++ b/libbt/include/vnd_generic_x86.txt
@@ -1,6 +1,5 @@
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
diff --git a/libbt/include/vnd_grouper.txt b/libbt/include/vnd_grouper.txt
index 65ef840..3e4d71c 100755
--- a/libbt/include/vnd_grouper.txt
+++ b/libbt/include/vnd_grouper.txt
@@ -1,6 +1,6 @@
BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2"
FW_PATCHFILE_LOCATION = "/etc/firmware/"
-BT_WAKE_VIA_USERIAL_IOCTL = TRUE
+BT_WAKE_VIA_PROC = TRUE
LPM_IDLE_TIMEOUT_MULTIPLE = 5
BTVND_DBG = FALSE
BTHW_DBG = TRUE
diff --git a/libbt/include/vnd_maguro.txt b/libbt/include/vnd_maguro.txt
index 43e790c..18964f2 100644
--- a/libbt/include/vnd_maguro.txt
+++ b/libbt/include/vnd_maguro.txt
@@ -1,6 +1,5 @@
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
diff --git a/libbt/include/vnd_mako.txt b/libbt/include/vnd_mako.txt
index 43e790c..18964f2 100644
--- a/libbt/include/vnd_mako.txt
+++ b/libbt/include/vnd_mako.txt
@@ -1,6 +1,5 @@
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
diff --git a/libbt/include/vnd_manta.txt b/libbt/include/vnd_manta.txt
index fc58fb3..b2809d1 100644
--- a/libbt/include/vnd_manta.txt
+++ b/libbt/include/vnd_manta.txt
@@ -1,7 +1,6 @@
BLUETOOTH_UART_DEVICE_PORT = "/dev/ttySAC0"
FW_PATCHFILE_LOCATION = "/vendor/firmware/"
UART_TARGET_BAUD_RATE = 921600
-BT_WAKE_VIA_USERIAL_IOCTL = TRUE
LPM_IDLE_TIMEOUT_MULTIPLE = 5
SCO_USE_I2S_INTERFACE = TRUE
SCO_I2SPCM_IF_ROLE = 0
diff --git a/libbt/include/vnd_phantasm.txt b/libbt/include/vnd_phantasm.txt
index 43e790c..18964f2 100644
--- a/libbt/include/vnd_phantasm.txt
+++ b/libbt/include/vnd_phantasm.txt
@@ -1,6 +1,5 @@
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
diff --git a/libbt/include/vnd_stingray.txt b/libbt/include/vnd_stingray.txt
index 3667e65..f5eb1d0 100755
--- a/libbt/include/vnd_stingray.txt
+++ b/libbt/include/vnd_stingray.txt
@@ -1,6 +1,5 @@
BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2"
FW_PATCHFILE_LOCATION = "/etc/firmware/"
-BT_WAKE_VIA_USERIAL_IOCTL = TRUE
LPM_IDLE_TIMEOUT_MULTIPLE = 5
BTVND_DBG = FALSE
BTHW_DBG = TRUE
diff --git a/libbt/include/vnd_tilapia.txt b/libbt/include/vnd_tilapia.txt
index 65ef840..3e4d71c 100755
--- a/libbt/include/vnd_tilapia.txt
+++ b/libbt/include/vnd_tilapia.txt
@@ -1,6 +1,6 @@
BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2"
FW_PATCHFILE_LOCATION = "/etc/firmware/"
-BT_WAKE_VIA_USERIAL_IOCTL = TRUE
+BT_WAKE_VIA_PROC = TRUE
LPM_IDLE_TIMEOUT_MULTIPLE = 5
BTVND_DBG = FALSE
BTHW_DBG = TRUE
diff --git a/libbt/include/vnd_wingray.txt b/libbt/include/vnd_wingray.txt
index 3667e65..f5eb1d0 100755
--- a/libbt/include/vnd_wingray.txt
+++ b/libbt/include/vnd_wingray.txt
@@ -1,6 +1,5 @@
BLUETOOTH_UART_DEVICE_PORT = "/dev/ttyHS2"
FW_PATCHFILE_LOCATION = "/etc/firmware/"
-BT_WAKE_VIA_USERIAL_IOCTL = TRUE
LPM_IDLE_TIMEOUT_MULTIPLE = 5
BTVND_DBG = FALSE
BTHW_DBG = TRUE
diff --git a/libbt/src/bt_vendor_brcm.c b/libbt/src/bt_vendor_brcm.c
index d17baa2..9bd8922 100644
--- a/libbt/src/bt_vendor_brcm.c
+++ b/libbt/src/bt_vendor_brcm.c
@@ -197,7 +197,7 @@
case BT_VND_OP_LPM_WAKE_SET_STATE:
{
uint8_t *state = (uint8_t *) param;
- uint8_t wake_assert = (state == BT_VND_LPM_WAKE_ASSERT) ? \
+ uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
TRUE : FALSE;
hw_lpm_set_wake_state(wake_assert);
diff --git a/libbt/src/hardware.c b/libbt/src/hardware.c
index 397507d..45008ef 100644
--- a/libbt/src/hardware.c
+++ b/libbt/src/hardware.c
@@ -1045,10 +1045,12 @@
if (turn_on)
{
memcpy(p, &lpm_param, LPM_CMD_PARAM_SIZE);
+ upio_set(UPIO_LPM_MODE, UPIO_ASSERT, 0);
}
else
{
memset(p, 0, LPM_CMD_PARAM_SIZE);
+ upio_set(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
}
if ((ret = bt_vendor_cbacks->xmit_cb(HCI_VSC_WRITE_SLEEP_MODE, p_buf, \
diff --git a/libbt/src/upio.c b/libbt/src/upio.c
index d32f334..2de171c 100644
--- a/libbt/src/upio.c
+++ b/libbt/src/upio.c
@@ -54,6 +54,39 @@
** Local type definitions
******************************************************************************/
+#if (BT_WAKE_VIA_PROC == TRUE)
+
+/* proc fs node for enable/disable lpm mode */
+#ifndef VENDOR_LPM_PROC_NODE
+#define VENDOR_LPM_PROC_NODE "/proc/bluetooth/sleep/lpm"
+#endif
+
+/* proc fs node for notifying write request */
+#ifndef VENDOR_BTWRITE_PROC_NODE
+#define VENDOR_BTWRITE_PROC_NODE "/proc/bluetooth/sleep/btwrite"
+#endif
+
+/*
+ * Maximum btwrite assertion holding time without consecutive btwrite kicking.
+ * This value is correlative(shorter) to the in-activity timeout period set in
+ * the bluesleep LPM code. The current value used in bluesleep is 10sec.
+ */
+#ifndef PROC_BTWRITE_TIMER_TIMEOUT_MS
+#define PROC_BTWRITE_TIMER_TIMEOUT_MS 8000
+#endif
+
+/* lpm proc control block */
+typedef struct
+{
+ uint8_t btwrite_active;
+ uint8_t timer_created;
+ timer_t timer_id;
+ uint32_t timeout_ms;
+} vnd_lpm_proc_cb_t;
+
+static vnd_lpm_proc_cb_t lpm_proc_cb;
+#endif
+
/******************************************************************************
** Static variables
******************************************************************************/
@@ -68,6 +101,12 @@
******************************************************************************/
/* for friendly debugging outpout string */
+static char *lpm_mode[] = {
+ "UNKNOWN",
+ "disabled",
+ "enabled"
+};
+
static char *lpm_state[] = {
"UNKNOWN",
"de-asserted",
@@ -141,6 +180,23 @@
** LPM Static Functions
*****************************************************************************/
+#if (BT_WAKE_VIA_PROC == TRUE)
+/*******************************************************************************
+**
+** Function proc_btwrite_timeout
+**
+** Description Timeout thread of proc/.../btwrite assertion holding timer
+**
+** Returns None
+**
+*******************************************************************************/
+static void proc_btwrite_timeout(union sigval arg)
+{
+ UPIODBG("..%s..", __FUNCTION__);
+ lpm_proc_cb.btwrite_active = FALSE;
+}
+#endif
+
/*****************************************************************************
** UPIO Interface Functions
*****************************************************************************/
@@ -157,6 +213,9 @@
void upio_init(void)
{
memset(upio_state, UPIO_UNKNOWN, UPIO_MAX_COUNT);
+#if (BT_WAKE_VIA_PROC == TRUE)
+ memset(&lpm_proc_cb, 0, sizeof(vnd_lpm_proc_cb_t));
+#endif
}
/*******************************************************************************
@@ -170,6 +229,12 @@
*******************************************************************************/
void upio_cleanup(void)
{
+#if (BT_WAKE_VIA_PROC == TRUE)
+ if (lpm_proc_cb.timer_created == TRUE)
+ timer_delete(lpm_proc_cb.timer_id);
+
+ lpm_proc_cb.timer_created = FALSE;
+#endif
}
/*******************************************************************************
@@ -260,33 +325,157 @@
void upio_set(uint8_t pio, uint8_t action, uint8_t polarity)
{
int rc;
+#if (BT_WAKE_VIA_PROC == TRUE)
+ int fd = -1;
+ char buffer;
+#endif
switch (pio)
{
- case UPIO_BT_WAKE:
+ case UPIO_LPM_MODE:
+ if (upio_state[UPIO_LPM_MODE] == action)
+ {
+ UPIODBG("LPM is %s already", lpm_mode[action]);
+ return;
+ }
+ upio_state[UPIO_LPM_MODE] = action;
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+ 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';
+
+ // delete btwrite assertion holding timer
+ if (lpm_proc_cb.timer_created == TRUE)
+ {
+ timer_delete(lpm_proc_cb.timer_id);
+ lpm_proc_cb.timer_created = FALSE;
+ }
+ }
+
+ if (write(fd, &buffer, 1) < 0)
+ {
+ ALOGE("upio_set : write(%s) failed: %s (%d)",
+ VENDOR_LPM_PROC_NODE, strerror(errno),errno);
+ }
+ else
+ {
+ if (action == UPIO_ASSERT)
+ {
+ // create btwrite assertion holding timer
+ if (lpm_proc_cb.timer_created == FALSE)
+ {
+ int status;
+ struct sigevent se;
+
+ se.sigev_notify = SIGEV_THREAD;
+ se.sigev_value.sival_ptr = &lpm_proc_cb.timer_id;
+ se.sigev_notify_function = proc_btwrite_timeout;
+ se.sigev_notify_attributes = NULL;
+
+ status = timer_create(CLOCK_MONOTONIC, &se,
+ &lpm_proc_cb.timer_id);
+
+ if (status == 0)
+ lpm_proc_cb.timer_created = TRUE;
+ }
+ }
+ }
+
+ if (fd >= 0)
+ close(fd);
+#endif
+ break;
+
+ case UPIO_BT_WAKE:
if (upio_state[UPIO_BT_WAKE] == action)
{
UPIODBG("BT_WAKE is %s already", lpm_state[action]);
+
+#if (BT_WAKE_VIA_PROC == TRUE)
+ if (lpm_proc_cb.btwrite_active == TRUE)
+ /*
+ * The proc btwrite node could have not been updated for
+ * certain time already due to heavy downstream path flow.
+ * In this case, we want to explicity touch proc btwrite
+ * node to keep the bt_wake assertion in the LPM kernel
+ * driver. The current kernel bluesleep LPM code starts
+ * a 10sec internal in-activity timeout timer before it
+ * attempts to deassert BT_WAKE line.
+ */
+#endif
return;
}
upio_state[UPIO_BT_WAKE] = action;
- /****************************************
- * !!! TODO !!!
- *
- * === Custom Porting Required ===
- *
- * Platform dependent user-to-kernel
- * interface is required to set output
- * state of physical BT_WAKE pin.
- ****************************************/
#if (BT_WAKE_VIA_USERIAL_IOCTL == TRUE)
+
userial_vendor_ioctl( ( (action==UPIO_ASSERT) ? \
USERIAL_OP_ASSERT_BT_WAKE : USERIAL_OP_DEASSERT_BT_WAKE),\
NULL);
+
+#elif (BT_WAKE_VIA_PROC == TRUE)
+
+ /*
+ * Kick proc btwrite node only at UPIO_ASSERT
+ */
+ if (action == UPIO_DEASSERT)
+ return;
+
+ 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;
+ }
+
+ buffer = '1';
+
+ if (write(fd, &buffer, 1) < 0)
+ {
+ ALOGE("upio_set : write(%s) failed: %s (%d)",
+ VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno);
+ }
+ else
+ {
+ lpm_proc_cb.btwrite_active = TRUE;
+
+ if (lpm_proc_cb.timer_created == TRUE)
+ {
+ struct itimerspec ts;
+
+ ts.it_value.tv_sec = PROC_BTWRITE_TIMER_TIMEOUT_MS/1000;
+ ts.it_value.tv_nsec = 1000*(PROC_BTWRITE_TIMER_TIMEOUT_MS%1000);
+ ts.it_interval.tv_sec = 0;
+ ts.it_interval.tv_nsec = 0;
+
+ timer_settime(lpm_proc_cb.timer_id, 0, &ts, 0);
+ }
+ }
+
+ UPIODBG("proc btwrite assertion");
+
+ if (fd >= 0)
+ close(fd);
#endif
+
break;
case UPIO_HOST_WAKE: