Add hciattach rome support for Qualcomm chip QCA6564

This is a multiple patch including all the specific qualcomm commits to add
support for its chip in bluez stack (hciattach rome).

Signed-off-by: Isaac Hermida <isaac.hermida@digi.com>

From e6d2fb7efcde66f9ab22a42bd6d7039a4f0c02cd Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Tue, 19 Aug 2014 20:23:01 +0530
Subject: [PATCH 01/19] bluetooth : Add bluetooth support for QCA6174 chip.

Register the QCA6174 initialization routine with hciattach for
downloading firmware patches to the bluetooth controller.
Add optional support 'f' to control installation of line
discipline driver. Invoke hciattach from command line and
download the firmware patches:
	hciattach /dev/ttyHS0 qca 3000000 -t120 flow -f0

Change-Id: I87f2927d7096904071a02d73d3afef0dc34db414
Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
---
 Makefile.tools         |    3 +-
 tools/hciattach.c      |   25 +-
 tools/hciattach.h      |    8 +-
 tools/hciattach_rome.c | 1578 ++++++++++++++++++++++++++++++++++++++++++++++++
 tools/hciattach_rome.h |  317 ++++++++++
 5 files changed, 1926 insertions(+), 5 deletions(-)
 create mode 100644 tools/hciattach_rome.c
 create mode 100644 tools/hciattach_rome.h

diff --git a/Makefile.tools b/Makefile.tools
index 0d5f1431e013..8f087c597490 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -164,7 +164,8 @@ tools_hciattach_SOURCES = tools/hciattach.c tools/hciattach.h \
 						tools/hciattach_ath3k.c \
 						tools/hciattach_qualcomm.c \
 						tools/hciattach_intel.c \
-						tools/hciattach_bcm43xx.c
+						tools/hciattach_bcm43xx.c \
+						tools/hciattach_rome.c tools/hciattach_rome.h
 tools_hciattach_LDADD = lib/libbluetooth-internal.la
 
 tools_hciconfig_SOURCES = tools/hciconfig.c tools/csr.h tools/csr.c
diff --git a/tools/hciattach.c b/tools/hciattach.c
index fad176c9b804..73811d4c4c2a 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
@@ -69,6 +69,8 @@ struct uart_t {
 #define ENABLE_PM	1
 #define DISABLE_PM	0
 
+int line_disp = 1;
+
 static volatile sig_atomic_t __io_canceled = 0;
 
 static void sig_hup(int sig)
@@ -263,6 +265,12 @@ static int ath3k_pm(int fd, struct uart_t *u, struct termios *ti)
 	return ath3k_post(fd, u->pm);
 }
 
+static int qca(int fd, struct uart_t *u, struct termios *ti)
+{
+        fprintf(stderr,"qca\n");
+        return qca_soc_init(fd, u->bdaddr);
+}
+
 static int qualcomm(int fd, struct uart_t *u, struct termios *ti)
 {
 	return qualcomm_init(fd, u->speed, ti, u->bdaddr);
@@ -1093,6 +1101,10 @@ struct uart_t uart[] = {
 	{ "ath3k",    0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,
 			FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm  },
 
+	/* QCA ROME */
+        { "qca",    0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+                        FLOW_CTL, DISABLE_PM, NULL, qca, NULL },
+
 	/* QUALCOMM BTS */
 	{ "qualcomm",   0x0000, 0x0000, HCI_UART_H4,   115200, 115200,
 			FLOW_CTL, DISABLE_PM, NULL, qualcomm, NULL },
@@ -1195,6 +1207,7 @@ static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)
 		goto fail;
 	}
 
+if (line_disp) {
 	/* Set TTY to N_HCI line discipline */
 	i = N_HCI;
 	if (ioctl(fd, TIOCSETD, &i) < 0) {
@@ -1211,6 +1224,7 @@ static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)
 		perror("Can't set device");
 		goto fail;
 	}
+}
 
 	if (u->post && u->post(fd, u, &ti) < 0)
 		goto fail;
@@ -1249,7 +1263,7 @@ int main(int argc, char *argv[])
 	printpid = 0;
 	raw = 0;
 
-	while ((opt=getopt(argc, argv, "bnpt:s:lr")) != EOF) {
+	while ((opt=getopt(argc, argv, "bnpt:s:lrf:")) != EOF) {
 		switch(opt) {
 		case 'b':
 			send_break = 1;
@@ -1282,6 +1296,11 @@ int main(int argc, char *argv[])
 			raw = 1;
 			break;
 
+		case 'f':
+			line_disp = atoi(optarg);
+			fprintf(stderr, "Line_disp val : %d\n", line_disp);
+			break;
+
 		default:
 			usage();
 			exit(1);
@@ -1350,6 +1369,7 @@ int main(int argc, char *argv[])
 		case 5:
 			u->bdaddr = argv[optind];
 			break;
+
 		}
 	}
 
@@ -1426,12 +1446,15 @@ int main(int argc, char *argv[])
 			break;
 	}
 
+if (line_disp) {
 	/* Restore TTY line discipline */
+	fprintf(stderr, "Restoring the Line Discipline driver\n");
 	ld = N_TTY;
 	if (ioctl(n, TIOCSETD, &ld) < 0) {
 		perror("Can't restore line discipline");
 		exit(1);
 	}
+}
 
 	return 0;
 }
diff --git a/tools/hciattach.h b/tools/hciattach.h
index 4279a3361749..0656a845223c 100644
--- a/tools/hciattach.h
+++ b/tools/hciattach.h
@@ -39,9 +39,10 @@
 #define HCI_UART_H4DS	3
 #define HCI_UART_LL	4
 #define HCI_UART_ATH3K  5
-#define HCI_UART_INTEL	6
-#define HCI_UART_BCM	7
-#define HCI_UART_QCA	8
+#define HCI_UART_IBS	6
+#define HCI_UART_INTEL	7
+#define HCI_UART_BCM	8
+#define HCI_UART_QCA	9
 
 #define HCI_UART_RAW_DEVICE	0
 #define HCI_UART_RESET_ON_INIT	1
@@ -63,6 +64,7 @@ int ath3k_init(int fd, int speed, int init_speed, char *bdaddr,
 						struct termios *ti);
 int ath3k_post(int fd, int pm);
 int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr);
+int qca_soc_init(int fd, char *bdaddr);
 int intel_init(int fd, int init_speed, int *speed, struct termios *ti);
 int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti,
 		const char *bdaddr);
diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
new file mode 100644
index 000000000000..f31be43c09e4
--- /dev/null
+++ b/tools/hciattach_rome.c
@@ -0,0 +1,1578 @@
+/*
+ *
+ *  Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  Not a Contribution.
+ *
+ *  Copyright 2012 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. You may
+ *  obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ *  implied. See the License for the specific language governing
+ *  permissions and limitations under the License.
+ *
+ */
+
+/******************************************************************************
+ *
+ *  Filename:      hciattach_rome.c
+ *
+ *  Description:   Contains controller-specific functions, like
+ *                      firmware patch download
+ *                      low power mode operations
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_vendor"
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <bluetooth/bluetooth.h>
+#include "hciattach_rome.h"
+#include "hciattach.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/******************************************************************************
+**  Variables
+******************************************************************************/
+FILE *file;
+unsigned char *phdr_buffer;
+unsigned char *pdata_buffer = NULL;
+patch_info rampatch_patch_info;
+int rome_ver = ROME_VER_UNKNOWN;
+unsigned char gTlv_type;
+char *rampatch_file_path;
+char *nvm_file_path;
+vnd_userial_cb_t vnd_userial;
+/******************************************************************************
+**  Extern variables
+******************************************************************************/
+//extern unsigned char vnd_local_bd_addr[6];
+
+/*****************************************************************************
+**   Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function        userial_to_tcio_baud
+**
+** Description     helper function converts USERIAL baud rates into TCIO
+**                  conforming baud rates
+**
+** Returns         TRUE/FALSE
+**
+*******************************************************************************/
+unsigned char userial_to_tcio_baud(unsigned char cfg_baud, unsigned int *baud)
+{
+    if (cfg_baud == USERIAL_BAUD_115200)
+        *baud = B115200;
+    else if (cfg_baud == USERIAL_BAUD_4M)
+        *baud = B4000000;
+    else if (cfg_baud == USERIAL_BAUD_3M)
+        *baud = B3000000;
+    else if (cfg_baud == USERIAL_BAUD_2M)
+        *baud = B2000000;
+    else if (cfg_baud == USERIAL_BAUD_1M)
+        *baud = B1000000;
+    else if (cfg_baud == USERIAL_BAUD_921600)
+        *baud = B921600;
+    else if (cfg_baud == USERIAL_BAUD_460800)
+        *baud = B460800;
+    else if (cfg_baud == USERIAL_BAUD_230400)
+        *baud = B230400;
+    else if (cfg_baud == USERIAL_BAUD_57600)
+        *baud = B57600;
+    else if (cfg_baud == USERIAL_BAUD_19200)
+        *baud = B19200;
+    else if (cfg_baud == USERIAL_BAUD_9600)
+        *baud = B9600;
+    else if (cfg_baud == USERIAL_BAUD_1200)
+        *baud = B1200;
+    else if (cfg_baud == USERIAL_BAUD_600)
+        *baud = B600;
+    else
+    {
+        fprintf(stderr,  "userial vendor open: unsupported baud idx %i\n", cfg_baud);
+        *baud = B115200;
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+/*******************************************************************************
+**
+** Function        userial_vendor_set_baud
+**
+** Description     Set new baud rate
+**
+** Returns         None
+**
+*******************************************************************************/
+void userial_vendor_set_baud(unsigned char userial_baud)
+{
+    unsigned int tcio_baud;
+    fprintf(stderr, "## userial_vendor_set_baud: %d\n", userial_baud);
+
+    userial_to_tcio_baud(userial_baud, &tcio_baud);
+
+    cfsetospeed(&vnd_userial.termios, tcio_baud);
+    cfsetispeed(&vnd_userial.termios, tcio_baud);
+    tcsetattr(vnd_userial.fd, TCSADRAIN, &vnd_userial.termios); /* don't change speed until last write done */
+
+}
+
+
+/*******************************************************************************
+**
+** Function        userial_vendor_ioctl
+**
+** Description     ioctl inteface
+**
+** Returns         None
+**
+*******************************************************************************/
+int userial_vendor_ioctl(int fd, userial_vendor_ioctl_op_t op, int *p_data)
+{
+    int err = -1;
+    struct termios ti;
+
+    if (tcgetattr(fd, &ti) < 0) {
+            perror("Can't get port settings");
+            return -1;
+    }
+    cfmakeraw(&ti);
+    ti.c_cflag |= CLOCAL;
+
+    switch(op)
+    {
+#if (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+        case USERIAL_OP_ASSERT_BT_WAKE:
+            VNDUSERIALDBG("## userial_vendor_ioctl: Asserting BT_Wake ##");
+            err = ioctl(fd, USERIAL_IOCTL_BT_WAKE_ASSERT, NULL);
+            break;
+
+        case USERIAL_OP_DEASSERT_BT_WAKE:
+            VNDUSERIALDBG("## userial_vendor_ioctl: De-asserting BT_Wake ##");
+            err = ioctl(fd, USERIAL_IOCTL_BT_WAKE_DEASSERT, NULL);
+            break;
+
+        case USERIAL_OP_GET_BT_WAKE_STATE:
+            err = ioctl(fd, USERIAL_IOCTL_BT_WAKE_GET_ST, p_data);
+            break;
+#endif  //  (BT_WAKE_VIA_USERIAL_IOCTL==TRUE)
+        case USERIAL_OP_FLOW_ON:
+            fprintf(stderr, "## userial_vendor_ioctl: UART Flow On\n ");
+            ti.c_cflag |= CRTSCTS;
+
+            if (err = tcsetattr(fd, TCSANOW, &ti) < 0) {
+                perror("Can't set port settings");
+                return -1;
+            }
+
+            break;
+
+        case USERIAL_OP_FLOW_OFF:
+            fprintf(stderr, "## userial_vendor_ioctl: UART Flow Off\n ");
+            ti.c_cflag &= ~CRTSCTS;
+            if (err = tcsetattr(fd, TCSANOW, &ti) < 0) {
+                fprintf(stderr, "Can't set port settings");
+                return -1;
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    return err;
+}
+
+
+int get_vs_hci_event(unsigned char *rsp)
+{
+    int err = 0, soc_id =0;
+    unsigned char paramlen = 0;
+
+    if( (rsp[EVENTCODE_OFFSET] == VSEVENT_CODE) || (rsp[EVENTCODE_OFFSET] == EVT_CMD_COMPLETE))
+        fprintf(stderr, "%s: Received HCI-Vendor Specific event\n", __FUNCTION__);
+    else {
+        fprintf(stderr, "%s: Failed to receive HCI-Vendor Specific event\n", __FUNCTION__);
+        err = -EIO;
+        goto failed;
+    }
+
+    fprintf(stderr, "%s: Parameter Length: 0x%x\n", __FUNCTION__, paramlen = rsp[EVT_PLEN]);
+    fprintf(stderr, "%s: Command response: 0x%x\n", __FUNCTION__, rsp[CMD_RSP_OFFSET]);
+    fprintf(stderr, "%s: Response type   : 0x%x\n", __FUNCTION__, rsp[RSP_TYPE_OFFSET]);
+
+    /* Check the status of the operation */
+    switch ( rsp[CMD_RSP_OFFSET] )
+    {
+        case EDL_CMD_REQ_RES_EVT:
+        fprintf(stderr, "%s: Command Request Response\n", __FUNCTION__);
+        switch(rsp[RSP_TYPE_OFFSET])
+        {
+            case EDL_PATCH_VER_RES_EVT:
+            case EDL_APP_VER_RES_EVT:
+                fprintf(stderr, "\t Current Product ID\t\t: 0x%08x\n",
+                    (unsigned int)(rsp[PATCH_PROD_ID_OFFSET +3] << 24 |
+                                        rsp[PATCH_PROD_ID_OFFSET+2] << 16 |
+                                        rsp[PATCH_PROD_ID_OFFSET+1] << 8 |
+                                        rsp[PATCH_PROD_ID_OFFSET]  ));
+
+                /* Patch Version indicates FW patch version */
+                fprintf(stderr, "\t Current Patch Version\t\t: 0x%04x\n",
+                    (unsigned short)(rsp[PATCH_PATCH_VER_OFFSET + 1] << 8 |
+                                            rsp[PATCH_PATCH_VER_OFFSET] ));
+
+                /* ROM Build Version indicates ROM build version like 1.0/1.1/2.0 */
+                fprintf(stderr, "\t Current ROM Build Version\t: 0x%04x\n", rome_ver =
+                    (int)(rsp[PATCH_ROM_BUILD_VER_OFFSET + 1] << 8 |
+                                            rsp[PATCH_ROM_BUILD_VER_OFFSET] ));
+
+                /* In case rome 1.0/1.1, there is no SOC ID version available */
+                if (paramlen - 10)
+                {
+                    fprintf(stderr, "\t Current SOC Version\t\t: 0x%08x\n", soc_id =
+                        (unsigned int)(rsp[PATCH_SOC_VER_OFFSET +3] << 24 |
+                                                rsp[PATCH_SOC_VER_OFFSET+2] << 16 |
+                                                rsp[PATCH_SOC_VER_OFFSET+1] << 8 |
+                                                rsp[PATCH_SOC_VER_OFFSET]  ));
+                }
+
+                /* Rome Chipset Version can be decided by Patch version and SOC version,
+                Upper 2 bytes will be used for Patch version and Lower 2 bytes will be
+                used for SOC as combination for BT host driver */
+                rome_ver = (rome_ver << 16) | (soc_id & 0x0000ffff);
+                break;
+            case EDL_TVL_DNLD_RES_EVT:
+            case EDL_CMD_EXE_STATUS_EVT:
+                switch (err = rsp[CMD_STATUS_OFFSET])
+                    {
+                    case HCI_CMD_SUCCESS:
+                        fprintf(stderr, "%s: Download Packet successfully!\n", __FUNCTION__);
+                        break;
+                    case PATCH_LEN_ERROR:
+                        fprintf(stderr, "%s: Invalid patch length argument passed for EDL PATCH "
+                        "SET REQ cmd\n", __FUNCTION__);
+                        break;
+                    case PATCH_VER_ERROR:
+                        fprintf(stderr, "%s: Invalid patch version argument passed for EDL PATCH "
+                        "SET REQ cmd\n", __FUNCTION__);
+                        break;
+                    case PATCH_CRC_ERROR:
+                        fprintf(stderr, "%s: CRC check of patch failed!!!\n", __FUNCTION__);
+                        break;
+                    case PATCH_NOT_FOUND:
+                        fprintf(stderr, "%s: Invalid patch data!!!\n", __FUNCTION__);
+                        break;
+                    case TLV_TYPE_ERROR:
+                        fprintf(stderr, "%s: TLV Type Error !!!\n", __FUNCTION__);
+                        break;
+                    default:
+                        fprintf(stderr, "%s: Undefined error (0x%x)", __FUNCTION__, err);
+                        break;
+                    }
+            break;
+        }
+        break;
+
+        case NVM_ACCESS_CODE:
+            fprintf(stderr, "%s: NVM Access Code!!!\n", __FUNCTION__);
+            err = HCI_CMD_SUCCESS;
+            break;
+        case EDL_SET_BAUDRATE_RSP_EVT:
+            /* Rome 1.1 has bug with the response, so it should ignore it. */
+            if (rsp[BAUDRATE_RSP_STATUS_OFFSET] != BAUDRATE_CHANGE_SUCCESS)
+            {
+                fprintf(stderr, "%s: Set Baudrate request failed - 0x%x\n", __FUNCTION__,
+                    rsp[CMD_STATUS_OFFSET]);
+                err = -1;
+            }
+            break;
+        default:
+            fprintf(stderr, "%s: Not a valid status!!!\n", __FUNCTION__);
+            err = -1;
+            break;
+    }
+
+failed:
+    return err;
+}
+
+
+/*
+ * Read an VS HCI event from the given file descriptor.
+ */
+int read_vs_hci_event(int fd, unsigned char* buf, int size)
+{
+    int remain, r;
+    int count = 0;
+
+    if (size <= 0) {
+        fprintf(stderr, "Invalid size arguement!\n");
+        return -1;
+    }
+
+    fprintf(stderr, "%s: Wait for HCI-Vendor Specfic Event from SOC\n", __FUNCTION__);
+
+    /* The first byte identifies the packet type. For HCI event packets, it
+     * should be 0x04, so we read until we get to the 0x04. */
+    /* It will keep reading until find 0x04 byte */
+    while (1) {
+            r = read(fd, buf, 1);
+            if (r <= 0)
+                    return -1;
+            if (buf[0] == 0x04)
+                    break;
+    }
+    count++;
+
+    fprintf(stderr, "%s: Wait for HCI-Vendor Specfic Event from SOC, buf[0] - 0x%x\n", __FUNCTION__, buf[0]);
+    /* The next two bytes are the event code and parameter total length. */
+    while (count < 3) {
+            r = read(fd, buf + count, 3 - count);
+            if ((r <= 0) || (buf[1] != 0xFF )) {
+                fprintf(stderr, "It is not VS event !!\n");
+                return -1;
+            }
+            count += r;
+    }
+
+    fprintf(stderr, "%s: Wait for HCI-Vendor Specfic Event from SOC, buf[1] - 0x%x\n", __FUNCTION__, buf[1]);
+    /* Now we read the parameters. */
+    if (buf[2] < (size - 3))
+            remain = buf[2];
+    else
+            remain = size - 3;
+
+    while ((count - 3) < remain) {
+            r = read(fd, buf + count, remain - (count - 3));
+            if (r <= 0)
+                    return -1;
+            count += r;
+    }
+
+     /* Check if the set patch command is successful or not */
+    if(get_vs_hci_event(buf) != HCI_CMD_SUCCESS)
+        return -1;
+
+    fprintf(stderr, "%s: Wait for HCI-Vendor Specfic Event from SOC, count - 0x%x\n", __FUNCTION__, count);
+    return count;
+}
+
+
+int hci_send_vs_cmd(int fd, unsigned char *cmd, unsigned char *rsp, int size)
+{
+    int ret = 0;
+
+    /* Send the HCI command packet to UART for transmission */
+    ret = write(fd, cmd, size);
+    if (ret != size) {
+        fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, ret);
+        goto failed;
+    }
+
+    /* Check for response from the Controller */
+    if (read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE) < 0) {
+        ret = -ETIMEDOUT;
+        fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__);
+        goto failed;
+    }
+
+    fprintf(stderr, "%s: Received HCI-Vendor Specific Event from SOC\n", __FUNCTION__);
+failed:
+    return ret;
+}
+
+void frame_hci_cmd_pkt(
+    unsigned char *cmd,
+    int edl_cmd, unsigned int p_base_addr,
+    int segtNo, int size
+    )
+{
+    int offset = 0;
+    hci_command_hdr *cmd_hdr;
+
+    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, HCI_PATCH_CMD_OCF);
+    cmd_hdr->plen   = size;
+    cmd[4]      = edl_cmd;
+
+    switch (edl_cmd)
+    {
+        case EDL_PATCH_SET_REQ_CMD:
+            /* Copy the patch header info as CMD params */
+            memcpy(&cmd[5], phdr_buffer, PATCH_HDR_LEN);
+            fprintf(stderr, "%s: Sending EDL_PATCH_SET_REQ_CMD\n", __FUNCTION__);
+            fprintf(stderr, "HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n",
+                segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+            break;
+        case EDL_PATCH_DLD_REQ_CMD:
+            offset = ((segtNo - 1) * MAX_DATA_PER_SEGMENT);
+            p_base_addr += offset;
+            cmd_hdr->plen   = (size + 6);
+            cmd[5]  = (size + 4);
+            cmd[6]  = EXTRACT_BYTE(p_base_addr, 0);
+            cmd[7]  = EXTRACT_BYTE(p_base_addr, 1);
+            cmd[8]  = EXTRACT_BYTE(p_base_addr, 2);
+            cmd[9]  = EXTRACT_BYTE(p_base_addr, 3);
+            memcpy(&cmd[10], (pdata_buffer + offset), size);
+
+            fprintf(stderr, "%s: Sending EDL_PATCH_DLD_REQ_CMD: size: %d bytes\n",
+                __FUNCTION__, size);
+            fprintf(stderr, "HCI-CMD %d:\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t"
+                "0x%x\t0x%x\t0x%x\t\n", segtNo, cmd[0], cmd[1], cmd[2],
+                cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9]);
+            break;
+        case EDL_PATCH_ATCH_REQ_CMD:
+            fprintf(stderr, "%s: Sending EDL_PATCH_ATTACH_REQ_CMD\n", __FUNCTION__);
+            fprintf(stderr, "HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n",
+            segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+            break;
+        case EDL_PATCH_RST_REQ_CMD:
+            fprintf(stderr, "%s: Sending EDL_PATCH_RESET_REQ_CMD\n", __FUNCTION__);
+            fprintf(stderr, "HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n",
+            segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+            break;
+        case EDL_PATCH_VER_REQ_CMD:
+            fprintf(stderr, "%s: Sending EDL_PATCH_VER_REQ_CMD\n", __FUNCTION__);
+            fprintf(stderr, "HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n",
+            segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
+            break;
+        case EDL_PATCH_TLV_REQ_CMD:
+            fprintf(stderr, "%s: Sending EDL_PATCH_TLV_REQ_CMD\n", __FUNCTION__);
+            /* Parameter Total Length */
+            cmd[3] = size +2;
+
+            /* TLV Segment Length */
+            cmd[5] = size;
+            fprintf(stderr, "HCI-CMD %d:\t0x%x \t0x%x \t0x%x \t0x%x \t0x%x \t0x%x\n",
+            segtNo, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]);
+            offset = (segtNo * MAX_SIZE_PER_TLV_SEGMENT);
+            memcpy(&cmd[6], (pdata_buffer + offset), size);
+            break;
+        default:
+            fprintf(stderr, "%s: Unknown EDL CMD !!!\n", __FUNCTION__);
+    }
+}
+
+void rome_extract_patch_header_info(unsigned char *buf)
+{
+    int index;
+
+    /* Extract patch id */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_id |=
+            (LSH(buf[index + P_ID_OFFSET], (index * 8)));
+
+    /* Extract (ROM and BUILD) version information */
+    for (index = 0; index < 2; index++)
+        rampatch_patch_info.patch_ver.rom_version |=
+            (LSH(buf[index + P_ROME_VER_OFFSET], (index * 8)));
+
+    for (index = 0; index < 2; index++)
+        rampatch_patch_info.patch_ver.build_version |=
+            (LSH(buf[index + P_BUILD_VER_OFFSET], (index * 8)));
+
+    /* Extract patch base and entry addresses */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_base_addr |=
+            (LSH(buf[index + P_BASE_ADDR_OFFSET], (index * 8)));
+
+    /* Patch BASE & ENTRY addresses are same */
+    rampatch_patch_info.patch_entry_addr = rampatch_patch_info.patch_base_addr;
+
+    /* Extract total length of the patch payload */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_length |=
+            (LSH(buf[index + P_LEN_OFFSET], (index * 8)));
+
+    /* Extract the CRC checksum of the patch payload */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_crc |=
+            (LSH(buf[index + P_CRC_OFFSET], (index * 8)));
+
+    /* Extract patch control value */
+    for (index = 0; index < 4; index++)
+        rampatch_patch_info.patch_ctrl |=
+            (LSH(buf[index + P_CONTROL_OFFSET], (index * 8)));
+
+    fprintf(stderr, "PATCH_ID\t : 0x%x\n", rampatch_patch_info.patch_id);
+    fprintf(stderr, "ROM_VERSION\t : 0x%x\n", rampatch_patch_info.patch_ver.rom_version);
+    fprintf(stderr, "BUILD_VERSION\t : 0x%x\n", rampatch_patch_info.patch_ver.build_version);
+    fprintf(stderr, "PATCH_LENGTH\t : 0x%x\n", rampatch_patch_info.patch_length);
+    fprintf(stderr, "PATCH_CRC\t : 0x%x\n", rampatch_patch_info.patch_crc);
+    fprintf(stderr, "PATCH_CONTROL\t : 0x%x\n", rampatch_patch_info.patch_ctrl);
+    fprintf(stderr, "PATCH_BASE_ADDR\t : 0x%x\n", rampatch_patch_info.patch_base_addr);
+
+}
+
+int rome_edl_set_patch_request(int fd)
+{
+    int size, err;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    /* Frame the HCI CMD to be sent to the Controller */
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_SET_REQ_CMD, 0,
+        -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]);
+
+    /* Send HCI Command packet to Controller */
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        fprintf(stderr, "Failed to set the patch info to the Controller!\n");
+        goto error;
+    }
+
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        fprintf(stderr, "%s: Failed to set patch info on Controller\n", __FUNCTION__);
+        goto error;
+    }
+    fprintf(stderr, "%s: Successfully set patch info on the Controller\n", __FUNCTION__);
+error:
+    return err;
+}
+
+int rome_edl_patch_download_request(int fd)
+{
+    int no_of_patch_segment;
+    int index = 1, err = 0, size = 0;
+    unsigned int p_base_addr;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    no_of_patch_segment = (rampatch_patch_info.patch_length /
+        MAX_DATA_PER_SEGMENT);
+    fprintf(stderr, "%s: %d patch segments to be d'loaded from patch base addr: 0x%x\n",
+        __FUNCTION__, no_of_patch_segment,
+    rampatch_patch_info.patch_base_addr);
+
+    /* Initialize the patch base address from the one read from bin file */
+    p_base_addr = rampatch_patch_info.patch_base_addr;
+
+    /*
+    * Depending upon size of the patch payload, download the patches in
+    * segments with a max. size of 239 bytes
+    */
+    for (index = 1; index <= no_of_patch_segment; index++) {
+
+        fprintf(stderr, "%s: Downloading patch segment: %d\n", __FUNCTION__, index);
+
+        /* Frame the HCI CMD PKT to be sent to Controller*/
+        frame_hci_cmd_pkt(cmd, EDL_PATCH_DLD_REQ_CMD, p_base_addr,
+        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]);
+
+        /* Initialize the RSP packet everytime to 0 */
+        memset(rsp, 0x0, HCI_MAX_EVENT_SIZE);
+
+        /* Send HCI Command packet to Controller */
+        err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+        if ( err != size) {
+            fprintf(stderr, "Failed to send the patch payload to the Controller!\n");
+            goto error;
+        }
+
+        /* Read Command Complete Event */
+        err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+        if ( err < 0) {
+            fprintf(stderr, "%s: Failed to downlaod patch segment: %d!\n",
+            __FUNCTION__, index);
+            goto error;
+        }
+        fprintf(stderr, "%s: Successfully downloaded patch segment: %d\n",
+        __FUNCTION__, index);
+    }
+
+    /* Check if any pending patch data to be sent */
+    size = (rampatch_patch_info.patch_length < MAX_DATA_PER_SEGMENT) ?
+        rampatch_patch_info.patch_length :
+        (rampatch_patch_info.patch_length  % MAX_DATA_PER_SEGMENT);
+
+    if (size)
+    {
+        /* Frame the HCI CMD PKT to be sent to Controller*/
+        frame_hci_cmd_pkt(cmd, EDL_PATCH_DLD_REQ_CMD, p_base_addr, index, size);
+
+        /* Initialize the RSP packet everytime to 0 */
+        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]);
+
+        /* Send HCI Command packet to Controller */
+        err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+        if ( err != size) {
+            fprintf(stderr, "Failed to send the patch payload to the Controller!\n");
+            goto error;
+        }
+
+        /* Read Command Complete Event */
+        err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+        if ( err < 0) {
+            fprintf(stderr, "%s: Failed to downlaod patch segment: %d!\n",
+                __FUNCTION__, index);
+            goto error;
+        }
+
+        fprintf(stderr, "%s: Successfully downloaded patch segment: %d\n",
+        __FUNCTION__, index);
+    }
+
+error:
+    return err;
+}
+
+static int rome_download_rampatch(int fd)
+{
+    int c, size, index, ret = -1;
+
+    fprintf(stderr, "%s:\n", __FUNCTION__);
+
+    /* Get handle to the RAMPATCH binary file */
+    fprintf(stderr, "%s: Getting handle to the RAMPATCH binary file from %s\n", __FUNCTION__, ROME_FW_PATH);
+    file = fopen(ROME_FW_PATH, "r");
+    if (file == NULL) {
+        fprintf(stderr, "%s: Failed to get handle to the RAMPATCH bin file!\n",
+        __FUNCTION__);
+        return -ENFILE;
+    }
+
+    /* Allocate memory for the patch headder info */
+    fprintf(stderr, "%s: Allocating memory for the patch header\n", __FUNCTION__);
+    phdr_buffer = (unsigned char *) malloc(PATCH_HDR_LEN + 1);
+    if (phdr_buffer == NULL) {
+        fprintf(stderr, "%s: Failed to allocate memory for patch header\n",
+        __FUNCTION__);
+        goto phdr_alloc_failed;
+    }
+    for (index = 0; index < PATCH_HDR_LEN + 1; index++)
+        phdr_buffer[index] = 0x0;
+
+    /* Read 28 bytes of patch header information */
+    fprintf(stderr, "%s: Reading patch header info\n", __FUNCTION__);
+    index = 0;
+    do {
+        c = fgetc (file);
+        phdr_buffer[index++] = (unsigned char)c;
+    } while (index != PATCH_HDR_LEN);
+
+    /* Save the patch header info into local structure */
+    fprintf(stderr, "%s: Saving patch hdr. info\n", __FUNCTION__);
+    rome_extract_patch_header_info((unsigned char *)phdr_buffer);
+
+    /* Set the patch header info onto the Controller */
+    ret = rome_edl_set_patch_request(fd);
+    if (ret < 0) {
+        fprintf(stderr, "%s: Error setting the patchheader info!\n", __FUNCTION__);
+        goto pdata_alloc_failed;
+    }
+
+    /* Allocate memory for the patch payload */
+    fprintf(stderr, "%s: Allocating memory for patch payload\n", __FUNCTION__);
+    size = rampatch_patch_info.patch_length;
+    pdata_buffer = (unsigned char *) malloc(size+1);
+    if (pdata_buffer == NULL) {
+        fprintf(stderr, "%s: Failed to allocate memory for patch payload\n",
+            __FUNCTION__);
+        goto pdata_alloc_failed;
+    }
+    for (index = 0; index < size+1; index++)
+        pdata_buffer[index] = 0x0;
+
+    /* Read the patch data from Rampatch binary image */
+    fprintf(stderr, "%s: Reading patch payload from RAMPATCH file\n", __FUNCTION__);
+    index = 0;
+    do {
+        c = fgetc (file);
+        pdata_buffer[index++] = (unsigned char)c;
+    } while (c != EOF);
+
+    /* Downloading patches in segments to controller */
+    ret = rome_edl_patch_download_request(fd);
+    if (ret < 0) {
+        fprintf(stderr, "%s: Error downloading patch segments!\n", __FUNCTION__);
+        goto cleanup;
+    }
+cleanup:
+    free(pdata_buffer);
+pdata_alloc_failed:
+    free(phdr_buffer);
+phdr_alloc_failed:
+    fclose(file);
+
+    return ret;
+}
+
+int rome_attach_rampatch(int fd)
+{
+    int size, err;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    /* Frame the HCI CMD to be sent to the Controller */
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_ATCH_REQ_CMD, 0,
+        -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]);
+
+    /* Send HCI Command packet to Controller */
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        fprintf(stderr, "Failed to attach the patch payload to the Controller!\n");
+        goto error;
+    }
+
+    /* Read Command Complete Event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        fprintf(stderr, "%s: Failed to attach the patch segment(s)\n", __FUNCTION__);
+        goto error;
+    }
+error:
+    return err;
+}
+
+int rome_rampatch_reset(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    struct timespec tm = { 0, 100*1000*1000 }; /* 100 ms */
+
+    /* Frame the HCI CMD to be sent to the Controller */
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_RST_REQ_CMD, 0,
+                                        -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);
+
+    /* Send HCI Command packet to Controller */
+    err = write(fd, cmd, size);
+    if (err != size) {
+        fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, err);
+        goto error;
+    }
+
+    /*
+    * Controller doesn't sends any response for the patch reset
+    * command. HOST has to wait for 100ms before proceeding.
+    */
+    nanosleep(&tm, NULL);
+
+error:
+    return err;
+}
+
+int rome_get_tlv_file(char *file_path)
+{
+    FILE * pFile;
+    long fileSize;
+    int readSize, nvm_length, nvm_index, i;
+    unsigned short nvm_tag_len;
+    tlv_patch_info *ptlv_header;
+    tlv_nvm_hdr *nvm_ptr;
+    unsigned char data_buf[PRINT_BUF_SIZE]={0,};
+    unsigned char *nvm_byte_ptr;
+
+    fprintf(stderr, "File Open (%s)\n", file_path);
+    pFile = fopen ( file_path , "r" );
+    if (pFile==NULL) {;
+        fprintf(stderr, "%s File Open Fail\n", file_path);
+        return -1;
+    }
+
+    /* Get File Size */
+    fseek (pFile , 0 , SEEK_END);
+    fileSize = ftell (pFile);
+    rewind (pFile);
+
+    pdata_buffer = (unsigned char*) malloc (sizeof(char)*fileSize);
+    if (pdata_buffer == NULL) {
+        fprintf(stderr, "Allocated Memory failed\n");
+        fclose (pFile);
+        return -1;
+    }
+
+    /* Copy file into allocated buffer */
+    readSize = fread (pdata_buffer,1,fileSize,pFile);
+
+    /* File Close */
+    fclose (pFile);
+
+    if (readSize != fileSize) {
+        fprintf(stderr, "Read file size(%d) not matched with actual file size (%ld bytes)\n",readSize,fileSize);
+        return -1;
+    }
+
+    ptlv_header = (tlv_patch_info *) pdata_buffer;
+
+    /* To handle different event between rampatch and NVM */
+    gTlv_type = ptlv_header->tlv_type;
+
+    if(ptlv_header->tlv_type == TLV_TYPE_PATCH){
+        fprintf(stderr, "====================================================\n");
+        fprintf(stderr, "TLV Type\t\t\t : 0x%x\n", ptlv_header->tlv_type);
+        fprintf(stderr, "Length\t\t\t : %d bytes\n", (ptlv_header->tlv_length1) |
+                                                    (ptlv_header->tlv_length2 << 8) |
+                                                    (ptlv_header->tlv_length3 << 16));
+        fprintf(stderr, "Total Length\t\t\t : %d bytes\n", ptlv_header->tlv_data_len);
+        fprintf(stderr, "Patch Data Length\t\t\t : %d bytes\n",ptlv_header->tlv_patch_data_len);
+        fprintf(stderr, "Signing Format Version\t : 0x%x\n", ptlv_header->tlv.patch.sign_ver);
+        fprintf(stderr, "Signature Algorithm\t\t : 0x%x\n", ptlv_header->tlv.patch.sign_algorithm);
+        fprintf(stderr, "Reserved\t\t\t : 0x%x\n", ptlv_header->tlv.patch.reserved1);
+        fprintf(stderr, "Product ID\t\t\t : 0x%04x\n", ptlv_header->tlv.patch.prod_id);
+        fprintf(stderr, "Rom Build Version\t\t : 0x%04x\n", ptlv_header->tlv.patch.build_ver);
+        fprintf(stderr, "Patch Version\t\t : 0x%04x\n", ptlv_header->tlv.patch.patch_ver);
+        fprintf(stderr, "Reserved\t\t\t : 0x%x\n", ptlv_header->tlv.patch.reserved2);
+        fprintf(stderr, "Patch Entry Address\t\t : 0x%x\n", (ptlv_header->tlv.patch.patch_entry_addr));
+        fprintf(stderr, "====================================================\n");
+
+    } else if(ptlv_header->tlv_type == TLV_TYPE_NVM) {
+        fprintf(stderr, "====================================================\n");
+        fprintf(stderr, "TLV Type\t\t\t : 0x%x\n", ptlv_header->tlv_type);
+        fprintf(stderr, "Length\t\t\t : %d bytes\n",  nvm_length = (ptlv_header->tlv_length1) |
+                                                    (ptlv_header->tlv_length2 << 8) |
+                                                    (ptlv_header->tlv_length3 << 16));
+
+        if(nvm_length <= 0)
+            return readSize;
+
+       for(nvm_byte_ptr=(unsigned char *)(nvm_ptr = &(ptlv_header->tlv.nvm)), nvm_index=0;
+             nvm_index < nvm_length ; nvm_ptr = (tlv_nvm_hdr *) nvm_byte_ptr)
+       {
+            fprintf(stderr, "TAG ID\t\t\t : %d\n", nvm_ptr->tag_id);
+            fprintf(stderr, "TAG Length\t\t\t : %d\n", nvm_tag_len = nvm_ptr->tag_len);
+            fprintf(stderr, "TAG Pointer\t\t\t : %d\n", nvm_ptr->tag_ptr);
+            fprintf(stderr, "TAG Extended Flag\t\t : %d\n", nvm_ptr->tag_ex_flag);
+
+            /* Increase nvm_index to NVM data */
+            nvm_index+=sizeof(tlv_nvm_hdr);
+            nvm_byte_ptr+=sizeof(tlv_nvm_hdr);
+
+            /* Write BD Address */
+            if(nvm_ptr->tag_id == TAG_NUM_2){
+                memcpy(nvm_byte_ptr, vnd_local_bd_addr, 6);
+                fprintf(stderr, "BD Address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x\n",
+                    *nvm_byte_ptr, *(nvm_byte_ptr+1), *(nvm_byte_ptr+2),
+                    *(nvm_byte_ptr+3), *(nvm_byte_ptr+4), *(nvm_byte_ptr+5));
+            }
+
+            for(i =0;(i<nvm_ptr->tag_len && (i*3 + 2) <PRINT_BUF_SIZE);i++)
+                snprintf((char *) data_buf, PRINT_BUF_SIZE, "%s%.02x ", (char *)data_buf, *(nvm_byte_ptr + i));
+
+            fprintf(stderr, "TAG Data\t\t\t : %s\n", data_buf);
+
+            /* Clear buffer */
+            memset(data_buf, 0x0, PRINT_BUF_SIZE);
+
+            /* increased by tag_len */
+            nvm_index+=nvm_ptr->tag_len;
+            nvm_byte_ptr +=nvm_ptr->tag_len;
+        }
+
+        fprintf(stderr, "====================================================\n");
+
+    } else {
+        fprintf(stderr, "TLV Header type is unknown (%d) \n", ptlv_header->tlv_type);
+    }
+
+    return readSize;
+}
+
+int rome_tlv_dnld_segment(int fd, int index, int seg_size, unsigned char wait_cc_evt)
+{
+    int size=0, err = -1;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    fprintf(stderr, "%s: Downloading TLV Patch segment no.%d, size:%d\n", __FUNCTION__, index, seg_size);
+
+    /* Frame the HCI CMD PKT to be sent to Controller*/
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_TLV_REQ_CMD, 0, index, seg_size);
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + cmd[PLEN]);
+
+    /* Initialize the RSP packet everytime to 0 */
+    memset(rsp, 0x0, HCI_MAX_EVENT_SIZE);
+
+    /* Send HCI Command packet to Controller */
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        fprintf(stderr, "Failed to send the patch payload to the Controller! 0x%x\n", err);
+        return err;
+    }
+
+    if(wait_cc_evt) {
+        err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+        if ( err < 0) {
+            fprintf(stderr, "%s: Failed to downlaod patch segment: %d!\n",  __FUNCTION__, index);
+            return err;
+        }
+    }
+
+    fprintf(stderr, "%s: Successfully downloaded patch segment: %d\n", __FUNCTION__, index);
+    return err;
+}
+
+int rome_tlv_dnld_req(int fd, int tlv_size)
+{
+    int  total_segment, remain_size, i, err = -1;
+    unsigned char wait_cc_evt;
+
+    total_segment = tlv_size/MAX_SIZE_PER_TLV_SEGMENT;
+    remain_size = (tlv_size < MAX_SIZE_PER_TLV_SEGMENT)?\
+        tlv_size: (tlv_size%MAX_SIZE_PER_TLV_SEGMENT);
+
+    fprintf(stderr, "%s: TLV size: %d, Total Seg num: %d, remain size: %d\n",
+        __FUNCTION__,tlv_size, total_segment, remain_size);
+
+    for(i=0;i<total_segment ;i++){
+        /* In case of ROME 1.1, last rampatch segment command will not wait for
+            command complete event */
+        wait_cc_evt = ((rome_ver >= ROME_VER_1_1) && (gTlv_type == TLV_TYPE_PATCH )
+             && !remain_size && ((i+1) == total_segment))? FALSE: TRUE;
+        if((err = rome_tlv_dnld_segment(fd, i, MAX_SIZE_PER_TLV_SEGMENT, wait_cc_evt )) < 0)
+            goto error;
+    }
+
+    /* In case remain data still remain, last rampatch segment command will not wait
+        for command complete event here */
+    wait_cc_evt = ((rome_ver >= ROME_VER_1_1) && (gTlv_type == TLV_TYPE_PATCH )
+         && remain_size )? FALSE:TRUE;
+
+    if(remain_size) err =rome_tlv_dnld_segment(fd, i, remain_size, wait_cc_evt);
+
+error:
+    return err;
+}
+
+int rome_download_tlv_file(int fd)
+{
+    int tlv_size, err = -1;
+
+    /* Rampatch TLV file Downloading */
+    pdata_buffer = NULL;
+
+    if((tlv_size = rome_get_tlv_file(rampatch_file_path)) < 0)
+        goto error;
+
+    if((err =rome_tlv_dnld_req(fd, tlv_size)) <0 )
+        goto error;
+
+    if (pdata_buffer != NULL){
+        free (pdata_buffer);
+        pdata_buffer = NULL;
+    }
+
+    /* NVM TLV file Downloading */
+    if((tlv_size = rome_get_tlv_file(nvm_file_path)) < 0)
+        goto error;
+
+    if((err =rome_tlv_dnld_req(fd, tlv_size)) <0 )
+        goto error;
+
+error:
+    if (pdata_buffer != NULL)
+        free (pdata_buffer);
+
+    return err;
+}
+
+int rome_1_0_nvm_tag_dnld(int fd)
+{
+    int i, size, err = 0;
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+#if (NVM_VERSION >= ROME_1_0_100019)
+    unsigned char cmds[MAX_TAG_CMD][HCI_MAX_CMD_SIZE] =
+    {
+        /* Tag 2 */ /* BD Address */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     9,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     2,
+            /* Tag Len */      6,
+            /* Tag Value */   0x77,0x78,0x23,0x01,0x56,0x22
+         },
+        /* Tag 6 */ /* Bluetooth Support Features */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     11,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     6,
+            /* Tag Len */      8,
+            /* Tag Value */   0xFF,0xFE,0x8B,0xFE,0xD8,0x3F,0x5B,0x8B
+         },
+        /* Tag 17 */ /* HCI Transport Layer Setting */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     11,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     17,
+            /* Tag Len */      8,
+            /* Tag Value */   0x82,0x01,0x0E,0x08,0x04,0x32,0x0A,0x00
+         },
+        /* Tag 35 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     58,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     35,
+            /* Tag Len */      55,
+            /* Tag Value */   0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x58, 0x59,
+                                      0x0E, 0x0E, 0x16, 0x16, 0x16, 0x1E, 0x26, 0x5F, 0x2F, 0x5F,
+                                      0x0E, 0x0E, 0x16, 0x16, 0x16, 0x1E, 0x26, 0x5F, 0x2F, 0x5F,
+                                      0x0C, 0x18, 0x14, 0x24, 0x40, 0x4C, 0x70, 0x80, 0x80, 0x80,
+                                      0x0C, 0x18, 0x14, 0x24, 0x40, 0x4C, 0x70, 0x80, 0x80, 0x80,
+                                      0x1B, 0x14, 0x01, 0x04, 0x48
+         },
+        /* Tag 36 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     15,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     36,
+            /* Tag Len */      12,
+            /* Tag Value */   0x0F,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x04,0x00
+         },
+        /* Tag 39 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     7,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     39,
+            /* Tag Len */      4,
+            /* Tag Value */   0x12,0x00,0x00,0x00
+         },
+        /* Tag 41 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     91,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     41,
+            /* Tag Len */      88,
+            /* Tag Value */   0x15, 0x00, 0x00, 0x00, 0xF6, 0x02, 0x00, 0x00, 0x76, 0x00,
+                                      0x1E, 0x00, 0x29, 0x02, 0x1F, 0x00, 0x61, 0x00, 0x1A, 0x00,
+                                      0x76, 0x00, 0x1E, 0x00, 0x7D, 0x00, 0x40, 0x00, 0x91, 0x00,
+                                      0x06, 0x00, 0x92, 0x00, 0x03, 0x00, 0xA6, 0x01, 0x50, 0x00,
+                                      0xAA, 0x01, 0x15, 0x00, 0xAB, 0x01, 0x0A, 0x00, 0xAC, 0x01,
+                                      0x00, 0x00, 0xB0, 0x01, 0xC5, 0x00, 0xB3, 0x01, 0x03, 0x00,
+                                      0xB4, 0x01, 0x13, 0x00, 0xB5, 0x01, 0x0C, 0x00, 0xC5, 0x01,
+                                      0x0D, 0x00, 0xC6, 0x01, 0x10, 0x00, 0xCA, 0x01, 0x2B, 0x00,
+                                      0xCB, 0x01, 0x5F, 0x00, 0xCC, 0x01, 0x48, 0x00
+         },
+        /* Tag 42 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     63,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     42,
+            /* Tag Len */      60,
+            /* Tag Value */   0xD7, 0xC0, 0x00, 0x00, 0x8F, 0x5C, 0x02, 0x00, 0x80, 0x47,
+                                      0x60, 0x0C, 0x70, 0x4C, 0x00, 0x00, 0x00, 0x01, 0x1F, 0x01,
+                                      0x42, 0x01, 0x69, 0x01, 0x95, 0x01, 0xC7, 0x01, 0xFE, 0x01,
+                                      0x3D, 0x02, 0x83, 0x02, 0xD1, 0x02, 0x29, 0x03, 0x00, 0x0A,
+                                      0x10, 0x00, 0x1F, 0x00, 0x3F, 0x00, 0x7F, 0x00, 0xFD, 0x00,
+                                      0xF9, 0x01, 0xF1, 0x03, 0xDE, 0x07, 0x00, 0x00, 0x9A, 0x01
+         },
+        /* Tag 84 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     153,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     84,
+            /* Tag Len */      150,
+            /* Tag Value */   0x7C, 0x6A, 0x59, 0x47, 0x19, 0x36, 0x35, 0x25, 0x25, 0x28,
+                                      0x2C, 0x2B, 0x2B, 0x28, 0x2C, 0x28, 0x29, 0x28, 0x29, 0x28,
+                                      0x29, 0x29, 0x2C, 0x29, 0x2C, 0x29, 0x2C, 0x28, 0x29, 0x28,
+                                      0x29, 0x28, 0x29, 0x2A, 0x00, 0x00, 0x2C, 0x2A, 0x2C, 0x18,
+                                      0x98, 0x98, 0x98, 0x98, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E,
+                                      0x1E, 0x13, 0x1E, 0x1E, 0x1E, 0x1E, 0x13, 0x13, 0x11, 0x13,
+                                      0x1E, 0x1E, 0x13, 0x12, 0x12, 0x12, 0x11, 0x12, 0x1F, 0x12,
+                                      0x12, 0x12, 0x10, 0x0C, 0x18, 0x0D, 0x01, 0x01, 0x01, 0x01,
+                                      0x01, 0x01, 0x01, 0x0C, 0x01, 0x01, 0x01, 0x01, 0x0D, 0x0D,
+                                      0x0E, 0x0D, 0x01, 0x01, 0x0D, 0x0D, 0x0D, 0x0D, 0x0F, 0x0D,
+                                      0x10, 0x0D, 0x0D, 0x0D, 0x0D, 0x10, 0x05, 0x10, 0x03, 0x00,
+                                      0x7E, 0x7B, 0x7B, 0x72, 0x71, 0x50, 0x50, 0x50, 0x00, 0x40,
+                                      0x60, 0x60, 0x30, 0x08, 0x02, 0x0F, 0x00, 0x01, 0x00, 0x00,
+                                      0x00, 0x00, 0x00, 0x00, 0x08, 0x16, 0x16, 0x08, 0x08, 0x00,
+                                      0x00, 0x00, 0x1E, 0x34, 0x2B, 0x1B, 0x23, 0x2B, 0x15, 0x0D
+         },
+        /* Tag 85 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     119,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     85,
+            /* Tag Len */      116,
+            /* Tag Value */   0x03, 0x00, 0x38, 0x00, 0x45, 0x77, 0x00, 0xE8, 0x00, 0x59,
+                                      0x01, 0xCA, 0x01, 0x3B, 0x02, 0xAC, 0x02, 0x1D, 0x03, 0x8E,
+                                      0x03, 0x00, 0x89, 0x01, 0x0E, 0x02, 0x5C, 0x02, 0xD7, 0x02,
+                                      0xF8, 0x08, 0x01, 0x00, 0x1F, 0x00, 0x0A, 0x02, 0x55, 0x02,
+                                      0x00, 0x35, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xD7, 0x00, 0x00,
+                                      0x00, 0x1E, 0xDE, 0x00, 0x00, 0x00, 0x14, 0x0F, 0x0A, 0x0F,
+                                      0x0A, 0x0C, 0x0C, 0x0C, 0x0C, 0x04, 0x04, 0x04, 0x0C, 0x0C,
+                                      0x0C, 0x0C, 0x06, 0x06, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+                                      0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00,
+                                      0x06, 0x0F, 0x14, 0x05, 0x47, 0xCF, 0x77, 0x00, 0x00, 0x00,
+                                      0x00, 0x00, 0x00, 0xAC, 0x7C, 0xFF, 0x40, 0x00, 0x00, 0x00,
+                                      0x12, 0x04, 0x04, 0x01, 0x04, 0x03
+         },
+        {TAG_END}
+    };
+#elif (NVM_VERSION == ROME_1_0_6002)
+    unsigned char cmds[MAX_TAG_CMD][HCI_MAX_CMD_SIZE] =
+    {
+        /* Tag 2 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     9,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     2,
+            /* Tag Len */      6,
+            /* Tag Value */   0x77,0x78,0x23,0x01,0x56,0x22 /* BD Address */
+         },
+        /* Tag 6 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     11,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     6,
+            /* Tag Len */      8,
+            /* Tag Value */   0xFF,0xFE,0x8B,0xFE,0xD8,0x3F,0x5B,0x8B
+         },
+        /* Tag 17 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     11,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     17,
+            /* Tag Len */      8,
+            /* Tag Value */   0x82,0x01,0x0E,0x08,0x04,0x32,0x0A,0x00
+         },
+        /* Tag 36 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     15,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     36,
+            /* Tag Len */      12,
+            /* Tag Value */   0x0F,0x00,0x03,0x03,0x03,0x03,0x00,0x00,0x03,0x03,0x04,0x00
+         },
+
+        /* Tag 39 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     7,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     39,
+            /* Tag Len */      4,
+            /* Tag Value */   0x12,0x00,0x00,0x00
+         },
+
+        /* Tag 41 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     199,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     41,
+            /* Tag Len */      196,
+            /* Tag Value */   0x30,0x00,0x00,0x00,0xD5,0x00,0x0E,0x00,0xD6,0x00,0x0E,0x00,
+                                      0xD7,0x00,0x16,0x00,0xD8,0x00,0x16,0x00,0xD9,0x00,0x16,0x00,
+                                      0xDA,0x00,0x1E,0x00,0xDB,0x00,0x26,0x00,0xDC,0x00,0x5F,0x00,
+                                      0xDD,0x00,0x2F,0x00,0xDE,0x00,0x5F,0x00,0xE0,0x00,0x0E,0x00,
+                                      0xE1,0x00,0x0E,0x00,0xE2,0x00,0x16,0x00,0xE3,0x00,0x16,0x00,
+                                      0xE4,0x00,0x16,0x00,0xE5,0x00,0x1E,0x00,0xE6,0x00,0x26,0x00,
+                                      0xE7,0x00,0x5F,0x00,0xE8,0x00,0x2F,0x00,0xE9,0x00,0x5F,0x00,
+                                      0xEC,0x00,0x0C,0x00,0xED,0x00,0x08,0x00,0xEE,0x00,0x14,0x00,
+                                      0xEF,0x00,0x24,0x00,0xF0,0x00,0x40,0x00,0xF1,0x00,0x4C,0x00,
+                                      0xF2,0x00,0x70,0x00,0xF3,0x00,0x80,0x00,0xF4,0x00,0x80,0x00,
+                                      0xF5,0x00,0x80,0x00,0xF8,0x00,0x0C,0x00,0xF9,0x00,0x18,0x00,
+                                      0xFA,0x00,0x14,0x00,0xFB,0x00,0x24,0x00,0xFC,0x00,0x40,0x00,
+                                      0xFD,0x00,0x4C,0x00,0xFE,0x00,0x70,0x00,0xFF,0x00,0x80,0x00,
+                                      0x00,0x01,0x80,0x00,0x01,0x01,0x80,0x00,0x04,0x01,0x1B,0x00,
+                                      0x05,0x01,0x14,0x00,0x06,0x01,0x01,0x00,0x07,0x01,0x04,0x00,
+                                      0x08,0x01,0x00,0x00,0x09,0x01,0x00,0x00,0x0A,0x01,0x03,0x00,
+                                      0x0B,0x01,0x03,0x00
+         },
+
+        /* Tag 44 */
+        {  /* Packet Type */HCI_COMMAND_PKT,
+            /* Opcode */       0x0b,0xfc,
+            /* Total Len */     44,
+            /* NVM CMD */    NVM_ACCESS_SET,
+            /* Tag Num */     44,
+            /* Tag Len */      41,
+            /* Tag Value */   0x6F,0x0A,0x00,0x00,0x00,0x00,0x00,0x50,0xFF,0x10,0x02,0x02,
+                                      0x01,0x00,0x14,0x01,0x06,0x28,0xA0,0x62,0x03,0x64,0x01,0x01,
+                                      0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xFF,0x10,0x02,0x01,
+                                      0x00,0x14,0x01,0x02,0x03
+         },
+        {TAG_END}
+    };
+#endif
+
+    fprintf(stderr, "%s: Start sending NVM Tags (ver: 0x%x)\n", __FUNCTION__, (unsigned int) NVM_VERSION);
+
+    for (i=0; (i < MAX_TAG_CMD) && (cmds[i][0] != TAG_END); i++)
+    {
+        /* Write BD Address */
+        if(cmds[i][TAG_NUM_OFFSET] == TAG_NUM_2){
+            memcpy(&cmds[i][TAG_BDADDR_OFFSET], vnd_local_bd_addr, 6);
+            fprintf(stderr, "BD Address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+                cmds[i][TAG_BDADDR_OFFSET ], cmds[i][TAG_BDADDR_OFFSET + 1],
+                cmds[i][TAG_BDADDR_OFFSET + 2], cmds[i][TAG_BDADDR_OFFSET + 3],
+                cmds[i][TAG_BDADDR_OFFSET + 4], cmds[i][TAG_BDADDR_OFFSET + 5]);
+        }
+        size = cmds[i][3] + HCI_COMMAND_HDR_SIZE + 1;
+        /* Send HCI Command packet to Controller */
+        err = hci_send_vs_cmd(fd, (unsigned char *)&cmds[i][0], rsp, size);
+        if ( err != size) {
+            fprintf(stderr, "Failed to attach the patch payload to the Controller!\n");
+            goto error;
+        }
+
+        /* Read Command Complete Event - This is extra routine for ROME 1.0. From ROM 2.0, it should be removed. */
+        err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+        if ( err < 0) {
+            fprintf(stderr, "%s: Failed to get patch version(s)\n", __FUNCTION__);
+            goto error;
+        }
+    }
+
+error:
+    return err;
+}
+
+
+
+int rome_patch_ver_req(int fd)
+{
+    int size, err = 0;
+    unsigned char cmd[HCI_MAX_CMD_SIZE];
+    unsigned char rsp[HCI_MAX_EVENT_SIZE];
+
+    /* Frame the HCI CMD to be sent to the Controller */
+    frame_hci_cmd_pkt(cmd, EDL_PATCH_VER_REQ_CMD, 0,
+    -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);
+
+    /* Send HCI Command packet to Controller */
+    err = hci_send_vs_cmd(fd, (unsigned char *)cmd, rsp, size);
+    if ( err != size) {
+        fprintf(stderr, "Failed to attach the patch payload to the Controller!\n");
+        goto error;
+    }
+
+    /* Read Command Complete Event - This is extra routine for ROME 1.0. From ROM 2.0, it should be removed. */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        fprintf(stderr, "%s: Failed to get patch version(s)\n", __FUNCTION__);
+        goto error;
+    }
+error:
+    return err;
+
+}
+
+int rome_disable_sleep(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, NVM_ACCESS_CODE);
+    cmd_hdr->plen     = VSC_DISABLE_IBS_LEN;
+    cmd[4] = 0x01;
+    cmd[5] = 0x1B;
+    cmd[6] = 0x01;
+    cmd[7] = 0x00;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + VSC_DISABLE_IBS_LEN);
+    /* Send the HCI command packet to UART for transmission */
+    fprintf(stderr, "%s: HCI CMD: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]) ;
+    err = write(fd, cmd, size);
+    if (err != size) {
+        fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, err);
+        goto error;
+    }
+
+    /* Check for response from the Controller */
+    if ((err =read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE)) < 0) {
+            fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__);
+            goto error;
+    }
+
+    fprintf(stderr, "%s: Received HCI-Vendor Specific Event from SOC\n", __FUNCTION__);
+
+    /* Wait for command complete event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        fprintf(stderr, "%s: Failed to set patch info on Controller\n", __FUNCTION__);
+        goto error;
+    }
+        fprintf(stderr, "%s\n", __FUNCTION__);
+error:
+    return err;
+
+}
+
+int rome_set_baudrate_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_SET_BAUDRATE_CMD_OCF);
+    cmd_hdr->plen     = VSC_SET_BAUDRATE_REQ_LEN;
+    cmd[4]  = BAUDRATE_115200;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + VSC_SET_BAUDRATE_REQ_LEN);
+    /* Send the HCI command packet to UART for transmission */
+    fprintf(stderr, "%s: HCI CMD: 0x%x 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, cmd[0], cmd[1], cmd[2], cmd[3],cmd[4]) ;
+    err = write(fd, cmd, size);
+    if (err != size) {
+        fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, err);
+        goto error;
+    }
+
+    /* Check for response from the Controller */
+    if ((err =read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE)) < 0) {
+            fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__);
+            goto error;
+    }
+
+    fprintf(stderr, "%s: Received HCI-Vendor Specific Event from SOC\n", __FUNCTION__);
+
+    /* Wait for command complete event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        fprintf(stderr, "%s: Failed to set patch info on Controller\n", __FUNCTION__);
+        goto error;
+    }
+        fprintf(stderr, "%s\n", __FUNCTION__);
+error:
+    return err;
+
+}
+
+
+int rome_hci_reset_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;
+
+    fprintf(stderr, "%s: HCI RESET \n", __FUNCTION__);
+
+    memset(cmd, 0x0, HCI_MAX_CMD_SIZE);
+
+    cmd_hdr = (void *) (cmd + 1);
+    cmd[0]  = HCI_COMMAND_PKT;
+    cmd_hdr->opcode = HCI_RESET;
+    cmd_hdr->plen   = 0;
+
+    /* Total length of the packet to be sent to the Controller */
+    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE);
+
+    /* Send the HCI command packet to UART for transmission */
+    fprintf(stderr, "%s: HCI CMD: 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, cmd[0], cmd[1], cmd[2], cmd[3]);
+    err = write(fd, cmd, size);
+    if (err != size) {
+        fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, err);
+        goto error;
+    }
+
+    /* Wait for command complete event */
+    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
+    if ( err < 0) {
+        fprintf(stderr, "%s: Failed to set patch info on Controller\n", __FUNCTION__);
+        goto error;
+    }
+
+error:
+    return err;
+
+}
+
+
+int qca_soc_init(int fd, char *bdaddr)
+{
+    int err = -1;
+    int size;
+
+    fprintf(stderr, " %s \n", __FUNCTION__);
+    vnd_userial.fd = fd;
+    /* Get Rome version information */
+    if((err = rome_patch_ver_req(fd)) <0){
+        fprintf(stderr, "%s: Fail to get Rome Version (0x%x)\n", __FUNCTION__, err);
+        goto error;
+    }
+
+    fprintf(stderr, "%s: Rome Version (0x%08x)\n", __FUNCTION__, rome_ver);
+
+    switch (rome_ver){
+        case ROME_VER_1_0:
+            {
+                /* Set and Download the RAMPATCH */
+                fprintf(stderr, "%s: Setting Patch Header & Downloading Patches\n", __FUNCTION__);
+                err = rome_download_rampatch(fd);
+                if (err < 0) {
+                    fprintf(stderr, "%s: DOWNLOAD RAMPATCH failed!\n", __FUNCTION__);
+                    goto error;
+                }
+                fprintf(stderr, "%s: DOWNLOAD RAMPTACH complete\n", __FUNCTION__);
+
+                /* Attach the RAMPATCH */
+                fprintf(stderr, "%s: Attaching the patches\n", __FUNCTION__);
+                err = rome_attach_rampatch(fd);
+                if (err < 0) {
+                    fprintf(stderr, "%s: ATTACH RAMPATCH failed!\n", __FUNCTION__);
+                    goto error;
+                }
+                fprintf(stderr, "%s: ATTACH RAMPTACH complete\n", __FUNCTION__);
+
+                /* Send Reset */
+                size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + EDL_PATCH_CMD_LEN);
+                err = rome_rampatch_reset(fd);
+                if ( err < 0 ) {
+                    fprintf(stderr, "Failed to RESET after RAMPATCH upgrade!\n");
+                    goto error;
+                }
+
+                /* NVM download */
+                fprintf(stderr, "%s: Downloading NVM\n", __FUNCTION__);
+                err = rome_1_0_nvm_tag_dnld(fd);
+                if ( err <0 ) {
+                    fprintf(stderr, "Downloading NVM Failed !!\n");
+                    goto error;
+                }
+
+                /* Change baud rate 115.2 kbps to 3Mbps*/
+                err = rome_hci_reset_req(fd);
+                if ( err <0 ) {
+                    fprintf(stderr, "HCI Reset Failed !!\n");
+                    goto error;
+                }
+
+                fprintf(stderr, "HCI Reset is done\n");
+            }
+            break;
+        case ROME_VER_1_1:
+            rampatch_file_path = ROME_RAMPATCH_TLV_PATH;
+            nvm_file_path = ROME_NVM_TLV_PATH;
+            goto download;
+        case ROME_VER_1_3:
+            rampatch_file_path = ROME_RAMPATCH_TLV_1_0_3_PATH;
+            nvm_file_path = ROME_NVM_TLV_1_0_3_PATH;
+            goto download;
+        case ROME_VER_2_1:
+            rampatch_file_path = ROME_RAMPATCH_TLV_2_0_1_PATH;
+            nvm_file_path = ROME_NVM_TLV_2_0_1_PATH;
+            goto download;
+        case ROME_VER_3_0:
+        case TUFELLO_VER_1_0:
+            rampatch_file_path = ROME_RAMPATCH_TLV_3_0_0_PATH;
+            nvm_file_path = ROME_NVM_TLV_3_0_0_PATH;
+
+download:
+            /* Donwload TLV files (rampatch, NVM) */
+            err = rome_download_tlv_file(fd);
+            if (err < 0) {
+                fprintf(stderr, "%s: Download TLV file failed!\n", __FUNCTION__);
+                goto error;
+            }
+            fprintf(stderr, "%s: Download TLV file successfully \n", __FUNCTION__);
+
+            /* Change baud rate back to user requested */
+            fprintf(stderr, "Changing baud rate back from 3M --> 115K\n");
+            err = rome_set_baudrate_req(fd);
+            if (err < 0) {
+                fprintf(stderr, "%s: Baud rate change failed!\n", __FUNCTION__);
+                goto error;
+            }
+            fprintf(stderr, "%s: Baud rate changed successfully \n", __FUNCTION__);
+
+	    fprintf(stderr, "%s: Disabling In Band Sleep functionality\n", __FUNCTION__);
+	    err = rome_disable_sleep(fd);
+            if (err < 0) {
+                fprintf(stderr, "%s: Failed to disable IBS!\n", __FUNCTION__);
+                goto error;
+            }
+            fprintf(stderr, "%s: IBS disabled successfully \n", __FUNCTION__);
+
+            /* Perform HCI reset here*/
+            err = rome_hci_reset_req(fd);
+            if ( err <0 ) {
+                fprintf(stderr, "HCI Reset Failed !!!\n");
+                goto error;
+            }
+	    fprintf(stderr, "HCI Reset is done\n");
+
+            break;
+        case ROME_VER_UNKNOWN:
+        default:
+            fprintf(stderr, "%s: Detected unknown ROME version\n", __FUNCTION__);
+            err = -1;
+            break;
+    }
+
+error:
+    return err;
+}
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
new file mode 100644
index 000000000000..aa59965643ec
--- /dev/null
+++ b/tools/hciattach_rome.h
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef HW_ROME_H
+#define HW_ROME_H
+
+/******************************************************************************
+**  Constants & Macros
+******************************************************************************/
+#define HCI_MAX_CMD_SIZE        260
+#define HCI_MAX_EVENT_SIZE     260
+#define PRINT_BUF_SIZE              ((HCI_MAX_CMD_SIZE * 3) + 2)
+/* HCI Command/Event Opcode */
+#define HCI_RESET                       0x0C03
+#define EVT_CMD_COMPLETE       0x0E
+/* HCI Packet types */
+#define HCI_COMMAND_PKT     0x01
+#define HCI_ACLDATA_PKT      0x02
+#define HCI_SCODATA_PKT     0x03
+#define HCI_EVENT_PKT           0x04
+#define HCI_VENDOR_PKT        0xff
+#define cmd_opcode_pack(ogf, ocf) (unsigned short)((ocf & 0x03ff)|(ogf << 10))
+unsigned char vnd_local_bd_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+typedef enum {
+    USERIAL_OP_FLOW_ON,
+    USERIAL_OP_FLOW_OFF,
+    USERIAL_OP_NOP,
+} userial_vendor_ioctl_op_t;
+
+
+/* vendor serial control block */
+typedef struct
+{
+    int fd;                     /* fd to Bluetooth device */
+    struct termios termios;     /* serial terminal of BT port */
+    char port_name[256];
+} vnd_userial_cb_t;
+
+/**** baud rates ****/
+#define USERIAL_BAUD_300        0
+#define USERIAL_BAUD_600        1
+#define USERIAL_BAUD_1200       2
+#define USERIAL_BAUD_2400       3
+#define USERIAL_BAUD_9600       4
+#define USERIAL_BAUD_19200      5
+#define USERIAL_BAUD_57600      6
+#define USERIAL_BAUD_115200     7
+#define USERIAL_BAUD_230400     8
+#define USERIAL_BAUD_460800     9
+#define USERIAL_BAUD_921600     10
+#define USERIAL_BAUD_1M         11
+#define USERIAL_BAUD_1_5M       12
+#define USERIAL_BAUD_2M         13
+#define USERIAL_BAUD_3M         14
+#define USERIAL_BAUD_4M         15
+#define USERIAL_BAUD_AUTO       16
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#ifndef TRUE
+#define TRUE   (!FALSE)
+#endif
+
+#define HCI_CHG_BAUD_CMD_OCF        0x0C
+#define HCI_VENDOR_CMD_OGF             0x3F
+#define WRITE_BDADDR_CMD_LEN        14
+#define WRITE_BAUD_CMD_LEN             6
+#define MAX_CMD_LEN                    WRITE_BDADDR_CMD_LEN
+#define GET_VERSION_OCF            0x1E
+
+#define PS_HDR_LEN                         4
+#define HCI_VENDOR_CMD_OGF      0x3F
+#define HCI_PS_CMD_OCF                0x0B
+
+#define HCI_COMMAND_HDR_SIZE        3
+#define EVT_CMD_COMPLETE_SIZE       3
+#define EVT_CMD_STATUS                     0x0F
+#define EVT_CMD_STATUS_SIZE           4
+#define HCI_EVENT_HDR_SIZE              2
+#define HCI_EV_SUCCESS                      0x00
+/* HCI Socket options */
+#define HCI_DATA_DIR            1
+#define HCI_FILTER                  2
+#define HCI_TIME_STAMP        3
+
+#define P_ID_OFFSET                                     (0)
+#define HCI_CMD_IND                                   (1)
+#define EVENTCODE_OFFSET                      (1)
+#define EVT_PLEN                                             (2)
+#define PLEN                                                       (3)
+#define CMD_RSP_OFFSET                             (3)
+#define RSP_TYPE_OFFSET                            (4)
+#define BAUDRATE_RSP_STATUS_OFFSET    (4)
+#define CMD_STATUS_OFFSET                      (5)
+#define P_ROME_VER_OFFSET                       (4)
+#define P_BUILD_VER_OFFSET                      (6)
+#define P_BASE_ADDR_OFFSET                     (8)
+#define P_ENTRY_ADDR_OFFSET                   (12)
+#define P_LEN_OFFSET                                   (16)
+#define P_CRC_OFFSET                                  (20)
+#define P_CONTROL_OFFSET                          (24)
+#define PATCH_HDR_LEN                               (28)
+#define MAX_DATA_PER_SEGMENT                (239)
+#define VSEVENT_CODE                                 (0xFF)
+#define HC_VS_MAX_CMD_EVENT                 (0xFF)
+#define PATCH_PROD_ID_OFFSET                (5)
+#define PATCH_PATCH_VER_OFFSET            (9)
+#define PATCH_ROM_BUILD_VER_OFFSET       (11)
+#define PATCH_SOC_VER_OFFSET             (13)
+#define MAX_SIZE_PER_TLV_SEGMENT        (243)
+
+/* VS Opcode */
+#define HCI_PATCH_CMD_OCF                       (0)
+#define EDL_SET_BAUDRATE_CMD_OCF        (0x48)
+
+/* VS Commands */
+#define VSC_SET_BAUDRATE_REQ_LEN        (1)
+#define EDL_PATCH_CMD_LEN	                       (1)
+#define EDL_PATCH_CMD_REQ_LEN               (1)
+#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 VSC_DISABLE_IBS_LEN                 (0x04)
+
+/* VS Event */
+#define EDL_CMD_REQ_RES_EVT                 (0x00)
+#define EDL_CMD_EXE_STATUS_EVT           (0x00)
+#define EDL_SET_BAUDRATE_RSP_EVT       (0x92)
+#define EDL_PATCH_VER_RES_EVT             (0x19)
+#define EDL_TVL_DNLD_RES_EVT                (0x04)
+#define EDL_APP_VER_RES_EVT                  (0x02)
+
+
+/* Status Codes of HCI CMD execution*/
+#define HCI_CMD_SUCCESS                     (0x0)
+#define PATCH_LEN_ERROR                       (0x1)
+#define PATCH_VER_ERROR                       (0x2)
+#define PATCH_CRC_ERROR                     (0x3)
+#define PATCH_NOT_FOUND                      (0x4)
+#define TLV_TYPE_ERROR                         (0x10)
+#define NVM_ACCESS_CODE                     (0x0B)
+#define BAUDRATE_CHANGE_SUCCESS   (1)
+
+/* TLV_TYPE */
+#define TLV_TYPE_PATCH                  (1)
+#define TLV_TYPE_NVM                      (2)
+
+/* NVM */
+#define MAX_TAG_CMD                 30
+#define TAG_END                           0xFF
+#define NVM_ACCESS_SET            0x01
+#define TAG_NUM_OFFSET             5
+#define TAG_NUM_2                       2
+#define TAG_BDADDR_OFFSET     7
+
+/* NVM Tags specifically used for ROME 1.0 */
+#define ROME_1_0_100022_1       0x101000221
+#define ROME_1_0_100019           0x101000190
+#define ROME_1_0_6002               0x100600200
+
+/* Default NVM Version setting for ROME 1.0 */
+#define NVM_VERSION                  ROME_1_0_100022_1
+
+
+#define LSH(val, n)     ((unsigned int)(val) << (n))
+#define EXTRACT_BYTE(val, pos)      (char) (((val) >> (8 * (pos))) & 0xFF)
+#define CALC_SEG_SIZE(len, max)   ((plen) % (max))?((plen/max)+1) : ((plen) / (max))
+
+#define ROME_FW_PATH        "/lib/firmware/rampatch.img"
+#define ROME_RAMPATCH_TLV_PATH      "/lib/firmware/rampatch_tlv.img"
+#define ROME_NVM_TLV_PATH         "/lib/firmware/nvm_tlv.bin"
+#define ROME_RAMPATCH_TLV_1_0_3_PATH    "/lib/firmware/rampatch_tlv_1.3.tlv"
+#define ROME_NVM_TLV_1_0_3_PATH         "/lib/firmware/nvm_tlv_1.3.bin"
+#define ROME_RAMPATCH_TLV_2_0_1_PATH    "/lib/firmware/rampatch_tlv_2.1.tlv"
+#define ROME_NVM_TLV_2_0_1_PATH         "/lib/firmware/nvm_tlv_2.1.bin"
+#define ROME_RAMPATCH_TLV_3_0_0_PATH    "/lib/firmware/qca/rampatch_tlv_3.0.tlv"
+#define ROME_NVM_TLV_3_0_0_PATH         "/lib/firmware/qca/nvm_tlv_3.0.bin"
+
+
+/******************************************************************************
+**  Local type definitions
+******************************************************************************/
+
+typedef struct {
+    unsigned char     ncmd;
+    unsigned short    opcode;
+} __attribute__ ((packed)) evt_cmd_complete;
+
+typedef struct {
+    unsigned char     status;
+    unsigned char     ncmd;
+    unsigned short    opcode;
+} __attribute__ ((packed)) evt_cmd_status;
+
+typedef struct {
+    unsigned short    opcode;
+    unsigned char     plen;
+} __attribute__ ((packed))  hci_command_hdr;
+
+typedef struct {
+    unsigned char     evt;
+    unsigned char     plen;
+} __attribute__ ((packed))  hci_event_hdr;
+typedef struct {
+    unsigned short rom_version;
+    unsigned short build_version;
+} __attribute__ ((packed)) patch_version;
+
+typedef struct {
+    unsigned int patch_id;
+    patch_version patch_ver;
+    unsigned int patch_base_addr;
+    unsigned int patch_entry_addr;
+    unsigned short patch_length;
+    int patch_crc;
+    unsigned short patch_ctrl;
+} __attribute__ ((packed)) patch_info;
+
+typedef struct {
+    unsigned char sign_ver;
+    unsigned char sign_algorithm;
+    unsigned short reserved1;
+    unsigned short prod_id;
+    unsigned short build_ver;
+    unsigned short patch_ver;
+    unsigned short reserved2;
+    unsigned int patch_entry_addr;
+} __attribute__ ((packed)) tlv_patch_hdr;
+
+typedef struct {
+    unsigned short tag_id;
+    unsigned short tag_len;
+    unsigned int tag_ptr;
+    unsigned int tag_ex_flag;
+} __attribute__ ((packed)) tlv_nvm_hdr;
+
+typedef struct {
+    unsigned char tlv_type;
+    unsigned char tlv_length1;
+    unsigned char tlv_length2;
+    unsigned char tlv_length3;
+    unsigned int  tlv_data_len;
+    unsigned int  tlv_patch_data_len;
+
+    union{
+        tlv_patch_hdr patch;
+        tlv_nvm_hdr nvm;
+    }tlv;
+} __attribute__ ((packed)) tlv_patch_info;
+
+enum{
+    BAUDRATE_115200     = 0x00,
+    BAUDRATE_57600       = 0x01,
+    BAUDRATE_38400       = 0x02,
+    BAUDRATE_19200       = 0x03,
+    BAUDRATE_9600         = 0x04,
+    BAUDRATE_230400     = 0x05,
+    BAUDRATE_250000     = 0x06,
+    BAUDRATE_460800     = 0x07,
+    BAUDRATE_500000     = 0x08,
+    BAUDRATE_720000     = 0x09,
+    BAUDRATE_921600     = 0x0A,
+    BAUDRATE_1000000   = 0x0B,
+    BAUDRATE_1250000   = 0x0C,
+    BAUDRATE_2000000   = 0x0D,
+    BAUDRATE_3000000   = 0x0E,
+    BAUDRATE_4000000   = 0x0F,
+    BAUDRATE_1600000   = 0x10,
+    BAUDRATE_3200000   = 0x11,
+    BAUDRATE_3500000   = 0x12,
+    BAUDRATE_AUTO        = 0xFE,
+    BAUDRATE_Reserved  = 0xFF
+};
+
+enum{
+    ROME_PATCH_VER_0100 = 0x0100,
+    ROME_PATCH_VER_0101 = 0x0101,
+    ROME_PATCH_VER_0200 = 0x0200,
+    ROME_PATCH_VER_0300 = 0x0300
+ };
+
+enum{
+    ROME_SOC_ID_00 = 0x00000000,
+    ROME_SOC_ID_11 = 0x00000011,
+    ROME_SOC_ID_13 = 0x00000013,
+    ROME_SOC_ID_22 = 0x00000022,
+};
+
+enum{
+    ROME_VER_UNKNOWN = 0,
+    ROME_VER_1_0 = ((ROME_PATCH_VER_0100 << 16 ) | ROME_SOC_ID_00 ),
+    ROME_VER_1_1 = ((ROME_PATCH_VER_0101 << 16 ) | ROME_SOC_ID_00 ),
+    ROME_VER_1_3 = ((ROME_PATCH_VER_0200 << 16 ) | ROME_SOC_ID_00 ),
+    ROME_VER_2_1 = ((ROME_PATCH_VER_0200 << 16 ) | ROME_SOC_ID_11 ),
+    ROME_VER_3_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_22 ),
+    TUFELLO_VER_1_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_13 )
+};
+#endif /* HW_ROME_H */

From 333676e63694e137558e7a685d2fa1a50c499436 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Thu, 11 Sep 2014 19:20:02 +0530
Subject: [PATCH 02/19] bluetooth: Enable bluetooth low power mode
 functionality

During periods of inactivity the bluetooth controller and the
application processor will indicate each other to enter into
low power mode and signal each other when they have data to be
exchanged, thereby saving considerable amount of power.

Change-Id: I9e0d579ac8a9d61a2ebde78b031f4101cb6bc443
Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
---
 tools/hciattach.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/hciattach.c b/tools/hciattach.c
index 73811d4c4c2a..e3a915061440 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
@@ -1102,7 +1102,7 @@ struct uart_t uart[] = {
 			FLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm  },
 
 	/* QCA ROME */
-        { "qca",    0x0000, 0x0000, HCI_UART_H4, 115200, 115200,
+        { "qca",    0x0000, 0x0000, HCI_UART_IBS, 115200, 115200,
                         FLOW_CTL, DISABLE_PM, NULL, qca, NULL },
 
 	/* QUALCOMM BTS */

From 0518592a10bff2ac0b99e4081bd01154f2eeacb6 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Thu, 11 Sep 2014 18:57:45 +0530
Subject: [PATCH 03/19] bluetooth: Fix bug in firmware parsing mechanism

Reorganize the RAMPATCH members to be present as part of the
RAMPATCH header structre instead of the main firmware structure

Change-Id: If523e1bb20edcd52b7c6f623c07af492e6305bd0
Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
---
 tools/hciattach_rome.c | 4 ++--
 tools/hciattach_rome.h | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index f31be43c09e4..122a0f4b89bc 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -851,8 +851,8 @@ int rome_get_tlv_file(char *file_path)
         fprintf(stderr, "Length\t\t\t : %d bytes\n", (ptlv_header->tlv_length1) |
                                                     (ptlv_header->tlv_length2 << 8) |
                                                     (ptlv_header->tlv_length3 << 16));
-        fprintf(stderr, "Total Length\t\t\t : %d bytes\n", ptlv_header->tlv_data_len);
-        fprintf(stderr, "Patch Data Length\t\t\t : %d bytes\n",ptlv_header->tlv_patch_data_len);
+        fprintf(stderr, "Total Length\t\t\t : %d bytes\n", ptlv_header->tlv.patch.tlv_data_len);
+        fprintf(stderr, "Patch Data Length\t\t\t : %d bytes\n",ptlv_header->tlv.patch.tlv_patch_data_len);
         fprintf(stderr, "Signing Format Version\t : 0x%x\n", ptlv_header->tlv.patch.sign_ver);
         fprintf(stderr, "Signature Algorithm\t\t : 0x%x\n", ptlv_header->tlv.patch.sign_algorithm);
         fprintf(stderr, "Reserved\t\t\t : 0x%x\n", ptlv_header->tlv.patch.reserved1);
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index aa59965643ec..07127f30a70a 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -236,6 +236,8 @@ typedef struct {
 } __attribute__ ((packed)) patch_info;
 
 typedef struct {
+    unsigned int  tlv_data_len;
+    unsigned int  tlv_patch_data_len;
     unsigned char sign_ver;
     unsigned char sign_algorithm;
     unsigned short reserved1;
@@ -258,8 +260,6 @@ typedef struct {
     unsigned char tlv_length1;
     unsigned char tlv_length2;
     unsigned char tlv_length3;
-    unsigned int  tlv_data_len;
-    unsigned int  tlv_patch_data_len;
 
     union{
         tlv_patch_hdr patch;

From 78f1ab9c20956f4e6f009d7bc2b94fe1d4474a08 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Mon, 8 Sep 2014 15:11:02 +0530
Subject: [PATCH 04/19] bluetooth: Configure BD Address

Read the BD Address programmed by user from persist location.
If there is no user programmed BD address then use the default
BD address present in the firmware file.

Change-Id: Id702d1476bae765dfd23f88542bfd5a8a1f26056
Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
---
 tools/hciattach_rome.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++---
 tools/hciattach_rome.h |  7 +++++++
 2 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 122a0f4b89bc..947e1abb96c4 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -809,6 +809,7 @@ int rome_get_tlv_file(char *file_path)
     tlv_nvm_hdr *nvm_ptr;
     unsigned char data_buf[PRINT_BUF_SIZE]={0,};
     unsigned char *nvm_byte_ptr;
+    unsigned char bdaddr[6];
 
     fprintf(stderr, "File Open (%s)\n", file_path);
     pFile = fopen ( file_path , "r" );
@@ -886,9 +887,10 @@ int rome_get_tlv_file(char *file_path)
             nvm_byte_ptr+=sizeof(tlv_nvm_hdr);
 
             /* Write BD Address */
-            if(nvm_ptr->tag_id == TAG_NUM_2){
-                memcpy(nvm_byte_ptr, vnd_local_bd_addr, 6);
-                fprintf(stderr, "BD Address: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x\n",
+            if(nvm_ptr->tag_id == TAG_NUM_2 && read_bd_address(&bdaddr) == 0) {
+                memcpy(nvm_byte_ptr, bdaddr, 6);
+                fprintf(stderr, "Overriding default BD ADDR with user"
+                  " programmed BD Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
                     *nvm_byte_ptr, *(nvm_byte_ptr+1), *(nvm_byte_ptr+2),
                     *(nvm_byte_ptr+3), *(nvm_byte_ptr+4), *(nvm_byte_ptr+5));
             }
@@ -1451,6 +1453,54 @@ error:
 
 }
 
+int read_bd_address(unsigned char *bdaddr)
+{
+  int fd = -1;
+  int readPtr = 0;
+  unsigned char data[BD_ADDR_LEN];
+
+  /* Open the persist file for reading device address*/
+  fd = open("/etc/bluetooth/.bt_nv.bin", O_RDONLY);
+  if(fd < 0)
+  {
+    fprintf(stderr, "%s: Open failed: Programming default BD ADDR\n", __func__);
+    return -1;
+  }
+
+  /* Read the NVM Header : fp will be advanced by readPtr number of bytes */
+  readPtr = read(fd, data, PERSIST_HEADER_LEN);
+  if (readPtr > 0)
+    fprintf(stderr, "%s: Persist header data: %02x \t %02x \t %02x\n", __func__,
+      data[NVITEM], data[RDWR_PROT], data[NVITEM_SIZE]);
+  else {
+    fprintf(stderr, "%s: Read from persist memory failed : Programming default"
+      " BD ADDR\n");
+    close(fd);
+    return -1;
+  }
+
+  /* Check for BD ADDR length before programming */
+  if(data[NVITEM_SIZE] != BD_ADDR_LEN) {
+    fprintf(stderr, "Invalid BD ADDR: Programming default BD ADDR!\n");
+    close(fd);
+    return -1;
+  }
+
+  /* Read the BD ADDR info */
+  readPtr = read(fd, data, BD_ADDR_LEN);
+  if (readPtr > 0)
+    fprintf(stderr, "BD-ADDR: ==> %02x:%02x:%02x:%02x:%02x:%02x\n", data[0],
+      data[1], data[2], data[3], data[4], data[5]);
+  else {
+    fprintf(stderr, "%s: Read from persist memory failed : Programming default"
+      " BD ADDR\n");
+    close(fd);
+    return -1;
+  }
+  memcpy(bdaddr, data, BD_ADDR_LEN);
+  close(fd);
+  return 0;
+}
 
 int qca_soc_init(int fd, char *bdaddr)
 {
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index 07127f30a70a..a4abe9f73080 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -34,6 +34,13 @@
 #define HCI_EVENT_PKT           0x04
 #define HCI_VENDOR_PKT        0xff
 #define cmd_opcode_pack(ogf, ocf) (unsigned short)((ocf & 0x03ff)|(ogf << 10))
+
+#define NVITEM              0
+#define RDWR_PROT           1
+#define NVITEM_SIZE         2
+#define PERSIST_HEADER_LEN  3
+#define BD_ADDR_LEN         6
+
 unsigned char vnd_local_bd_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 typedef enum {
     USERIAL_OP_FLOW_ON,

From 7f148243e9d36427734de874f291911e1f3d60d0 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Mon, 8 Sep 2014 14:33:24 +0530
Subject: [PATCH 05/19] bluetooth: Remove unused functions in the firmware
 download process

rome_disable_sleep() function is not used anywhere in the code and
hence remove it.

Change-Id: Iec1f9b1478850af3023ff297493693283a5338d7
Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
---
 tools/hciattach_rome.c | 48 ------------------------------------------------
 1 file changed, 48 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 947e1abb96c4..4fcbdf2ab82a 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -1317,54 +1317,6 @@ error:
 
 }
 
-int rome_disable_sleep(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, NVM_ACCESS_CODE);
-    cmd_hdr->plen     = VSC_DISABLE_IBS_LEN;
-    cmd[4] = 0x01;
-    cmd[5] = 0x1B;
-    cmd[6] = 0x01;
-    cmd[7] = 0x00;
-
-    /* Total length of the packet to be sent to the Controller */
-    size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + VSC_DISABLE_IBS_LEN);
-    /* Send the HCI command packet to UART for transmission */
-    fprintf(stderr, "%s: HCI CMD: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7]) ;
-    err = write(fd, cmd, size);
-    if (err != size) {
-        fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, err);
-        goto error;
-    }
-
-    /* Check for response from the Controller */
-    if ((err =read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE)) < 0) {
-            fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__);
-            goto error;
-    }
-
-    fprintf(stderr, "%s: Received HCI-Vendor Specific Event from SOC\n", __FUNCTION__);
-
-    /* Wait for command complete event */
-    err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
-    if ( err < 0) {
-        fprintf(stderr, "%s: Failed to set patch info on Controller\n", __FUNCTION__);
-        goto error;
-    }
-        fprintf(stderr, "%s\n", __FUNCTION__);
-error:
-    return err;
-
-}
 
 int rome_set_baudrate_req(int fd)
 {

From 175fe3690522afc91f38933f821e4b00bd1a12c8 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Mon, 8 Sep 2014 14:31:18 +0530
Subject: [PATCH 06/19] bluetooth: Enable 3Mbps baud rate support

Allow APPS PROC and BT Controller to operate at 3Mbps baud rate
for faster exchange of commands, events and data between the two

Change-Id: I55651633027ea60a762b11abea84fe1abd6574a9
Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
---
 tools/hciattach_rome.c | 63 ++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 48 insertions(+), 15 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 4fcbdf2ab82a..d0e2935b9997 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -166,6 +166,7 @@ int userial_vendor_ioctl(int fd, userial_vendor_ioctl_op_t op, int *p_data)
     }
     cfmakeraw(&ti);
     ti.c_cflag |= CLOCAL;
+    ti.c_cflag |= CREAD;
 
     switch(op)
     {
@@ -332,6 +333,8 @@ int read_vs_hci_event(int fd, unsigned char* buf, int size)
 {
     int remain, r;
     int count = 0;
+    fd_set infids;
+    struct timeval timeout;
 
     if (size <= 0) {
         fprintf(stderr, "Invalid size arguement!\n");
@@ -340,6 +343,16 @@ int read_vs_hci_event(int fd, unsigned char* buf, int size)
 
     fprintf(stderr, "%s: Wait for HCI-Vendor Specfic Event from SOC\n", __FUNCTION__);
 
+    FD_ZERO (&infids);
+    FD_SET (fd, &infids);
+    timeout.tv_sec = 3;
+    timeout.tv_usec = 0;  /* half second is a long time at 115.2 Kbps */
+
+    if (select (fd + 1, &infids, NULL, NULL, &timeout) < 1)
+	    fprintf(stderr, "%s: Timing out on select for 3 secs.\n", __FUNCTION__);
+    else
+	    fprintf(stderr, "%s: Data available in TTY Serial buffer\n", __FUNCTION__);
+
     /* The first byte identifies the packet type. For HCI event packets, it
      * should be 0x04, so we read until we get to the 0x04. */
     /* It will keep reading until find 0x04 byte */
@@ -1332,10 +1345,16 @@ int rome_set_baudrate_req(int fd)
     cmd[0]  = HCI_COMMAND_PKT;
     cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, EDL_SET_BAUDRATE_CMD_OCF);
     cmd_hdr->plen     = VSC_SET_BAUDRATE_REQ_LEN;
-    cmd[4]  = BAUDRATE_115200;
+    cmd[4]  = BAUDRATE_3000000;
 
     /* Total length of the packet to be sent to the Controller */
     size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + VSC_SET_BAUDRATE_REQ_LEN);
+    /* Flow off during baudrate change */
+    if ((err = userial_vendor_ioctl(fd, USERIAL_OP_FLOW_OFF , &flags)) < 0)
+    {
+      fprintf(stderr, "%s: HW Flow-off error: 0x%x\n", __FUNCTION__, err);
+      goto error;
+    }
     /* Send the HCI command packet to UART for transmission */
     fprintf(stderr, "%s: HCI CMD: 0x%x 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, cmd[0], cmd[1], cmd[2], cmd[3],cmd[4]) ;
     err = write(fd, cmd, size);
@@ -1343,7 +1362,15 @@ int rome_set_baudrate_req(int fd)
         fprintf(stderr, "%s: Send failed with ret value: %d\n", __FUNCTION__, err);
         goto error;
     }
+    /* Change Local UART baudrate to high speed UART */
+    userial_vendor_set_baud(USERIAL_BAUD_3M);
 
+    /* Flow on after changing local uart baudrate */
+    if ((err = userial_vendor_ioctl(fd, USERIAL_OP_FLOW_ON , &flags)) < 0)
+    {
+        fprintf(stderr, "%s: HW Flow-on error: 0x%x \n", __FUNCTION__, err);
+        return err;
+    }
     /* Check for response from the Controller */
     if ((err =read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE)) < 0) {
             fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__);
@@ -1385,6 +1412,12 @@ int rome_hci_reset_req(int fd)
     /* Total length of the packet to be sent to the Controller */
     size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE);
 
+    /* Flow off during baudrate change */
+    if ((err = userial_vendor_ioctl(fd, USERIAL_OP_FLOW_OFF , &flags)) < 0)
+    {
+      fprintf(stderr, "%s: HW Flow-off error: 0x%x\n", __FUNCTION__, err);
+      goto error;
+    }
     /* Send the HCI command packet to UART for transmission */
     fprintf(stderr, "%s: HCI CMD: 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, cmd[0], cmd[1], cmd[2], cmd[3]);
     err = write(fd, cmd, size);
@@ -1393,6 +1426,15 @@ int rome_hci_reset_req(int fd)
         goto error;
     }
 
+    /* Change Local UART baudrate to high speed UART */
+     userial_vendor_set_baud(USERIAL_BAUD_3M);
+
+    /* Flow on after changing local uart baudrate */
+    if ((err = userial_vendor_ioctl(fd, USERIAL_OP_FLOW_ON , &flags)) < 0)
+    {
+        fprintf(stderr, "%s: HW Flow-on error: 0x%x \n", __FUNCTION__, err);
+        return err;
+    }
     /* Wait for command complete event */
     err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
     if ( err < 0) {
@@ -1534,16 +1576,7 @@ int qca_soc_init(int fd, char *bdaddr)
             nvm_file_path = ROME_NVM_TLV_3_0_0_PATH;
 
 download:
-            /* Donwload TLV files (rampatch, NVM) */
-            err = rome_download_tlv_file(fd);
-            if (err < 0) {
-                fprintf(stderr, "%s: Download TLV file failed!\n", __FUNCTION__);
-                goto error;
-            }
-            fprintf(stderr, "%s: Download TLV file successfully \n", __FUNCTION__);
-
-            /* Change baud rate back to user requested */
-            fprintf(stderr, "Changing baud rate back from 3M --> 115K\n");
+            /* Change baud rate 115.2 kbps to 3Mbps*/
             err = rome_set_baudrate_req(fd);
             if (err < 0) {
                 fprintf(stderr, "%s: Baud rate change failed!\n", __FUNCTION__);
@@ -1551,13 +1584,13 @@ download:
             }
             fprintf(stderr, "%s: Baud rate changed successfully \n", __FUNCTION__);
 
-	    fprintf(stderr, "%s: Disabling In Band Sleep functionality\n", __FUNCTION__);
-	    err = rome_disable_sleep(fd);
+            /* Donwload TLV files (rampatch, NVM) */
+            err = rome_download_tlv_file(fd);
             if (err < 0) {
-                fprintf(stderr, "%s: Failed to disable IBS!\n", __FUNCTION__);
+                fprintf(stderr, "%s: Download TLV file failed!\n", __FUNCTION__);
                 goto error;
             }
-            fprintf(stderr, "%s: IBS disabled successfully \n", __FUNCTION__);
+            fprintf(stderr, "%s: Download TLV file successfully \n", __FUNCTION__);
 
             /* Perform HCI reset here*/
             err = rome_hci_reset_req(fd);

From 1911a9d5799d110a7d010e154b44e43c65e838ff Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Tue, 30 Sep 2014 12:13:00 +0530
Subject: [PATCH 07/19] bluetooth: Check TTY buffer for data availability
 before reading

When operating at higher baud rates check the TTY buffer for
availability of data before proceeding to read. Call select() with
a 3 sec timeout value to check for the availablitiy of data.
select() will return once data is available in the TTY buffers
and will allow read() to fetch the data. If data is not available
in the TTY buffer until the timeout valueexpires, do not proceed
to read the data from the TTY buffers as there is none.

Occasionally corrupt data is received on UART lines while we wait
for vendor specific event from Controller. Expected vendor specific
events are received after the corrupt data. But we do not retry
and exit and this causes firmware download failures. So, retry once
if we did not get HCI event.

Change-Id: I3b672a7762403690f8b934ca216492f16285e8da
Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
---
 tools/hciattach.c      | 20 ++++++++++++-
 tools/hciattach_rome.c | 77 +++++++++++++++++++++++++++++++++++++++-----------
 tools/hciattach_rome.h |  3 ++
 3 files changed, 83 insertions(+), 17 deletions(-)

diff --git a/tools/hciattach.c b/tools/hciattach.c
index e3a915061440..c3cf10843303 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
@@ -109,16 +109,34 @@ int read_hci_event(int fd, unsigned char* buf, int size)
 {
 	int remain, r;
 	int count = 0;
+	fd_set infids;
+	struct timeval timeout;
 
 	if (size <= 0)
 		return -1;
 
+	FD_ZERO (&infids);
+	FD_SET (fd, &infids);
+	timeout.tv_sec = 3;
+	timeout.tv_usec = 0;
+
+	/* Check whether data is available in TTY buffer before calling read() */
+	if (select (fd + 1, &infids, NULL, NULL, &timeout) < 1) {
+		fprintf(stderr, "%s: Timing out on select for 3 secs.\n", __FUNCTION__);
+		return -1;
+	}
+	else
+		fprintf(stderr, "%s: Data(HCI-CMD-COMP-EVENT) available in TTY Serial buffer\n", __FUNCTION__);
+
 	/* The first byte identifies the packet type. For HCI event packets, it
 	 * should be 0x04, so we read until we get to the 0x04. */
 	while (1) {
 		r = read(fd, buf, 1);
-		if (r <= 0)
+		if (r <= 0) {
+	                fprintf(stderr, "%s: read() failed with return value: %d\n",
+                            __FUNCTION__, r);
 			return -1;
+                }
 		if (buf[0] == 0x04)
 			break;
 	}
diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index d0e2935b9997..d2687b1ef01a 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -326,42 +326,87 @@ failed:
 }
 
 
+int wait_for_data(int fd, int maxTimeOut)
+{
+    fd_set infids;
+    struct timeval timeout;
+
+    if (maxTimeOut <= 0) {
+        fprintf(stderr, "%s: Invalid timeout value specified", __func__);
+        return -EINVAL;
+    }
+
+    FD_ZERO (&infids);
+    FD_SET (fd, &infids);
+    timeout.tv_sec = maxTimeOut;
+    timeout.tv_usec = 0;
+
+    /* Check whether data is available in TTY buffer before calling read() */
+    if (select (fd + 1, &infids, NULL, NULL, &timeout) < 1) {
+        fprintf(stderr, "%s: Timing out on select for %d secs.\n", __FUNCTION__, maxTimeOut);
+        return -1;
+    }
+    else
+        fprintf(stderr, "%s: HCI-VS-EVENT available in TTY Serial buffer\n",
+            __FUNCTION__);
+
+    return 1;
+}
+
 /*
  * Read an VS HCI event from the given file descriptor.
  */
 int read_vs_hci_event(int fd, unsigned char* buf, int size)
 {
-    int remain, r;
+    int remain, r, retry = 0;
     int count = 0;
-    fd_set infids;
-    struct timeval timeout;
 
     if (size <= 0) {
         fprintf(stderr, "Invalid size arguement!\n");
         return -1;
     }
 
-    fprintf(stderr, "%s: Wait for HCI-Vendor Specfic Event from SOC\n", __FUNCTION__);
-
-    FD_ZERO (&infids);
-    FD_SET (fd, &infids);
-    timeout.tv_sec = 3;
-    timeout.tv_usec = 0;  /* half second is a long time at 115.2 Kbps */
+    fprintf(stderr, "%s: Wait for HCI-Vendor Specfic Event from SOC\n",
+        __FUNCTION__);
 
-    if (select (fd + 1, &infids, NULL, NULL, &timeout) < 1)
-	    fprintf(stderr, "%s: Timing out on select for 3 secs.\n", __FUNCTION__);
-    else
-	    fprintf(stderr, "%s: Data available in TTY Serial buffer\n", __FUNCTION__);
+    /* Check whether data is available in TTY buffer before calling read() */
+    if (wait_for_data(fd, SELECT_TIMEOUT) < 1)
+        return -1;
 
     /* The first byte identifies the packet type. For HCI event packets, it
      * should be 0x04, so we read until we get to the 0x04. */
     /* It will keep reading until find 0x04 byte */
     while (1) {
+            /* Read UART Buffer for HCI-DATA */
             r = read(fd, buf, 1);
-            if (r <= 0)
-                    return -1;
-            if (buf[0] == 0x04)
+            if (r <= 0) {
+                fprintf(stderr, "%s: read() failed. error: %d\n",
+                    __FUNCTION__, r);
+                return -1;
+            }
+
+            /* Check if received data is HCI-DATA or not.
+             * If not HCI-DATA, then retry reading the UART Buffer once.
+             * Sometimes there could be corruption on the UART lines and to
+             * avoid that retry once reading the UART Buffer for HCI-DATA.
+             */
+            if (buf[0] == 0x04) { /* Recvd. HCI DATA */
+                    retry = 0;
                     break;
+            }
+            else if (retry < MAX_RETRY_CNT){ /* Retry mechanism */
+                retry++;
+                fprintf(stderr, "%s: Not an HCI-VS-Event! buf[0]: %d",
+                    __FUNCTION__, buf[0]);
+                if (wait_for_data(fd, SELECT_TIMEOUT) < 1)
+                    return -1;
+                else /* Data available in UART Buffer: Continue to read */
+                    continue;
+            }
+            else { /* RETRY failed : Exiting with failure */
+                fprintf(stderr, "%s: RETRY failed!", __FUNCTION__);
+                return -1;
+            }
     }
     count++;
 
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index a4abe9f73080..3efb71995c45 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -179,6 +179,9 @@ typedef struct
 #define TAG_NUM_2                       2
 #define TAG_BDADDR_OFFSET     7
 
+#define MAX_RETRY_CNT  1
+#define SELECT_TIMEOUT 3
+
 /* NVM Tags specifically used for ROME 1.0 */
 #define ROME_1_0_100022_1       0x101000221
 #define ROME_1_0_100019           0x101000190

From 9d81b1dd643966ba6f2ffb3f7658a24cfcb37df4 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Wed, 20 Aug 2014 12:13:19 +0530
Subject: [PATCH 08/19] bluetooth : Add support for TUFEELO firmware download

Add TUFELLO chip version to allow firmware download.

Change-Id: Ie3760fa64e8345bf9a84b2f047fde0ac1003b393
---
 tools/hciattach_rome.c | 5 ++++-
 tools/hciattach_rome.h | 3 ++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index d2687b1ef01a..84dfc97b5140 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -1616,9 +1616,12 @@ int qca_soc_init(int fd, char *bdaddr)
             nvm_file_path = ROME_NVM_TLV_2_0_1_PATH;
             goto download;
         case ROME_VER_3_0:
-        case TUFELLO_VER_1_0:
             rampatch_file_path = ROME_RAMPATCH_TLV_3_0_0_PATH;
             nvm_file_path = ROME_NVM_TLV_3_0_0_PATH;
+            goto download;
+        case TUFELLO_VER_1_0:
+            rampatch_file_path = TF_RAMPATCH_TLV_1_0_0_PATH;
+            nvm_file_path = TF_NVM_TLV_1_0_0_PATH;
 
 download:
             /* Change baud rate 115.2 kbps to 3Mbps*/
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index 3efb71995c45..9d18c576fcae 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -204,7 +204,8 @@ typedef struct
 #define ROME_NVM_TLV_2_0_1_PATH         "/lib/firmware/nvm_tlv_2.1.bin"
 #define ROME_RAMPATCH_TLV_3_0_0_PATH    "/lib/firmware/qca/rampatch_tlv_3.0.tlv"
 #define ROME_NVM_TLV_3_0_0_PATH         "/lib/firmware/qca/nvm_tlv_3.0.bin"
-
+#define TF_RAMPATCH_TLV_1_0_0_PATH    "/lib/firmware/rampatch_tlv_tf_1.0.tlv"
+#define TF_NVM_TLV_1_0_0_PATH         "/lib/firmware/nvm_tlv_tf_1.0.bin"
 
 /******************************************************************************
 **  Local type definitions

From ac12a2a733ad6cc6eed8ccdd3462d1fe1969fc54 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Mon, 8 Dec 2014 14:52:16 +0530
Subject: [PATCH 09/19] bluetooth: Add support for ROME 3.2 SOC.

Add firmware download support for ROME 3.2 version. As part
of this, the Bluetooth on time is optimized based on event
handling while downloading rampatch files.From ROME 3.2 onwards,
the VS and command complete events will be sent depending the flag
indication present in the header. HOST can wait for VS and command
complete events only if specified in the header info. This greatly
reduces the time spent by HOST in waiting for 2 events from the
Controller before downloading each segment of the RAMPATCH file

Change-Id: I9c4227a7a529455f4d120b2c9d065f3ec6b439e9
---
 tools/hciattach_rome.c | 104 ++++++++++++++++++++++++++++++++++++++++++-------
 tools/hciattach_rome.h |  16 +++++++-
 2 files changed, 103 insertions(+), 17 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 84dfc97b5140..c6d528f118e1 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -62,9 +62,11 @@ unsigned char *pdata_buffer = NULL;
 patch_info rampatch_patch_info;
 int rome_ver = ROME_VER_UNKNOWN;
 unsigned char gTlv_type;
+unsigned char gtlv_dwndcfg;
 char *rampatch_file_path;
 char *nvm_file_path;
 vnd_userial_cb_t vnd_userial;
+unsigned char wait_vsc_evt = TRUE;
 /******************************************************************************
 **  Extern variables
 ******************************************************************************/
@@ -455,14 +457,16 @@ int hci_send_vs_cmd(int fd, unsigned char *cmd, unsigned char *rsp, int size)
         goto failed;
     }
 
-    /* Check for response from the Controller */
-    if (read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE) < 0) {
-        ret = -ETIMEDOUT;
-        fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__);
-        goto failed;
+    if (wait_vsc_evt) {
+        /* Check for response from the Controller */
+        if (read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE) < 0) {
+            ret = -ETIMEDOUT;
+            fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__);
+            goto failed;
+        }
+        fprintf(stderr, "%s: Received HCI-Vendor Specific Event from SOC\n", __FUNCTION__);
     }
 
