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: