Merge "Bluetooth-Wipower: Support for wipower forward handoff."
diff --git a/libbt-vendor/include/hw_rome.h b/libbt-vendor/include/hw_rome.h
index 0ffebd7..ceb766a 100644
--- a/libbt-vendor/include/hw_rome.h
+++ b/libbt-vendor/include/hw_rome.h
@@ -76,17 +76,22 @@
 /* VS Opcode */
 #define HCI_PATCH_CMD_OCF                       (0)
 #define EDL_SET_BAUDRATE_CMD_OCF        (0x48)
+#define EDL_WIPOWER_VS_CMD_OCF          (0x0c)
 
 /* VS Commands */
 #define VSC_SET_BAUDRATE_REQ_LEN        (1)
 #define EDL_PATCH_CMD_LEN	                       (1)
 #define EDL_PATCH_CMD_REQ_LEN               (1)
+#define EDL_WIP_QUERY_CHARGING_STATUS_LEN   (0x01)
+#define EDL_WIP_START_HANDOFF_TO_HOST_LEN   (0x01)
 #define EDL_PATCH_DLD_REQ_CMD               (0x01)
 #define EDL_PATCH_RST_REQ_CMD               (0x05)
 #define EDL_PATCH_SET_REQ_CMD               (0x16)
 #define EDL_PATCH_ATCH_REQ_CMD            (0x17)
 #define EDL_PATCH_VER_REQ_CMD               (0x19)
 #define EDL_PATCH_TLV_REQ_CMD               (0x1E)
+#define EDL_WIP_QUERY_CHARGING_STATUS_CMD   (0x1D)
+#define EDL_WIP_START_HANDOFF_TO_HOST_CMD   (0x1E)
 
 /* VS Event */
 #define EDL_CMD_REQ_RES_EVT                 (0x00)
@@ -95,6 +100,8 @@
 #define EDL_PATCH_VER_RES_EVT             (0x19)
 #define EDL_TVL_DNLD_RES_EVT                (0x04)
 #define EDL_APP_VER_RES_EVT                  (0x02)
+#define EDL_WIP_QUERY_CHARGING_STATUS_EVT    (0x18)
+#define EDL_WIP_START_HANDOFF_TO_HOST_EVENT  (0x19)
 
 
 /* Status Codes of HCI CMD execution*/
@@ -107,6 +114,10 @@
 #define NVM_ACCESS_CODE                     (0x0B)
 #define BAUDRATE_CHANGE_SUCCESS   (1)
 
+/* Wipower status codes */
+#define WIPOWER_IN_EMBEDDED_MODE 0x01
+#define NON_WIPOWER_MODE 0x02
+
 /* TLV_TYPE */
 #define TLV_TYPE_PATCH                  (1)
 #define TLV_TYPE_NVM                      (2)
diff --git a/libbt-vendor/src/bt_vendor_qcom.c b/libbt-vendor/src/bt_vendor_qcom.c
index 2c7a406..8523636 100644
--- a/libbt-vendor/src/bt_vendor_qcom.c
+++ b/libbt-vendor/src/bt_vendor_qcom.c
@@ -47,6 +47,7 @@
 
 extern int is_hw_ready();
 extern int rome_soc_init(int fd, char *bdaddr);
+extern int check_embedded_mode(int fd);
 /******************************************************************************
 **  Variables
 ******************************************************************************/
@@ -161,10 +162,9 @@
 
         if (strcmp(service_status, "") != 0) {
             usleep(200000);
-        }
-	else {
+        } else {
             break;
-	}
+        }
     }
 
     return 0;
@@ -394,7 +394,7 @@
     }
     if (!memcmp(enable_ldo, "true", 4)) {
         ALOGI("External LDO has been configured");
-	enable_extldo = TRUE;
+        enable_extldo = TRUE;
     }
 
     ALOGE("Write %c to rfkill\n", on);
@@ -406,7 +406,7 @@
         bt_semaphore_release(lock_fd);
         bt_semaphore_destroy(lock_fd);
 #endif
-	return -1;
+        return -1;
     }
 #ifdef BT_SOC_TYPE_ROME
     if(on == '0'){
@@ -574,6 +574,7 @@
     int nCnt = 0;
     int nState = -1;
     bool is_ant_req = false;
+    char wipower_status[PROPERTY_VALUE_MAX];
 
     ALOGV("bt-vendor : op for %d", opcode);
 
@@ -692,6 +693,14 @@
                                     ALOGE("userial_vendor_open returns err");
                                     retval = -1;
                                 } else {
+                                    property_get("ro.bluetooth.wipower", wipower_status, false);
+                                    if(strcmp(wipower_status, "true") == 0) {
+                                       /* wait for embedded mode startup */
+                                        usleep(WAIT_TIMEOUT - (WAIT_TIMEOUT/4));
+                                        check_embedded_mode(fd);
+                                    } else {
+                                        ALOGI("Wipower not enabled");
+                                    }
                                     ALOGV("rome_soc_init is started");
                                     property_set("wc_transport.soc_initialized", "0");
                                     /* Always read BD address from NV file */
diff --git a/libbt-vendor/src/hw_rome.c b/libbt-vendor/src/hw_rome.c
index ef7d3dc..a84c42e 100644
--- a/libbt-vendor/src/hw_rome.c
+++ b/libbt-vendor/src/hw_rome.c
@@ -66,6 +66,8 @@
 patch_info rampatch_patch_info;
 int rome_ver = ROME_VER_UNKNOWN;
 unsigned char gTlv_type;
+static unsigned int wipower_flag = 0;
+static unsigned int wipower_handoff_ready = 0;
 char *rampatch_file_path;
 char *nvm_file_path;
 extern char enable_extldo;
@@ -83,6 +85,7 @@
 {
     int err = 0, i, soc_id =0;
     unsigned char paramlen = 0;
+    unsigned char EMBEDDED_MODE_CHECK = 0x02;
 
     if( (rsp[EVENTCODE_OFFSET] == VSEVENT_CODE) || (rsp[EVENTCODE_OFFSET] == EVT_CMD_COMPLETE))
         ALOGI("%s: Received HCI-Vendor Specific event", __FUNCTION__);
@@ -181,6 +184,25 @@
                 err = -1;
             }
             break;
+       case EDL_WIP_QUERY_CHARGING_STATUS_EVT:
+            /*TODO: rsp code 00 mean no charging
+            this is going to change in FW soon*/
+            if (rsp[4] != EMBEDDED_MODE_CHECK)
+            {
+               ALOGI("%s: WiPower Charging in Embedded Mode!!!", __FUNCTION__);
+               wipower_handoff_ready = rsp[4];
+               wipower_flag = 1;
+            }
+            break;
+        case EDL_WIP_START_HANDOFF_TO_HOST_EVENT:
+            /*TODO: rsp code 00 mean no charging
+            this is going to change in FW soon*/
+            if (rsp[4] == NON_WIPOWER_MODE)
+            {
+               ALOGE("%s: WiPower Charging hand off not ready!!!", __FUNCTION__);
+            }
+            break;
+
         default:
             ALOGE("%s: Not a valid status!!!", __FUNCTION__);
             err = -1;
@@ -249,6 +271,35 @@
     return count;
 }
 
+/*
+ * For Hand-Off related Wipower commands, Command complete arrives first and
+ * the followd with VS event
+ *
+ */
+int hci_send_wipower_vs_cmd(int fd, unsigned char *cmd, unsigned char *rsp, int size)
+{
+    int ret = 0;
+    int err = 0;
+
+    /* Send the HCI command packet to UART for transmission */
+    ret = write(fd, cmd, size);
+    if (ret != size) {
+        ALOGE("%s: WP Send failed with ret value: %d", __FUNCTION__, ret);
+        goto failed;
+    }
+
+    /* Wait for command complete event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        ALOGE("%s: Failed to charging status cmd on Controller", __FUNCTION__);
+        goto failed;
+    }
+
+    ALOGI("%s: WP Received HCI command complete Event from SOC", __FUNCTION__);
+failed:
+    return ret;
+}
+
 
 int hci_send_vs_cmd(int fd, unsigned char *cmd, unsigned char *rsp, int size)
 {
@@ -411,7 +462,7 @@
         -1, PATCH_HDR_LEN + 1);
 
     /* Total length of the packet to be sent to the Controller */
-    size = (HCI_CMD_IND	+ HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
 
     /* Send HCI Command packet to Controller */
     err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
@@ -460,7 +511,7 @@
         index, MAX_DATA_PER_SEGMENT);
 
         /* Total length of the packet to be sent to the Controller */
-        size = (HCI_CMD_IND	+ HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+        size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
 
         /* Initialize the RSP packet everytime to 0 */
         memset(rsp, 0x0, HCI_MAX_EVENT_SIZE);
@@ -497,7 +548,7 @@
         memset(rsp, 0x0, HCI_MAX_EVENT_SIZE);
 
         /* Total length of the packet to be sent to the Controller */
-        size = (HCI_CMD_IND	+ HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+        size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
 
         /* Send HCI Command packet to Controller */
         err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
@@ -614,7 +665,7 @@
         -1, EDL_PATCH_CMD_LEN);
 
     /* Total length of the packet to be sent to the Controller */
-    size = (HCI_CMD_IND	+ HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
 
     /* Send HCI Command packet to Controller */
     err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
@@ -644,7 +695,7 @@
                                         -1, EDL_PATCH_CMD_LEN);
 
     /* Total length of the packet to be sent to the Controller */
-    size = (HCI_CMD_IND	+ HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN);
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN);
 
     /* Send HCI Command packet to Controller */
     err = write(fd, cmd, size);
@@ -853,7 +904,6 @@
 
     /* Rampatch TLV file Downloading */
     pdata_buffer = NULL;
-
     if((tlv_size = rome_get_tlv_file(rampatch_file_path)) < 0)
         goto error;
 
@@ -864,7 +914,6 @@
         free (pdata_buffer);
         pdata_buffer = NULL;
     }
-
     /* NVM TLV file Downloading */
     if((tlv_size = rome_get_tlv_file(nvm_file_path)) < 0)
         goto error;
@@ -1341,6 +1390,99 @@
 
 }
 
+int rome_wipower_current_charging_status_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+    hci_command_hdr *cmd_hdr;
+    int flags;
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+    cmd[0]  = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, EDL_WIPOWER_VS_CMD_OCF);
+    cmd_hdr->plen     = EDL_WIP_QUERY_CHARGING_STATUS_LEN;
+    cmd[4]  = EDL_WIP_QUERY_CHARGING_STATUS_CMD;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_WIP_QUERY_CHARGING_STATUS_LEN);
+
+    ALOGD("%s: Sending EDL_WIP_QUERY_CHARGING_STATUS_CMD", __FUNCTION__);
+    ALOGD("HCI-CMD: \t0x%x \t0x%x \t0x%x \t0x%x \t0x%x", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+
+    err = hci_send_wipower_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to send EDL_WIP_QUERY_CHARGING_STATUS_CMD command!");
+        goto error;
+    }
+
+    /* Check for response from the Controller */
+    if (read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE) < 0) {
+        err = -ETIMEDOUT;
+        ALOGI("%s: WP Failed to get HCI-VS Event from SOC", __FUNCTION__);
+        goto error;
+    }
+
+error:
+    return err;
+}
+
+int check_embedded_mode(int fd) {
+    int err = 0;
+
+    wipower_flag = 0;
+    /* Get current wipower charging status */
+    if ((err = rome_wipower_current_charging_status_req(fd)) < 0)
+    {
+        ALOGI("%s: Wipower status req failed (0x%x)", __FUNCTION__, err);
+    }
+    usleep(500);
+
+    ALOGE("%s: wipower_flag: %d", __FUNCTION__, wipower_flag);
+
+    return wipower_flag;
+}
+
+int rome_wipower_forward_handoff_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+    hci_command_hdr *cmd_hdr;
+    int flags;
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+    cmd[0]  = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, EDL_WIPOWER_VS_CMD_OCF);
+    cmd_hdr->plen     = EDL_WIP_START_HANDOFF_TO_HOST_LEN;
+    cmd[4]  = EDL_WIP_START_HANDOFF_TO_HOST_CMD;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_WIP_START_HANDOFF_TO_HOST_LEN);
+
+    ALOGD("%s: Sending EDL_WIP_START_HANDOFF_TO_HOST_CMD", __FUNCTION__);
+    ALOGD("HCI-CMD: \t0x%x \t0x%x \t0x%x \t0x%x \t0x%x", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+    err = hci_send_wipower_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        ALOGE("Failed to send EDL_WIP_START_HANDOFF_TO_HOST_CMD command!");
+        goto error;
+    }
+
+    /* Check for response from the Controller */
+    if (read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE) < 0) {
+        err = -ETIMEDOUT;
+        ALOGI("%s: WP Failed to get HCI-VS Event from SOC", __FUNCTION__);
+        goto error;
+    }
+
+error:
+    return err;
+}
+
 
 static void enable_controller_log (int fd)
 {
@@ -1393,6 +1535,17 @@
 
     ALOGI(" %s ", __FUNCTION__);
 
+    /* If wipower charging is going on in embedded mode then start hand off req */
+    if (wipower_flag == WIPOWER_IN_EMBEDDED_MODE && wipower_handoff_ready != NON_WIPOWER_MODE)
+    {
+        wipower_flag = 0;
+        wipower_handoff_ready = 0;
+        if ((err = rome_wipower_forward_handoff_req(fd)) < 0)
+        {
+            ALOGI("%s: Wipower handoff failed (0x%x)", __FUNCTION__, err);
+        }
+    }
+
     /* Get Rome version information */
     if((err = rome_patch_ver_req(fd)) <0){
         ALOGI("%s: Fail to get Rome Version (0x%x)", __FUNCTION__, err);
@@ -1440,7 +1593,7 @@
 
                 /* Change baud rate 115.2 kbps to 3Mbps*/
                 err = rome_hci_reset_req(fd);
-                if ( err <0 ) {
+                if (err < 0) {
                     ALOGE("HCI Reset Failed !!");
                     goto error;
                 }
@@ -1472,7 +1625,6 @@
                 goto error;
             }
             ALOGI("%s: Baud rate changed successfully ", __FUNCTION__);
-
             /* Donwload TLV files (rampatch, NVM) */
             err = rome_download_tlv_file(fd);
             if (err < 0) {
@@ -1480,7 +1632,6 @@
                 goto error;
             }
             ALOGI("%s: Download TLV file successfully ", __FUNCTION__);
-
             /* This function sends a vendor specific command to enable/disable
              * controller logs on need. Once the command is received to the SOC,
              * It would start sending cotroller's print strings and LMP RX/TX
@@ -1495,6 +1646,13 @@
 
             /* Send HCI Reset */
             err = rome_hci_reset(fd);
+            if ( err <0 ) {
+                ALOGE("HCI Reset Failed !!");
+                goto error;
+            }
+
+            ALOGI("HCI Reset is done\n");
+
             break;
         case ROME_VER_UNKNOWN:
         default: