Reconcile with jb-mr1-factory-release - do not merge

Change-Id: I9601fda00ccff581fcf0eb9dfe47c1bf87e5bda0
diff --git a/clear-factory-images-variables.sh b/clear-factory-images-variables.sh
index e0c6758..df9c251 100644
--- a/clear-factory-images-variables.sh
+++ b/clear-factory-images-variables.sh
@@ -12,9 +12,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+unset XLOADER
+unset XLOADERSRC
 unset BOOTLOADER
 unset BOOTLOADERFILE
 unset BOOTLOADERSRC
+unset TWINBOOTLOADERS
 unset BUILD
 unset CDMARADIO
 unset DEVICE
diff --git a/generate-blob-lists.sh b/generate-blob-lists.sh
index eebc083..0f34ad3 100755
--- a/generate-blob-lists.sh
+++ b/generate-blob-lists.sh
@@ -42,7 +42,7 @@
 fi
 shift
 
-DEVICES="maguro toro toroplus grouper manta mako"
+DEVICES="maguro toro toroplus grouper manta mako phantasm"
 export LC_ALL=C
 
 repo sync -j32 -n
diff --git a/generate-factory-images-common.sh b/generate-factory-images-common.sh
index d6674bc..0ff6868 100644
--- a/generate-factory-images-common.sh
+++ b/generate-factory-images-common.sh
@@ -1,4 +1,4 @@
-# Copyright (C) 2011 The Android Open Source Project
+# Copyright 2011 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.
@@ -12,16 +12,33 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-if test "$RADIOSRC" = ""
+# Use the default values if they weren't explicitly set
+if test "$XLOADERSRC" = ""
 then
-  RADIOSRC=radio.img
+  XLOADERSRC=xloader.img
 fi
 if test "$BOOTLOADERSRC" = ""
 then
   BOOTLOADERSRC=bootloader.img
 fi
+if test "$RADIOSRC" = ""
+then
+  RADIOSRC=radio.img
+fi
+if test "$SLEEPDURATION" = ""
+then
+  SLEEPDURATION=5
+fi
+
+# Prepare the staging directory
 rm -rf tmp
 mkdir -p tmp/$PRODUCT-$VERSION
+
+# Extract the bootloader(s) and radio(s) as necessary
+if test "$XLOADER" != ""
+then
+  unzip -d tmp ${SRCPREFIX}$PRODUCT-target_files-$BUILD.zip RADIO/$XLOADERSRC
+fi
 if test "$BOOTLOADERFILE" = ""
 then
   unzip -d tmp ${SRCPREFIX}$PRODUCT-target_files-$BUILD.zip RADIO/$BOOTLOADERSRC
@@ -34,7 +51,10 @@
 then
   unzip -d tmp ${SRCPREFIX}$PRODUCT-target_files-$BUILD.zip RADIO/radio-cdma.img
 fi
+
+# Copy the various images in their staging location
 cp ${SRCPREFIX}$PRODUCT-img-$BUILD.zip tmp/$PRODUCT-$VERSION/image-$PRODUCT-$VERSION.zip
+cp tmp/RADIO/$XLOADERSRC tmp/$PRODUCT-$VERSION/xloader-$DEVICE-$XLOADER.img
 if test "$BOOTLOADERFILE" = ""
 then
   cp tmp/RADIO/$BOOTLOADERSRC tmp/$PRODUCT-$VERSION/bootloader-$DEVICE-$BOOTLOADER.img
@@ -49,14 +69,12 @@
 then
   cp tmp/RADIO/radio-cdma.img tmp/$PRODUCT-$VERSION/radio-cdma-$DEVICE-$CDMARADIO.img
 fi
-if test "$SLEEPDURATION" = ""
-then
-  SLEEPDURATION=5
-fi
+
+# Write flash-all.sh
 cat > tmp/$PRODUCT-$VERSION/flash-all.sh << EOF
 #!/bin/sh
 
-# Copyright (C) 2011 The Android Open Source Project
+# Copyright 2011 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.
@@ -81,8 +99,22 @@
 fastboot erase userdata
 EOF
 fi
+if test "$XLOADER" != ""
+then
+cat >> tmp/$PRODUCT-$VERSION/flash-all.sh << EOF
+fastboot flash xloader xloader-$DEVICE-$XLOADER.img
+EOF
+fi
 cat >> tmp/$PRODUCT-$VERSION/flash-all.sh << EOF
 fastboot flash bootloader bootloader-$DEVICE-$BOOTLOADER.img
+EOF
+if test "$TWINBOOTLOADERS" = "true"
+then
+cat >> tmp/$PRODUCT-$VERSION/flash-all.sh << EOF
+fastboot flash bootloader2 bootloader-$DEVICE-$BOOTLOADER.img
+EOF
+fi
+cat >> tmp/$PRODUCT-$VERSION/flash-all.sh << EOF
 fastboot reboot-bootloader
 sleep $SLEEPDURATION
 EOF
@@ -106,6 +138,8 @@
 fastboot -w update image-$PRODUCT-$VERSION.zip
 EOF
 chmod a+x tmp/$PRODUCT-$VERSION/flash-all.sh
+
+# Write flash-all.bat
 cat > tmp/$PRODUCT-$VERSION/flash-all.bat << EOF
 @ECHO OFF
 :: Copyright 2012 The Android Open Source Project
@@ -134,8 +168,22 @@
 fastboot erase userdata
 EOF
 fi
+if test "$XLOADER" != ""
+then
+cat >> tmp/$PRODUCT-$VERSION/flash-all.bat << EOF
+fastboot flash xloader xloader-$DEVICE-$XLOADER.img
+EOF
+fi
 cat >> tmp/$PRODUCT-$VERSION/flash-all.bat << EOF
 fastboot flash bootloader bootloader-$DEVICE-$BOOTLOADER.img
+EOF
+if test "$TWINBOOTLOADERS" = "true"
+then
+cat >> tmp/$PRODUCT-$VERSION/flash-all.bat << EOF
+fastboot flash bootloader2 bootloader-$DEVICE-$BOOTLOADER.img
+EOF
+fi
+cat >> tmp/$PRODUCT-$VERSION/flash-all.bat << EOF
 fastboot reboot-bootloader
 ping -n $SLEEPDURATION 127.0.0.1 >nul
 EOF
@@ -162,10 +210,12 @@
 pause >nul
 exit
 EOF
+
+# Write flash-base.sh
 cat > tmp/$PRODUCT-$VERSION/flash-base.sh << EOF
 #!/bin/sh
 
-# Copyright (C) 2011 The Android Open Source Project
+# Copyright 2011 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.
@@ -179,7 +229,23 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+EOF
+if test "$XLOADER" != ""
+then
+cat >> tmp/$PRODUCT-$VERSION/flash-base.sh << EOF
+fastboot flash xloader xloader-$DEVICE-$XLOADER.img
+EOF
+fi
+cat >> tmp/$PRODUCT-$VERSION/flash-base.sh << EOF
 fastboot flash bootloader bootloader-$DEVICE-$BOOTLOADER.img
+EOF
+if test "$TWINBOOTLOADERS" = "true"
+then
+cat >> tmp/$PRODUCT-$VERSION/flash-base.sh << EOF
+fastboot flash bootloader2 bootloader-$DEVICE-$BOOTLOADER.img
+EOF
+fi
+cat >> tmp/$PRODUCT-$VERSION/flash-base.sh << EOF
 fastboot reboot-bootloader
 sleep $SLEEPDURATION
 EOF
@@ -200,6 +266,10 @@
 EOF
 fi
 chmod a+x tmp/$PRODUCT-$VERSION/flash-base.sh
+
+# Create the distributable package
 (cd tmp ; tar zcvf ../$PRODUCT-$VERSION-factory.tgz $PRODUCT-$VERSION)
 mv $PRODUCT-$VERSION-factory.tgz $PRODUCT-$VERSION-factory-$(sha1sum < $PRODUCT-$VERSION-factory.tgz | cut -b -8).tgz
+
+# Clean up
 rm -rf tmp
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: