From 64912e658db8883637afd298b0a8eda1f49b056a Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 Upstream-Status: Inappropriate [DEY specific] Change-Id: I87f2927d7096904071a02d73d3afef0dc34db414 Signed-off-by: Rupesh Tatiya --- Makefile.tools | 3 +- tools/hciattach.c | 25 +- tools/hciattach.h | 3 + tools/hciattach_rome.c | 1578 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/hciattach_rome.h | 317 ++++++++++ 5 files changed, 1924 insertions(+), 2 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..93577e9474de 100644 --- a/tools/hciattach.h +++ b/tools/hciattach.h @@ -43,6 +43,8 @@ #define HCI_UART_BCM 7 #define HCI_UART_QCA 8 +#define HCI_UART_IBS 12 + #define HCI_UART_RAW_DEVICE 0 #define HCI_UART_RESET_ON_INIT 1 #define HCI_UART_CREATE_AMP 2 @@ -63,6 +65,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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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;(itag_len && (i*3 + 2) 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= 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 f84a56a539fa5f37b1a8262520bf4ab7f503cc17 Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 --- 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 05c8c51fbdce151bcd050a8b742c3af7ba175ceb Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 --- 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 480096d50d5cad31650380470f9c7f7e783f38e4 Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 --- 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 91decff6ed724123a182f4ca0514b7e55b2b5d0f Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 --- 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 ec990e2f5c62417dc32cc3f23af3c5861f815837 Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 --- 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 4acc26e112f003c23f2997f98e0e84e1875c37b1 Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 --- 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 1f7fb6f953b1714d574181e6ae6b7b281288c0de Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 f1594502b2627691bf519fe163e655a3d8755e4f Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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= 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 4980bd625c8eab2240e7e754f2b7be99ab679fcb Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 +#include #include #include #include @@ -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 c42651fe738f2ce0740016fcc885bb79a1909021 Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 93577e9474de..5255251448d6 100644 --- a/tools/hciattach.h +++ b/tools/hciattach.h @@ -65,7 +65,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 c3e7808efa573974bf7d7d5fb08766b140dbe8f3 Mon Sep 17 00:00:00 2001 From: Kamal Negi 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 --- 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;(itag_len && (i*3 + 2) 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 e435ae1aa83440aaee7833c8ebce438065168f76 Mon Sep 17 00:00:00 2001 From: Rupesh Tatiya 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 --- 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 f09f6d7675062407b904fb85348249b09425bbed Mon Sep 17 00:00:00 2001 From: Anantha Krishnan 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 96e0dfef4073e19927d1a5c3e45b91fc0a7a3827 Mon Sep 17 00:00:00 2001 From: Kamal Negi 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 --- 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 30168b14444dad98babe8e0dc4474bb1947e60e6 Mon Sep 17 00:00:00 2001 From: Dibyendu Roy 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 --- 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 ed48ba0a9558ea9e0025210ade514e86579e0801 Mon Sep 17 00:00:00 2001 From: Dibyendu Roy 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 73225f2554d77df772d026475d27413161f5aaa6 Mon Sep 17 00:00:00 2001 From: Dibyendu Roy 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 cba902ee7f1d78e8b46d0ce7e2243b2d9dddf063 Mon Sep 17 00:00:00 2001 From: Kamal Negi 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 --- 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;