-    fprintf(stderr, "%s: Received HCI-Vendor Specific Event from SOC\n", __FUNCTION__);
 failed:
     return ret;
 }
@@ -903,6 +907,7 @@ int rome_get_tlv_file(char *file_path)
 
     /* To handle different event between rampatch and NVM */
     gTlv_type = ptlv_header->tlv_type;
+    gtlv_dwndcfg = ptlv_header->tlv.patch.dwnd_cfg;
 
     if(ptlv_header->tlv_type == TLV_TYPE_PATCH){
         fprintf(stderr, "====================================================\n");
@@ -914,6 +919,7 @@ int rome_get_tlv_file(char *file_path)
         fprintf(stderr, "Patch Data Length\t\t\t : %d bytes\n",ptlv_header->tlv.patch.tlv_patch_data_len);
         fprintf(stderr, "Signing Format Version\t : 0x%x\n", ptlv_header->tlv.patch.sign_ver);
         fprintf(stderr, "Signature Algorithm\t\t : 0x%x\n", ptlv_header->tlv.patch.sign_algorithm);
+        fprintf(stderr, "Event Handling\t\t\t : 0x%x", ptlv_header->tlv.patch.dwnd_cfg);
         fprintf(stderr, "Reserved\t\t\t : 0x%x\n", ptlv_header->tlv.patch.reserved1);
         fprintf(stderr, "Product ID\t\t\t : 0x%04x\n", ptlv_header->tlv.patch.prod_id);
         fprintf(stderr, "Rom Build Version\t\t : 0x%04x\n", ptlv_header->tlv.patch.build_ver);
@@ -1023,19 +1029,83 @@ int rome_tlv_dnld_req(int fd, int tlv_size)
     fprintf(stderr, "%s: TLV size: %d, Total Seg num: %d, remain size: %d\n",
         __FUNCTION__,tlv_size, total_segment, remain_size);
 
-    for(i=0;i<total_segment ;i++){
-        /* In case of ROME 1.1, last rampatch segment command will not wait for
-            command complete event */
-        wait_cc_evt = ((rome_ver >= ROME_VER_1_1) && (gTlv_type == TLV_TYPE_PATCH )
-             && !remain_size && ((i+1) == total_segment))? FALSE: TRUE;
+    if (gTlv_type == TLV_TYPE_PATCH) {
+       /* Prior to Rome version 3.2(including inital few rampatch release of
+        * Rome 3.2), the event handling mechanism is ROME_SKIP_EVT_NONE. After
+        * few release of rampatch for Rome 3.2, the mechamism is changed to
+        * ROME_SKIP_EVT_VSE_CC. Rest of the mechanism is not used for now
+        */
+       switch(gtlv_dwndcfg)
+       {
+           case ROME_SKIP_EVT_NONE:
+              wait_vsc_evt = TRUE;
+              wait_cc_evt = TRUE;
+              fprintf(stderr, "%s: Event handling type: ROME_SKIP_EVT_NONE", __func__);
+              break;
+           case ROME_SKIP_EVT_VSE_CC:
+              wait_vsc_evt = FALSE;
+              wait_cc_evt = FALSE;
+              fprintf(stderr, "%s: Event handling type: ROME_SKIP_EVT_VSE_CC", __func__);
+              break;
+           /* Not handled for now */
+           case ROME_SKIP_EVT_VSE:
+           case ROME_SKIP_EVT_CC:
+           default:
+              fprintf(stderr, "%s: Unsupported Event handling: %d", __func__, gtlv_dwndcfg);
+              break;
+       }
+    } else {
+        wait_vsc_evt = TRUE;
+        wait_cc_evt = TRUE;
+    }
+
+    for(i = 0; i < total_segment; i++) {
+        if((i+1) == total_segment) {
+             if ((rome_ver >= ROME_VER_1_1) && (rome_ver < ROME_VER_3_2) &&
+                 (gTlv_type == TLV_TYPE_PATCH)) {
+               /* If the Rome version is from 1.1 to 3.1
+                * 1. No CCE for the last command segment but all other segment
+                * 2. All the command segments get VSE including the last one
+                */
+                wait_cc_evt = !remain_size ? FALSE: TRUE;
+             } else if ((rome_ver == ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+                /* If the Rome version is 3.2
+                 * 1. None of the command segments receive CCE
+                 * 2. No command segments receive VSE except the last one
+                 * 3. If gtlv_dwndcfg is ROME_SKIP_EVT_NONE then the logic is
+                 *    same as Rome 2.1, 2.2, 3.0
+                 */
+                 if (gtlv_dwndcfg == ROME_SKIP_EVT_NONE) {
+                    wait_cc_evt = !remain_size ? FALSE: TRUE;
+                 } else if (gtlv_dwndcfg == ROME_SKIP_EVT_VSE_CC) {
+                    wait_vsc_evt = !remain_size ? TRUE: FALSE;
+                 }
+             }
+        }
+
         if((err = rome_tlv_dnld_segment(fd, i, MAX_SIZE_PER_TLV_SEGMENT, wait_cc_evt )) < 0)
             goto error;
     }
 
-    /* In case remain data still remain, last rampatch segment command will not wait
-        for command complete event here */
-    wait_cc_evt = ((rome_ver >= ROME_VER_1_1) && (gTlv_type == TLV_TYPE_PATCH )
-         && remain_size )? FALSE:TRUE;
+    if ((rome_ver >= ROME_VER_1_1) && (rome_ver < ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+       /* If the Rome version is from 1.1 to 3.1
+        * 1. No CCE for the last command segment but all other segment
+        * 2. All the command segments get VSE including the last one
+        */
+        wait_cc_evt = remain_size ? FALSE: TRUE;
+    } else if ((rome_ver == ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+        /* If the Rome version is 3.2
+         * 1. None of the command segments receive CCE
+         * 2. No command segments receive VSE except the last one
+         * 3. If gtlv_dwndcfg is ROME_SKIP_EVT_NONE then the logic is
+         *    same as Rome 2.1, 2.2, 3.0
+         */
+        if (gtlv_dwndcfg == ROME_SKIP_EVT_NONE) {
+           wait_cc_evt = remain_size ? FALSE: TRUE;
+        } else if (gtlv_dwndcfg == ROME_SKIP_EVT_VSE_CC) {
+           wait_vsc_evt = remain_size ? TRUE: FALSE;
+        }
+    }
 
     if(remain_size) err =rome_tlv_dnld_segment(fd, i, remain_size, wait_cc_evt);
 
@@ -1619,6 +1689,10 @@ int qca_soc_init(int fd, char *bdaddr)
             rampatch_file_path = ROME_RAMPATCH_TLV_3_0_0_PATH;
             nvm_file_path = ROME_NVM_TLV_3_0_0_PATH;
             goto download;
+        case ROME_VER_3_2:
+            rampatch_file_path = ROME_RAMPATCH_TLV_3_0_2_PATH;
+            nvm_file_path = ROME_NVM_TLV_3_0_2_PATH;
+            goto download;
         case TUFELLO_VER_1_0:
             rampatch_file_path = TF_RAMPATCH_TLV_1_0_0_PATH;
             nvm_file_path = TF_NVM_TLV_1_0_0_PATH;
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index 9d18c576fcae..77e85e7e7b19 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -204,9 +204,17 @@ typedef struct
 #define ROME_NVM_TLV_2_0_1_PATH         "/lib/firmware/nvm_tlv_2.1.bin"
 #define ROME_RAMPATCH_TLV_3_0_0_PATH    "/lib/firmware/qca/rampatch_tlv_3.0.tlv"
 #define ROME_NVM_TLV_3_0_0_PATH         "/lib/firmware/qca/nvm_tlv_3.0.bin"
+#define ROME_RAMPATCH_TLV_3_0_2_PATH    "/lib/firmware/qca/rampatch_tlv_3.2.tlv"
+#define ROME_NVM_TLV_3_0_2_PATH         "/lib/firmware/qca/nvm_tlv_3.2.bin"
 #define TF_RAMPATCH_TLV_1_0_0_PATH    "/lib/firmware/rampatch_tlv_tf_1.0.tlv"
 #define TF_NVM_TLV_1_0_0_PATH         "/lib/firmware/nvm_tlv_tf_1.0.bin"
 
+/* This header value in rampatch file decides event handling mechanism in the HOST */
+#define ROME_SKIP_EVT_NONE     0x00
+#define ROME_SKIP_EVT_VSE      0x01
+#define ROME_SKIP_EVT_CC       0x02
+#define ROME_SKIP_EVT_VSE_CC   0x03
+
 /******************************************************************************
 **  Local type definitions
 ******************************************************************************/
@@ -251,7 +259,8 @@ typedef struct {
     unsigned int  tlv_patch_data_len;
     unsigned char sign_ver;
     unsigned char sign_algorithm;
-    unsigned short reserved1;
+    unsigned char dwnd_cfg;
+    unsigned char reserved1;
     unsigned short prod_id;
     unsigned short build_ver;
     unsigned short patch_ver;
@@ -306,7 +315,8 @@ enum{
     ROME_PATCH_VER_0100 = 0x0100,
     ROME_PATCH_VER_0101 = 0x0101,
     ROME_PATCH_VER_0200 = 0x0200,
-    ROME_PATCH_VER_0300 = 0x0300
+    ROME_PATCH_VER_0300 = 0x0300,
+    ROME_PATCH_VER_0302 = 0x0302
  };
 
 enum{
@@ -314,6 +324,7 @@ enum{
     ROME_SOC_ID_11 = 0x00000011,
     ROME_SOC_ID_13 = 0x00000013,
     ROME_SOC_ID_22 = 0x00000022,
+    ROME_SOC_ID_44 = 0x00000044
 };
 
 enum{
@@ -323,6 +334,7 @@ enum{
     ROME_VER_1_3 = ((ROME_PATCH_VER_0200 << 16 ) | ROME_SOC_ID_00 ),
     ROME_VER_2_1 = ((ROME_PATCH_VER_0200 << 16 ) | ROME_SOC_ID_11 ),
     ROME_VER_3_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_22 ),
+    ROME_VER_3_2 = ((ROME_PATCH_VER_0302 << 16 ) | ROME_SOC_ID_44 ),
     TUFELLO_VER_1_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_13 )
 };
 #endif /* HW_ROME_H */

From f7cc3b22522cfc66a7c4126630c6222f22be17f6 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Thu, 4 Dec 2014 17:23:58 +0530
Subject: [PATCH 10/19] bluetooth: Use correct TTY ioctl calls for flow control
 operations

BT firmware download application is using incorrect APIs for
performing flow off and flow on operations. As a result, the local
UART Controller is detecting breaks errors on the UART HW lines.

Appliaction should use TIOCMGET and TIOCMSET ioctl()'s for flow
control operations instead of the tcsetattr() call. Also, the
application should set the value of "number of bits per character"
value to 8 and not as 5.

Due to incorrect APIs used for flow control operation and wrong
value configured for CSIZE parameter, the local UART Controller
detected break errors on the UART HW lines. This caused the
firmware download operation to fail and resulted in BT ON failure.

Change-Id: Id0ac1276609eceb528163860cc87267aaa50fede
---
 tools/hciattach_rome.c | 67 +++++++++++++++++++++++++++++++++-----------------
 tools/hciattach_rome.h |  6 +++--
 2 files changed, 49 insertions(+), 24 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index c6d528f118e1..1e689273b851 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  *  Not a Contribution.
  *
  *  Copyright 2012 The Android Open Source Project
@@ -31,6 +31,7 @@
 
 #define LOG_TAG "bt_vendor"
 #include <stdio.h>
+#include <unistd.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -139,6 +140,16 @@ void userial_vendor_set_baud(unsigned char userial_baud)
     unsigned int tcio_baud;
     fprintf(stderr, "## userial_vendor_set_baud: %d\n", userial_baud);
 
+    if (tcgetattr(vnd_userial.fd, &vnd_userial.termios) < 0) {
+            perror("Can't get port settings");
+            return;
+    }
+    cfmakeraw(&vnd_userial.termios);
+    vnd_userial.termios.c_cflag |= CLOCAL;
+    vnd_userial.termios.c_cflag |= CREAD;
+    vnd_userial.termios.c_cflag |= CS8;
+    tcsetattr(vnd_userial.fd, TCSANOW, &vnd_userial.termios);
+
     userial_to_tcio_baud(userial_baud, &tcio_baud);
 
     cfsetospeed(&vnd_userial.termios, tcio_baud);
@@ -169,6 +180,7 @@ int userial_vendor_ioctl(int fd, userial_vendor_ioctl_op_t op, int *p_data)
     cfmakeraw(&ti);
     ti.c_cflag |= CLOCAL;
     ti.c_cflag |= CREAD;
+    ti.c_cflag |= CS8;
 
     switch(op)
     {
@@ -1445,6 +1457,29 @@ error:
 
 }
 
+static void flow_control(int fd, int opt)
+{
+    struct termios c_opt;
+
+    ioctl(fd, TIOCMGET, &c_opt);
+    c_opt.c_cc[VTIME] = 0; /* inter-character timer unused */
+    c_opt.c_cc[VMIN] = 0; /* blocking read until 8 chars received */
+    c_opt.c_cflag &= ~CSIZE;
+    c_opt.c_cflag |= (CS8 | CLOCAL | CREAD);
+    if (MSM_ENABLE_FLOW_CTRL)
+        c_opt.c_cflag |= CRTSCTS;
+    else if (MSM_DISABLE_FLOW_CTRL)
+        c_opt.c_cflag |= ~CRTSCTS;
+    else {
+        fprintf(stderr, "%s: Incorrect option passed for TIOCMSET\n", __func__);
+        return;
+    }
+    c_opt.c_iflag = IGNPAR;
+    c_opt.c_oflag = 0;
+    c_opt.c_lflag = 0;
+    ioctl(fd, TIOCMSET, &c_opt);
+}
+
 
 int rome_set_baudrate_req(int fd)
 {
@@ -1464,12 +1499,10 @@ int rome_set_baudrate_req(int fd)
 
     /* Total length of the packet to be sent to the Controller */
     size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + VSC_SET_BAUDRATE_REQ_LEN);
+
     /* Flow off during baudrate change */
-    if ((err = userial_vendor_ioctl(fd, USERIAL_OP_FLOW_OFF , &flags)) < 0)
-    {
-      fprintf(stderr, "%s: HW Flow-off error: 0x%x\n", __FUNCTION__, err);
-      goto error;
-    }
+    flow_control(fd, MSM_DISABLE_FLOW_CTRL);
+
     /* Send the HCI command packet to UART for transmission */
     fprintf(stderr, "%s: HCI CMD: 0x%x 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, cmd[0], cmd[1], cmd[2], cmd[3],cmd[4]) ;
     err = write(fd, cmd, size);
@@ -1481,11 +1514,8 @@ int rome_set_baudrate_req(int fd)
     userial_vendor_set_baud(USERIAL_BAUD_3M);
 
     /* Flow on after changing local uart baudrate */
-    if ((err = userial_vendor_ioctl(fd, USERIAL_OP_FLOW_ON , &flags)) < 0)
-    {
-        fprintf(stderr, "%s: HW Flow-on error: 0x%x \n", __FUNCTION__, err);
-        return err;
-    }
+    flow_control(fd, MSM_ENABLE_FLOW_CTRL);
+
     /* Check for response from the Controller */
     if ((err =read_vs_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE)) < 0) {
             fprintf(stderr, "%s: Failed to get HCI-VS Event from SOC\n", __FUNCTION__);
@@ -1528,11 +1558,8 @@ int rome_hci_reset_req(int fd)
     size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE);
 
     /* Flow off during baudrate change */
-    if ((err = userial_vendor_ioctl(fd, USERIAL_OP_FLOW_OFF , &flags)) < 0)
-    {
-      fprintf(stderr, "%s: HW Flow-off error: 0x%x\n", __FUNCTION__, err);
-      goto error;
-    }
+    flow_control(fd, MSM_DISABLE_FLOW_CTRL);
+
     /* Send the HCI command packet to UART for transmission */
     fprintf(stderr, "%s: HCI CMD: 0x%x 0x%x 0x%x 0x%x\n", __FUNCTION__, cmd[0], cmd[1], cmd[2], cmd[3]);
     err = write(fd, cmd, size);
@@ -1545,11 +1572,8 @@ int rome_hci_reset_req(int fd)
      userial_vendor_set_baud(USERIAL_BAUD_3M);
 
     /* Flow on after changing local uart baudrate */
-    if ((err = userial_vendor_ioctl(fd, USERIAL_OP_FLOW_ON , &flags)) < 0)
-    {
-        fprintf(stderr, "%s: HW Flow-on error: 0x%x \n", __FUNCTION__, err);
-        return err;
-    }
+    flow_control(fd, MSM_ENABLE_FLOW_CTRL);
+
     /* Wait for command complete event */
     err = read_hci_event(fd, rsp, HCI_MAX_EVENT_SIZE);
     if ( err < 0) {
@@ -1616,7 +1640,6 @@ int qca_soc_init(int fd, char *bdaddr)
     int err = -1;
     int size;
 
-    fprintf(stderr, " %s \n", __FUNCTION__);
     vnd_userial.fd = fd;
     /* Get Rome version information */
     if((err = rome_patch_ver_req(fd)) <0){
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index 77e85e7e7b19..ef3647e6a69b 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -1,7 +1,7 @@
 /*
- * Copyright 2012 The Android Open Source Project
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  * Not a Contribution.
+ * Copyright 2012 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.
@@ -40,6 +40,8 @@
 #define NVITEM_SIZE         2
 #define PERSIST_HEADER_LEN  3
 #define BD_ADDR_LEN         6
+#define MSM_ENABLE_FLOW_CTRL   16
+#define MSM_DISABLE_FLOW_CTRL  17
 
 unsigned char vnd_local_bd_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 typedef enum {

From bd7d1fce8de4639445563442a8448468d671fad2 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Tue, 20 Jan 2015 12:43:20 +0530
Subject: [PATCH 11/19] bluetooth: Add support for multi baud rate

Currently BT operates only at 3M baud rate. Provide option
to configure the pre-defined baud rate values as supported by the
target platform.

Change-Id: I4bbaf7db01ffb983c38dca7c4a4a56f579c678a8
---
 tools/hciattach.c      |   2 +-
 tools/hciattach.h      |   2 +-
 tools/hciattach_rome.c | 109 ++++++++++++++++++++++++++++++++++++++++++-------
 tools/hciattach_rome.h |  23 +++++++++++
 4 files changed, 119 insertions(+), 17 deletions(-)

diff --git a/tools/hciattach.c b/tools/hciattach.c
index c3cf10843303..dda639cabca3 100644
--- a/tools/hciattach.c
+++ b/tools/hciattach.c
@@ -286,7 +286,7 @@ static int ath3k_pm(int fd, struct uart_t *u, struct termios *ti)
 static int qca(int fd, struct uart_t *u, struct termios *ti)
 {
         fprintf(stderr,"qca\n");
-        return qca_soc_init(fd, u->bdaddr);
+        return qca_soc_init(fd, u->speed, u->bdaddr);
 }
 
 static int qualcomm(int fd, struct uart_t *u, struct termios *ti)
diff --git a/tools/hciattach.h b/tools/hciattach.h
index 0656a845223c..49e59321fcac 100644
--- a/tools/hciattach.h
+++ b/tools/hciattach.h
@@ -64,7 +64,7 @@ int ath3k_init(int fd, int speed, int init_speed, char *bdaddr,
 						struct termios *ti);
 int ath3k_post(int fd, int pm);
 int qualcomm_init(int fd, int speed, struct termios *ti, const char *bdaddr);
-int qca_soc_init(int fd, char *bdaddr);
+int qca_soc_init(int fd, int speed, char *bdaddr);
 int intel_init(int fd, int init_speed, int *speed, struct termios *ti);
 int bcm43xx_init(int fd, int def_speed, int speed, struct termios *ti,
 		const char *bdaddr);
diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 1e689273b851..37974290ae0a 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -1481,7 +1481,7 @@ static void flow_control(int fd, int opt)
 }
 
 
-int rome_set_baudrate_req(int fd)
+int rome_set_baudrate_req(int fd, int local_baud_rate, int controller_baud_rate)
 {
    int size, err = 0;
     unsigned char cmd[HCI_MAX_CMD_SIZE];
@@ -1495,7 +1495,7 @@ int rome_set_baudrate_req(int fd)
     cmd[0]  = HCI_COMMAND_PKT;
     cmd_hdr->opcode = cmd_opcode_pack(HCI_VENDOR_CMD_OGF, EDL_SET_BAUDRATE_CMD_OCF);
     cmd_hdr->plen     = VSC_SET_BAUDRATE_REQ_LEN;
-    cmd[4]  = BAUDRATE_3000000;
+    cmd[4]  = controller_baud_rate;
 
     /* Total length of the packet to be sent to the Controller */
     size = (HCI_CMD_IND + HCI_COMMAND_HDR_SIZE + VSC_SET_BAUDRATE_REQ_LEN);
@@ -1511,7 +1511,7 @@ int rome_set_baudrate_req(int fd)
         goto error;
     }
     /* Change Local UART baudrate to high speed UART */
-    userial_vendor_set_baud(USERIAL_BAUD_3M);
+    userial_vendor_set_baud(local_baud_rate);
 
     /* Flow on after changing local uart baudrate */
     flow_control(fd, MSM_ENABLE_FLOW_CTRL);
@@ -1537,7 +1537,7 @@ error:
 }
 
 
-int rome_hci_reset_req(int fd)
+int rome_hci_reset_req(int fd, char baud)
 {
     int size, err = 0;
     unsigned char cmd[HCI_MAX_CMD_SIZE];
@@ -1569,7 +1569,7 @@ int rome_hci_reset_req(int fd)
     }
 
     /* Change Local UART baudrate to high speed UART */
-     userial_vendor_set_baud(USERIAL_BAUD_3M);
+     userial_vendor_set_baud(baud);
 
     /* Flow on after changing local uart baudrate */
     flow_control(fd, MSM_ENABLE_FLOW_CTRL);
@@ -1635,10 +1635,69 @@ int read_bd_address(unsigned char *bdaddr)
   return 0;
 }
 
-int qca_soc_init(int fd, char *bdaddr)
+int isSpeedValid(int speed, int *local_baud_rate, int *controller_baud_rate)
+{
+    switch(speed) {
+    case 9600:
+        *local_baud_rate = USERIAL_BAUD_9600;
+        *controller_baud_rate = BAUDRATE_9600;
+        break;
+    case 19200:
+        *local_baud_rate = USERIAL_BAUD_19200;
+        *controller_baud_rate = BAUDRATE_19200;
+        break;
+    case 57600:
+        *local_baud_rate = USERIAL_BAUD_57600;
+        *controller_baud_rate = BAUDRATE_57600;
+        break;
+    case 115200:
+        *local_baud_rate = USERIAL_BAUD_115200;
+        *controller_baud_rate = BAUDRATE_115200;
+        break;
+    case 230400:
+        *local_baud_rate = USERIAL_BAUD_230400;
+        *controller_baud_rate = BAUDRATE_230400;
+        break;
+    case 460800:
+        *local_baud_rate = USERIAL_BAUD_460800;
+        *controller_baud_rate = BAUDRATE_460800;
+        break;
+    case 921600:
+        *local_baud_rate = USERIAL_BAUD_921600;
+        *controller_baud_rate = BAUDRATE_921600;
+        break;
+    case 1000000:
+        *local_baud_rate = USERIAL_BAUD_1M;
+        *controller_baud_rate = BAUDRATE_1000000;
+        break;
+    case 2000000:
+        *local_baud_rate = USERIAL_BAUD_2M;
+        *controller_baud_rate = BAUDRATE_2000000;
+        break;
+    case 3000000:
+        *local_baud_rate = USERIAL_BAUD_3M;
+        *controller_baud_rate = BAUDRATE_3000000;
+        break;
+    case 4000000:
+        *local_baud_rate = USERIAL_BAUD_4M;
+        *controller_baud_rate = BAUDRATE_4000000;
+        break;
+    case 300:
+    case 600:
+    case 1200:
+    case 2400:
+    default:
+        fprintf(stderr, "Invalid baud rate passed!\n");
+        *local_baud_rate = *controller_baud_rate = -1;
+        break;
+    }
+    return -1;
+}
+
+int qca_soc_init(int fd, int speed, char *bdaddr)
 {
     int err = -1;
-    int size;
+    int size, local_baud_rate = 0, controller_baud_rate = 0;
 
     vnd_userial.fd = fd;
     /* Get Rome version information */
@@ -1687,7 +1746,7 @@ int qca_soc_init(int fd, char *bdaddr)
                 }
 
                 /* Change baud rate 115.2 kbps to 3Mbps*/
-                err = rome_hci_reset_req(fd);
+                err = rome_hci_reset_req(fd, local_baud_rate);
                 if ( err <0 ) {
                     fprintf(stderr, "HCI Reset Failed !!\n");
                     goto error;
@@ -1721,13 +1780,23 @@ int qca_soc_init(int fd, char *bdaddr)
             nvm_file_path = TF_NVM_TLV_1_0_0_PATH;
 
 download:
-            /* Change baud rate 115.2 kbps to 3Mbps*/
-            err = rome_set_baudrate_req(fd);
-            if (err < 0) {
-                fprintf(stderr, "%s: Baud rate change failed!\n", __FUNCTION__);
-                goto error;
+            /* Check if user requested for 115200 kbps */
+            if (speed == 115200) {
+                local_baud_rate = USERIAL_BAUD_115200;
+                controller_baud_rate = BAUDRATE_115200;
             }
-            fprintf(stderr, "%s: Baud rate changed successfully \n", __FUNCTION__);
+            else {
+                /* Change only if baud rate requested is valid or not */
+                isSpeedValid(speed, &local_baud_rate, &controller_baud_rate);
+                if (local_baud_rate < 0 || controller_baud_rate < 0)
+                    goto error;
+
+                err = rome_set_baudrate_req(fd, local_baud_rate, controller_baud_rate);
+                if (err < 0) {
+                    fprintf(stderr, "%s: Baud rate change failed!\n", __FUNCTION__);
+                    goto error;
+                }
+             }
 
             /* Donwload TLV files (rampatch, NVM) */
             err = rome_download_tlv_file(fd);
@@ -1737,8 +1806,18 @@ download:
             }
             fprintf(stderr, "%s: Download TLV file successfully \n", __FUNCTION__);
 
+            /*
+             * Overriding the baud rate value in NVM file with the user
+             * requested baud rate, since default baud rate in NVM file is 3M.
+             */
+            err = rome_set_baudrate_req(fd, local_baud_rate, controller_baud_rate);
+            if (err < 0) {
+                fprintf(stderr, "%s: Baud rate change failed!\n", __FUNCTION__);
+                goto error;
+            }
+
             /* Perform HCI reset here*/
-            err = rome_hci_reset_req(fd);
+            err = rome_hci_reset_req(fd, local_baud_rate);
             if ( err <0 ) {
                 fprintf(stderr, "HCI Reset Failed !!!\n");
                 goto error;
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index ef3647e6a69b..1500ddd3a79f 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -78,6 +78,29 @@ typedef struct
 #define USERIAL_BAUD_4M         15
 #define USERIAL_BAUD_AUTO       16
 
+/* Vendor specific baud rate values */
+#define UART_Baud_Rate_Baud_9600        4
+#define UART_Baud_Rate_Baud_19200       3
+#define UART_Baud_Rate_Baud_57600       1
+#define UART_Baud_Rate_Baud_115200      0
+#define UART_Baud_Rate_Baud_230400      5
+#define UART_Baud_Rate_Baud_460800      7
+#define UART_Baud_Rate_Baud_921600      10
+#define UART_Baud_Rate_Baud_1000000     11
+#define UART_Baud_Rate_Baud_2000000     13
+#define UART_Baud_Rate_Baud_3000000     14
+#define UART_Baud_Rate_Baud_4000000     15
+
+#define UART_Baud_Rate_Baud_250000      6
+#define UART_Baud_Rate_Baud_500000      8
+#define UART_Baud_Rate_Baud_720000      9
+#define UART_Baud_Rate_Baud_125000      12
+#define UART_Baud_Rate_Baud_1600000     16
+#define UART_Baud_Rate_Baud_3200000     17
+#define UART_Baud_Rate_Baud_3500000     18
+
+
+
 #ifndef FALSE
 #define FALSE  0
 #endif

From 7dc9c5e316aa9a22899259ce296136b2e257735d Mon Sep 17 00:00:00 2001
From: Kamal Negi <kamaln@codeaurora.org>
Date: Tue, 30 Dec 2014 19:15:08 +0530
Subject: [PATCH 12/19] Override PCM Settings by reading configuration file

Configure the PCM role as master or slave depending upon
the platform's support. This configuration is provided
in the config file which is read during the firmware
download process and the default PCM configuration is
overwritten with this value.

Change-Id: If0eae58b4cd32d75b3bcb669bc73dca67652473c
Signed-off-by: Kamal Negi <kamaln@codeaurora.org>
---
 tools/hciattach_rome.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++---
 tools/hciattach_rome.h |  8 ++++++
 2 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 37974290ae0a..99866e23e99e 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *  Not a Contribution.
  *
  *  Copyright 2012 The Android Open Source Project
@@ -873,6 +873,44 @@ error:
     return err;
 }
 
+int get_value_from_config(char *file_path,char *param)
+{
+    FILE *pfile = NULL;
+    char *line = NULL;
+    char *pch = NULL;
+    char param_str[20];
+    int bytes_read = 0, position;
+    int ret = -1;
+
+    if (!file_path || !param) {
+        fprintf(stderr,"Invalid arguments\n");
+        return -EINVAL;
+    }
+
+    pfile = fopen(file_path, "r" );
+    if (!pfile) {
+        fprintf(stderr, "Failed to open %s\n", file_path);
+        return ret;
+    }
+
+    while (getline(&line, &bytes_read, pfile) > 0 ) {
+        if (line[0] != '#'  && line[0] != '\n') {
+            pch = memchr(line, '=', strlen(line));
+            if (pch != NULL) {
+                position = pch - line;
+                strncpy(param_str, line, position);
+                if (strncmp(param_str, param, position) == 0) {
+                    ret = atoi(pch + 1);
+                    break;
+                }
+            }
+        }
+    }
+    free(line);
+    fclose(pfile);
+    return ret;
+}
+
 int rome_get_tlv_file(char *file_path)
 {
     FILE * pFile;
@@ -884,7 +922,7 @@ int rome_get_tlv_file(char *file_path)
     unsigned char data_buf[PRINT_BUF_SIZE]={0,};
     unsigned char *nvm_byte_ptr;
     unsigned char bdaddr[6];
-
+    unsigned short pcm_value;
     fprintf(stderr, "File Open (%s)\n", file_path);
     pFile = fopen ( file_path , "r" );
     if (pFile==NULL) {;
@@ -970,9 +1008,30 @@ int rome_get_tlv_file(char *file_path)
                     *nvm_byte_ptr, *(nvm_byte_ptr+1), *(nvm_byte_ptr+2),
                     *(nvm_byte_ptr+3), *(nvm_byte_ptr+4), *(nvm_byte_ptr+5));
             }
+            /* Read from file and check what PCM Configuration is required:
+             * Master = 0 /Slave = 1 */
+            /* Override PCM configuration */
+            if (nvm_ptr->tag_id == TAG_NUM_44) {
+                if ((pcm_value =
+                    get_value_from_config(PCM_CONFIG_FILE_PATH, "PCM")) >= 0) {
+
+                    if (pcm_value == PCM_SLAVE) {
+                        nvm_byte_ptr[PCM_MS_OFFSET_1] |=
+                                                    (1 << PCM_ROLE_BIT_OFFSET);
+                        nvm_byte_ptr[PCM_MS_OFFSET_2] |=
+                                                    (1 << PCM_ROLE_BIT_OFFSET);
+                    } else if (pcm_value == PCM_MASTER) {
+                        nvm_byte_ptr[PCM_MS_OFFSET_1] &=
+                                                 (~(1 << PCM_ROLE_BIT_OFFSET));
+                        nvm_byte_ptr[PCM_MS_OFFSET_2] &=
+                                                 (~(1 << PCM_ROLE_BIT_OFFSET));
+                    }
+                }
+            }
 
-            for(i =0;(i<nvm_ptr->tag_len && (i*3 + 2) <PRINT_BUF_SIZE);i++)
-                snprintf((char *) data_buf, PRINT_BUF_SIZE, "%s%.02x ", (char *)data_buf, *(nvm_byte_ptr + i));
+            for(i =0;(i<nvm_ptr->tag_len && (i*3 + 2) < PRINT_BUF_SIZE);i++)
+                snprintf((char *) data_buf, PRINT_BUF_SIZE, "%s%.02x ",
+                    (char *)data_buf, *(nvm_byte_ptr + i));
 
             fprintf(stderr, "TAG Data\t\t\t : %s\n", data_buf);
 
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index 1500ddd3a79f..f591c10e4f2b 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -202,8 +202,15 @@ typedef struct
 #define NVM_ACCESS_SET            0x01
 #define TAG_NUM_OFFSET             5
 #define TAG_NUM_2                       2
+#define TAG_NUM_44                      44
 #define TAG_BDADDR_OFFSET     7
 
+#define PCM_MS_OFFSET_1       9
+#define PCM_MS_OFFSET_2       33
+
+#define PCM_SLAVE            1
+#define PCM_MASTER           0
+#define PCM_ROLE_BIT_OFFSET  4
 #define MAX_RETRY_CNT  1
 #define SELECT_TIMEOUT 3
 
@@ -240,6 +247,7 @@ typedef struct
 #define ROME_SKIP_EVT_CC       0x02
 #define ROME_SKIP_EVT_VSE_CC   0x03
 
+#define PCM_CONFIG_FILE_PATH        "/etc/bluetooth/pcm.conf"
 /******************************************************************************
 **  Local type definitions
 ******************************************************************************/

From 9eb8220969598d63be3b918b49b6258387629bf3 Mon Sep 17 00:00:00 2001
From: Rupesh Tatiya <rtatiya@codeaurora.org>
Date: Thu, 29 Jan 2015 15:36:27 +0530
Subject: [PATCH 13/19] Add support for Tufello 1.1 SOC

Enable mechanism to download firmware for Tufello 1.1 SOC.
Also, use correct firmware file path for Tufello 1.0.

Change-Id: I915e48023e45de9e2550336a3de9a07f2b788189
Signed-off-by: Rupesh Tatiya <rtatiya@codeaurora.org>
---
 tools/hciattach_rome.c | 29 ++++++++++++++++++-----------
 tools/hciattach_rome.h | 10 +++++++---
 2 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 99866e23e99e..fee36f904e04 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -621,7 +621,7 @@ int rome_edl_set_patch_request(int fd)
         -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);
@@ -670,7 +670,7 @@ int rome_edl_patch_download_request(int fd)
         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);
@@ -707,7 +707,7 @@ int rome_edl_patch_download_request(int fd)
         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);
@@ -824,7 +824,7 @@ int rome_attach_rampatch(int fd)
         -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);
@@ -854,7 +854,7 @@ int rome_rampatch_reset(int fd)
                                         -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);
@@ -1058,7 +1058,7 @@ int rome_tlv_dnld_segment(int fd, int index, int seg_size, unsigned char wait_cc
     unsigned char cmd[HCI_MAX_CMD_SIZE];
     unsigned char rsp[HCI_MAX_EVENT_SIZE];
 
-    fprintf(stderr, "%s: Downloading TLV Patch segment no.%d, size:%d\n", __FUNCTION__, index, seg_size);
+    fprintf(stderr, "%s: Downloading TLV Patch segment no.%d, size:%d wait_cc_evt = 0x%x\n", __FUNCTION__, index, seg_size, wait_cc_evt);
 
     /* Frame the HCI CMD PKT to be sent to Controller*/
     frame_hci_cmd_pkt(cmd, EDL_PATCH_TLV_REQ_CMD, 0, index, seg_size);
@@ -1092,6 +1092,7 @@ int rome_tlv_dnld_req(int fd, int tlv_size)
 {
     int  total_segment, remain_size, i, err = -1;
     unsigned char wait_cc_evt;
+    unsigned int rom = rome_ver >> 16;
 
     total_segment = tlv_size/MAX_SIZE_PER_TLV_SEGMENT;
     remain_size = (tlv_size < MAX_SIZE_PER_TLV_SEGMENT)?\
@@ -1132,14 +1133,15 @@ int rome_tlv_dnld_req(int fd, int tlv_size)
 
     for(i = 0; i < total_segment; i++) {
         if((i+1) == total_segment) {
-             if ((rome_ver >= ROME_VER_1_1) && (rome_ver < ROME_VER_3_2) &&
+             if ((rom >= ROME_PATCH_VER_0100) && (rom < ROME_PATCH_VER_0302) &&
                  (gTlv_type == TLV_TYPE_PATCH)) {
                /* If the Rome version is from 1.1 to 3.1
                 * 1. No CCE for the last command segment but all other segment
                 * 2. All the command segments get VSE including the last one
                 */
                 wait_cc_evt = !remain_size ? FALSE: TRUE;
-             } else if ((rome_ver == ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+             } else if ((rom == ROME_PATCH_VER_0302) &&
+                             (gTlv_type == TLV_TYPE_PATCH)) {
                 /* If the Rome version is 3.2
                  * 1. None of the command segments receive CCE
                  * 2. No command segments receive VSE except the last one
@@ -1158,13 +1160,14 @@ int rome_tlv_dnld_req(int fd, int tlv_size)
             goto error;
     }
 
-    if ((rome_ver >= ROME_VER_1_1) && (rome_ver < ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+    if ((rom >= ROME_PATCH_VER_0100) && (rom < ROME_PATCH_VER_0302) &&
+                                               (gTlv_type == TLV_TYPE_PATCH)) {
        /* If the Rome version is from 1.1 to 3.1
         * 1. No CCE for the last command segment but all other segment
         * 2. All the command segments get VSE including the last one
         */
         wait_cc_evt = remain_size ? FALSE: TRUE;
-    } else if ((rome_ver == ROME_VER_3_2) && (gTlv_type == TLV_TYPE_PATCH)) {
+    } else if ((rom == ROME_PATCH_VER_0302) && (gTlv_type == TLV_TYPE_PATCH)) {
         /* If the Rome version is 3.2
          * 1. None of the command segments receive CCE
          * 2. No command segments receive VSE except the last one
@@ -1837,6 +1840,10 @@ int qca_soc_init(int fd, int speed, char *bdaddr)
         case TUFELLO_VER_1_0:
             rampatch_file_path = TF_RAMPATCH_TLV_1_0_0_PATH;
             nvm_file_path = TF_NVM_TLV_1_0_0_PATH;
+            goto download;
+        case TUFELLO_VER_1_1:
+            rampatch_file_path = TF_RAMPATCH_TLV_1_0_1_PATH;
+            nvm_file_path = TF_NVM_TLV_1_0_1_PATH;
 
 download:
             /* Check if user requested for 115200 kbps */
@@ -1881,7 +1888,7 @@ download:
                 fprintf(stderr, "HCI Reset Failed !!!\n");
                 goto error;
             }
-	    fprintf(stderr, "HCI Reset is done\n");
+            fprintf(stderr, "HCI Reset is done\n");
 
             break;
         case ROME_VER_UNKNOWN:
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index f591c10e4f2b..95d5f1e8a5c2 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -238,8 +238,10 @@ typedef struct
 #define ROME_NVM_TLV_3_0_0_PATH         "/lib/firmware/qca/nvm_tlv_3.0.bin"
 #define ROME_RAMPATCH_TLV_3_0_2_PATH    "/lib/firmware/qca/rampatch_tlv_3.2.tlv"
 #define ROME_NVM_TLV_3_0_2_PATH         "/lib/firmware/qca/nvm_tlv_3.2.bin"
-#define TF_RAMPATCH_TLV_1_0_0_PATH    "/lib/firmware/rampatch_tlv_tf_1.0.tlv"
-#define TF_NVM_TLV_1_0_0_PATH         "/lib/firmware/nvm_tlv_tf_1.0.bin"
+#define TF_RAMPATCH_TLV_1_0_0_PATH      "/lib/firmware/qca/rampatch_tlv_tf_1.0.tlv"
+#define TF_NVM_TLV_1_0_0_PATH           "/lib/firmware/qca/nvm_tlv_tf_1.0.bin"
+#define TF_RAMPATCH_TLV_1_0_1_PATH      "/lib/firmware/qca/rampatch_tlv_tf_1.1.tlv"
+#define TF_NVM_TLV_1_0_1_PATH           "/lib/firmware/qca/nvm_tlv_tf_1.1.bin"
 
 /* This header value in rampatch file decides event handling mechanism in the HOST */
 #define ROME_SKIP_EVT_NONE     0x00
@@ -357,6 +359,7 @@ enum{
     ROME_SOC_ID_11 = 0x00000011,
     ROME_SOC_ID_13 = 0x00000013,
     ROME_SOC_ID_22 = 0x00000022,
+    ROME_SOC_ID_23 = 0x00000023,
     ROME_SOC_ID_44 = 0x00000044
 };
 
@@ -368,6 +371,7 @@ enum{
     ROME_VER_2_1 = ((ROME_PATCH_VER_0200 << 16 ) | ROME_SOC_ID_11 ),
     ROME_VER_3_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_22 ),
     ROME_VER_3_2 = ((ROME_PATCH_VER_0302 << 16 ) | ROME_SOC_ID_44 ),
-    TUFELLO_VER_1_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_13 )
+    TUFELLO_VER_1_0 = ((ROME_PATCH_VER_0300 << 16 ) | ROME_SOC_ID_13 ),
+    TUFELLO_VER_1_1 = ((ROME_PATCH_VER_0302 << 16 ) | ROME_SOC_ID_23 )
 };
 #endif /* HW_ROME_H */

From f55d710cf43d008e42ce06ead49dc0dfbf97d3a1 Mon Sep 17 00:00:00 2001
From: Anantha Krishnan <ananthk@codeaurora.org>
Date: Wed, 4 Feb 2015 12:29:07 +0530
Subject: [PATCH 14/19] bluetooth: Vote UART CLK ON prior to firmware download
 process

Before starting the firmware download process, vote UART CLK ON
to avoid triggering the dynamic suspend of UART driver. Post
firmware download and in error scenarios vote UART CLK OFF.

As per design, the UART driver enters into dynamic suspend if
there are no activity on the UART lines for 100ms. Depending upon
the rampatch size, the BT Controller takes time to apply the
downloaded rampatch segments and in sending the vendor specific
event. If the BT Controller takes > 100ms time in sending the
vendor specific event, the UART driver enters into suspend state.

As a result, UART driver fails to process the last vendor specific
event sent by the BT Controller. The VSE sent by BT Controller
wakes up the UART driver, but the data is not processed causing
firmware download failures.

Hence, vote UART CLK ON prior to firmware download process and
vote UART CLK OFF post firmware download proess and in error
scenarios.

Change-Id: I447ded33ad1cfaa020b491effce368fbfe41f894
---
 tools/hciattach_rome.c | 13 +++++++++++++
 tools/hciattach_rome.h |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index fee36f904e04..574ceac6c750 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -1762,6 +1762,14 @@ int qca_soc_init(int fd, int speed, char *bdaddr)
     int size, local_baud_rate = 0, controller_baud_rate = 0;
 
     vnd_userial.fd = fd;
+
+    /* Vote for UART CLK prior to FW download */
+    err = ioctl(fd, USERIAL_OP_CLK_ON);
+    if (err < 0) {
+        fprintf(stderr, "%s: Failed to vote UART CLK ON\n", __func__);
+        return -1;
+    }
+
     /* Get Rome version information */
     if((err = rome_patch_ver_req(fd)) <0){
         fprintf(stderr, "%s: Fail to get Rome Version (0x%x)\n", __FUNCTION__, err);
@@ -1899,5 +1907,10 @@ download:
     }
 
 error:
+    /* Vote UART CLK OFF post to FW download */
+    err = ioctl(fd, USERIAL_OP_CLK_OFF);
+    if (err < 0)
+        fprintf(stderr, "%s: Failed to vote UART CLK OFF!!!\n", __func__);
+
     return err;
 }
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index 95d5f1e8a5c2..20264f9978d9 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -42,6 +42,8 @@
 #define BD_ADDR_LEN         6
 #define MSM_ENABLE_FLOW_CTRL   16
 #define MSM_DISABLE_FLOW_CTRL  17
+#define USERIAL_OP_CLK_ON      0x5441
+#define USERIAL_OP_CLK_OFF     0x5442
 
 unsigned char vnd_local_bd_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 typedef enum {

From b09f8b12c937ec58df0581b2d95493e036c86432 Mon Sep 17 00:00:00 2001
From: Kamal Negi <kamaln@codeaurora.org>
Date: Thu, 30 Apr 2015 15:53:06 +0530
Subject: [PATCH 15/19] Override IBS settings by reading configuration file

Configure the IBS value in Firmware by reading the
configuration file.This configuration value is
provided in the config file which is read during
the firmware download process and the default
configuration value is overwritten with this value.

Change-Id: I47992a573b3137ac9bfb80538727981f56b328c4
Signed-off-by: Kamal Negi <kamaln@codeaurora.org>
---
 tools/hciattach_rome.c | 42 +++++++++++++++++++++++++++++-------------
 tools/hciattach_rome.h | 24 ++++++++++++++++--------
 2 files changed, 45 insertions(+), 21 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 574ceac6c750..6a3f33867c12 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -922,7 +922,8 @@ int rome_get_tlv_file(char *file_path)
     unsigned char data_buf[PRINT_BUF_SIZE]={0,};
     unsigned char *nvm_byte_ptr;
     unsigned char bdaddr[6];
-    unsigned short pcm_value;
+    unsigned short pcm_value, ibs_value;
+
     fprintf(stderr, "File Open (%s)\n", file_path);
     pFile = fopen ( file_path , "r" );
     if (pFile==NULL) {;
@@ -1008,23 +1009,38 @@ int rome_get_tlv_file(char *file_path)
                     *nvm_byte_ptr, *(nvm_byte_ptr+1), *(nvm_byte_ptr+2),
                     *(nvm_byte_ptr+3), *(nvm_byte_ptr+4), *(nvm_byte_ptr+5));
             }
+
+	    if (nvm_ptr->tag_id == TAG_NUM_17) {
+		if ((ibs_value =
+			get_value_from_config(FW_CONFIG_FILE_PATH, "IBS")) >= 0) {
+			if (ibs_value == FWCONF_IBS_DISABLE) {
+				nvm_byte_ptr[FWCONF_IBS_VAL_OFFSET] &=
+					(~(FWCONF_IBS_ENABLE <<
+							FWCONF_IBS_VAL_BIT));
+			} else if (ibs_value == FWCONF_IBS_ENABLE) {
+				nvm_byte_ptr[FWCONF_IBS_VAL_OFFSET] |=
+					(FWCONF_IBS_ENABLE <<
+							FWCONF_IBS_VAL_BIT);
+			}
+		}
+	    }
             /* Read from file and check what PCM Configuration is required:
              * Master = 0 /Slave = 1 */
             /* Override PCM configuration */
             if (nvm_ptr->tag_id == TAG_NUM_44) {
                 if ((pcm_value =
-                    get_value_from_config(PCM_CONFIG_FILE_PATH, "PCM")) >= 0) {
-
-                    if (pcm_value == PCM_SLAVE) {
-                        nvm_byte_ptr[PCM_MS_OFFSET_1] |=
-                                                    (1 << PCM_ROLE_BIT_OFFSET);
-                        nvm_byte_ptr[PCM_MS_OFFSET_2] |=
-                                                    (1 << PCM_ROLE_BIT_OFFSET);
-                    } else if (pcm_value == PCM_MASTER) {
-                        nvm_byte_ptr[PCM_MS_OFFSET_1] &=
-                                                 (~(1 << PCM_ROLE_BIT_OFFSET));
-                        nvm_byte_ptr[PCM_MS_OFFSET_2] &=
-                                                 (~(1 << PCM_ROLE_BIT_OFFSET));
+                    get_value_from_config(FW_CONFIG_FILE_PATH, "PCM")) >= 0) {
+
+                    if (pcm_value == FWCONF_PCM_SLAVE) {
+                        nvm_byte_ptr[FWCONF_PCM_MS_OFFSET_1] |=
+					(1 << FWCONF_PCM_ROLE_BIT_OFFSET);
+                        nvm_byte_ptr[FWCONF_PCM_MS_OFFSET_2] |=
+					(1 << FWCONF_PCM_ROLE_BIT_OFFSET);
+                    } else if (pcm_value == FWCONF_PCM_MASTER) {
+                        nvm_byte_ptr[FWCONF_PCM_MS_OFFSET_1] &=
+					(~(1 << FWCONF_PCM_ROLE_BIT_OFFSET));
+                        nvm_byte_ptr[FWCONF_PCM_MS_OFFSET_2] &=
+					(~(1 << FWCONF_PCM_ROLE_BIT_OFFSET));
                     }
                 }
             }
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index 20264f9978d9..8eaeeed8bc96 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -203,16 +203,24 @@ typedef struct
 #define TAG_END                           0xFF
 #define NVM_ACCESS_SET            0x01
 #define TAG_NUM_OFFSET             5
-#define TAG_NUM_2                       2
-#define TAG_NUM_44                      44
+#define TAG_NUM_2			2
+#define TAG_NUM_17			(17)
+#define TAG_NUM_44			44
 #define TAG_BDADDR_OFFSET     7
 
-#define PCM_MS_OFFSET_1       9
-#define PCM_MS_OFFSET_2       33
+/* FW PCM Configuration */
+#define FWCONF_PCM_MS_OFFSET_1		9
+#define FWCONF_PCM_MS_OFFSET_2		33
+#define FWCONF_PCM_SLAVE		1
+#define FWCONF_PCM_MASTER		0
+#define FWCONF_PCM_ROLE_BIT_OFFSET	4
+
+/* FW IBS Configuration */
+#define FWCONF_IBS_DISABLE		(0)
+#define FWCONF_IBS_ENABLE		(1)
+#define FWCONF_IBS_VAL_BIT		(7)
+#define FWCONF_IBS_VAL_OFFSET		(0)
 
-#define PCM_SLAVE            1
-#define PCM_MASTER           0
-#define PCM_ROLE_BIT_OFFSET  4
 #define MAX_RETRY_CNT  1
 #define SELECT_TIMEOUT 3
 
@@ -251,7 +259,7 @@ typedef struct
 #define ROME_SKIP_EVT_CC       0x02
 #define ROME_SKIP_EVT_VSE_CC   0x03
 
-#define PCM_CONFIG_FILE_PATH        "/etc/bluetooth/pcm.conf"
+#define FW_CONFIG_FILE_PATH        "/etc/bluetooth/firmware.conf"
 /******************************************************************************
 **  Local type definitions
 ******************************************************************************/

From b307659dc988054c1fef32c131417cfab2b74c3e Mon Sep 17 00:00:00 2001
From: Dibyendu Roy <dibyen@codeaurora.org>
Date: Fri, 22 May 2015 18:57:05 +0530
Subject: [PATCH 16/19] bluetooth: Fix flow control operation

Flow off operation was not actually happening at the UART line level,
since the argument passed was not being used correctly. As a result,
sometimes command complete and VS event were sent by BT SOC even
before the local UART Controller could change its baud rate to the
newer one(3 Mbps). This led to VS event being processed
incorrectly which in turn causes baud rate change to fail.

CRs-Fixed: 844730
Change-Id: I06d8c4ed7807aa47dd5498642c7a23c9189a1cff
Signed-off-by: Dibyendu Roy <dibyen@codeaurora.org>
---
 tools/hciattach_rome.c | 6 +++---
 tools/hciattach_rome.h | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 6a3f33867c12..0d7014f1d2f6 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -1544,10 +1544,10 @@ static void flow_control(int fd, int opt)
     c_opt.c_cc[VMIN] = 0; /* blocking read until 8 chars received */
     c_opt.c_cflag &= ~CSIZE;
     c_opt.c_cflag |= (CS8 | CLOCAL | CREAD);
-    if (MSM_ENABLE_FLOW_CTRL)
+    if (opt == MSM_ENABLE_FLOW_CTRL)
         c_opt.c_cflag |= CRTSCTS;
-    else if (MSM_DISABLE_FLOW_CTRL)
-        c_opt.c_cflag |= ~CRTSCTS;
+    else if (opt == MSM_DISABLE_FLOW_CTRL)
+        c_opt.c_cflag &= ~CRTSCTS;
     else {
         fprintf(stderr, "%s: Incorrect option passed for TIOCMSET\n", __func__);
         return;
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index 8eaeeed8bc96..3fdaf208e522 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -40,8 +40,8 @@
 #define NVITEM_SIZE         2
 #define PERSIST_HEADER_LEN  3
 #define BD_ADDR_LEN         6
-#define MSM_ENABLE_FLOW_CTRL   16
-#define MSM_DISABLE_FLOW_CTRL  17
+#define MSM_DISABLE_FLOW_CTRL  0
+#define MSM_ENABLE_FLOW_CTRL   1
 #define USERIAL_OP_CLK_ON      0x5441
 #define USERIAL_OP_CLK_OFF     0x5442
 

From bec6be1174e250c60b48b51933ab6f80a27a093e Mon Sep 17 00:00:00 2001
From: Dibyendu Roy <dibyen@codeaurora.org>
Date: Thu, 11 Jun 2015 12:07:43 +0530
Subject: [PATCH 17/19] Adding MDM specific code under _PLATFORM_MDM_

This patch is added to comment out the commit
84cc0e12983b5761c67789ef93fd6fb164c7314d in x86 as
dynamic suspend feature is not available in x86. However,
this code shall be active for MDM platform due to
dynamic suspend feature.

Change-Id: I998f0521b4a5f9744412db40f2c2d3bff2ac3d11
---
 tools/hciattach_rome.c | 5 ++++-
 tools/hciattach_rome.h | 3 +++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 0d7014f1d2f6..1891de24e21a 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -1779,13 +1779,14 @@ int qca_soc_init(int fd, int speed, char *bdaddr)
 
     vnd_userial.fd = fd;
 
+#ifdef _PLATFORM_MDM_
     /* Vote for UART CLK prior to FW download */
     err = ioctl(fd, USERIAL_OP_CLK_ON);
     if (err < 0) {
         fprintf(stderr, "%s: Failed to vote UART CLK ON\n", __func__);
         return -1;
     }
-
+#endif
     /* Get Rome version information */
     if((err = rome_patch_ver_req(fd)) <0){
         fprintf(stderr, "%s: Fail to get Rome Version (0x%x)\n", __FUNCTION__, err);
@@ -1923,10 +1924,12 @@ download:
     }
 
 error:
+#ifdef _PLATFORM_MDM_
     /* Vote UART CLK OFF post to FW download */
     err = ioctl(fd, USERIAL_OP_CLK_OFF);
     if (err < 0)
         fprintf(stderr, "%s: Failed to vote UART CLK OFF!!!\n", __func__);
+#endif
 
     return err;
 }
diff --git a/tools/hciattach_rome.h b/tools/hciattach_rome.h
index 3fdaf208e522..89f7db3bef86 100644
--- a/tools/hciattach_rome.h
+++ b/tools/hciattach_rome.h
@@ -42,8 +42,11 @@
 #define BD_ADDR_LEN         6
 #define MSM_DISABLE_FLOW_CTRL  0
 #define MSM_ENABLE_FLOW_CTRL   1
+
+#ifdef _PLATFORM_MDM_
 #define USERIAL_OP_CLK_ON      0x5441
 #define USERIAL_OP_CLK_OFF     0x5442
+#endif
 
 unsigned char vnd_local_bd_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 typedef enum {

From 5ab2a193c11eaa8a68a0e060a560a5bd2ee2459c Mon Sep 17 00:00:00 2001
From: Dibyendu Roy <dibyen@codeaurora.org>
Date: Mon, 6 Jul 2015 13:30:53 +0530
Subject: [PATCH 18/19] Bluetooth: Fix static analysis issues

Change-Id: Ida91f012544c39a8aaa6e7db23f1d5b68d3bec08
---
 tools/hciattach_rome.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/tools/hciattach_rome.c b/tools/hciattach_rome.c
index 1891de24e21a..59bdc16e4e8f 100644
--- a/tools/hciattach_rome.c
+++ b/tools/hciattach_rome.c
@@ -933,7 +933,13 @@ int rome_get_tlv_file(char *file_path)
 
     /* Get File Size */
     fseek (pFile , 0 , SEEK_END);
-    fileSize = ftell (pFile);
+
+    if((fileSize = ftell(pFile)) < 0) {
+        fprintf(stderr, "%s: fail to get current file position\n", file_path);
+        fclose (pFile);
+        return -1;
+    }
+
     rewind (pFile);
 
     pdata_buffer = (unsigned char*) malloc (sizeof(char)*fileSize);
@@ -1107,7 +1113,7 @@ int rome_tlv_dnld_segment(int fd, int index, int seg_size, unsigned char wait_cc
 int rome_tlv_dnld_req(int fd, int tlv_size)
 {
     int  total_segment, remain_size, i, err = -1;
-    unsigned char wait_cc_evt;
+    unsigned char wait_cc_evt = FALSE;
     unsigned int rom = rome_ver >> 16;
 
     total_segment = tlv_size/MAX_SIZE_PER_TLV_SEGMENT;

From ca52faad6e23bee353e3315f136efb43d1e9d143 Mon Sep 17 00:00:00 2001
From: Kamal Negi <kamaln@codeaurora.org>
Date: Fri, 8 May 2015 15:01:02 +0530
Subject: [PATCH 19/19] Handle NULL Pointer derefrencing in AVRCP Target role

Check NULL pointer to AVRCP controller role initialized or not.
If remote device don't support the AVRCP target role, then HOST dont
initialize AVRCP controller role and directly dereference the controller
role and segfault happens.

Change-Id: Ibbb9452f17a576c3a79a53ea72e0211982752144
Signed-off-by: Kamal Negi <kamaln@codeaurora.org>
---
 profiles/audio/avrcp.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index c100149acf42..d8cb0ed96a1f 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -2082,13 +2082,19 @@ static gboolean avrcp_get_play_status_rsp(struct avctp *conn, uint8_t code,
 					void *user_data)
 {
 	struct avrcp *session = user_data;
-	struct avrcp_player *player = session->controller->player;
-	struct media_player *mp = player->user_data;
+	struct avrcp_player *player;
+	struct media_player *mp;
 	struct avrcp_header *pdu = (void *) operands;
 	uint32_t duration;
 	uint32_t position;
 	uint8_t status;
 
+	if (!session || !session->controller)
+		return FALSE;
+
+	player = session->controller->player;
+	mp = player->user_data;
+
 	if (pdu == NULL || code == AVC_CTYPE_REJECTED ||
 						ntohs(pdu->params_len) != 9)
 		return FALSE;
@@ -2146,12 +2152,18 @@ static gboolean avrcp_player_value_rsp(struct avctp *conn, uint8_t code,
 					void *user_data)
 {
 	struct avrcp *session = user_data;
-	struct avrcp_player *player = session->controller->player;
-	struct media_player *mp = player->user_data;
+	struct avrcp_player *player;
+	struct media_player *mp;
 	struct avrcp_header *pdu = (void *) operands;
 	uint8_t count;
 	int i;
 
+	if (!session || !session->controller)
+		return FALSE;
+
+	player = session->controller->player;
+	mp = player->user_data;
+
 	if (pdu == NULL) {
 		media_player_set_setting(mp, "Error", "Timeout");
 		return FALSE;
@@ -2303,10 +2315,15 @@ static gboolean avrcp_get_element_attributes_rsp(struct avctp *conn,
 						void *user_data)
 {
 	struct avrcp *session = user_data;
-	struct avrcp_player *player = session->controller->player;
+	struct avrcp_player *player;
 	struct avrcp_header *pdu = (void *) operands;
 	uint8_t count;
 
+	if (!session || !session->controller)
+		return FALSE;
+
+	player = session->controller->player;
+
 	if (code == AVC_CTYPE_REJECTED)
 		return FALSE;
 
