1982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* 2982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * 3982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Copyright (c) 2013, The Linux Foundation. All rights reserved. 4982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Not a Contribution. 5982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * 6982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Copyright 2012 The Android Open Source Project 7982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * 8982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Licensed under the Apache License, Version 2.0 (the "License"); you 9982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * may not use this file except in compliance with the License. You may 10982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * obtain a copy of the License at 11982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * 12982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * http://www.apache.org/licenses/LICENSE-2.0 13982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * 14982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Unless required by applicable law or agreed to in writing, software 15982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * distributed under the License is distributed on an "AS IS" BASIS, 16982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 17982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * implied. See the License for the specific language governing 18982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * permissions and limitations under the License. 19982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * 20982edd19a092114c479134cb16e0af54730edf1fPrashant Malani */ 21982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 22982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/****************************************************************************** 23982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * 24982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Filename: hw_ar3k.c 25982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * 26982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Description: Contains controller-specific functions, like 27982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * firmware patch download 28982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * low power mode operations 29982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * 30982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ******************************************************************************/ 31982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#ifdef __cplusplus 32982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniextern "C" { 33982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#endif 34982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 35982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define LOG_TAG "bt_vendor" 36982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 37982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <sys/socket.h> 38982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <utils/Log.h> 39982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <sys/types.h> 40982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <sys/stat.h> 41982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <signal.h> 42982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <time.h> 43982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <errno.h> 44982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <fcntl.h> 45982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <dirent.h> 46982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <ctype.h> 47982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <cutils/properties.h> 48982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <stdlib.h> 49982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <termios.h> 50982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include <string.h> 51982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 52982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include "bt_hci_bdroid.h" 53982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include "hci_uart.h" 54982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#include "hw_ar3k.h" 55982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 56982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/****************************************************************************** 57982edd19a092114c479134cb16e0af54730edf1fPrashant Malani** Variables 58982edd19a092114c479134cb16e0af54730edf1fPrashant Malani******************************************************************************/ 59982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint cbstat = 0; 60982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PATCH_LOC_STRING_LEN 8 61982edd19a092114c479134cb16e0af54730edf1fPrashant Malanichar ARbyte[3]; 62982edd19a092114c479134cb16e0af54730edf1fPrashant Malanichar ARptr[MAX_PATCH_CMD + 1]; 63982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint byte_cnt; 64982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint patch_count = 0; 65982edd19a092114c479134cb16e0af54730edf1fPrashant Malanichar patch_loc[PATCH_LOC_STRING_LEN + 1]; 66982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint PSCounter=0; 67982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 68982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniuint32_t dev_type = 0; 69982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniuint32_t rom_version = 0; 70982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniuint32_t build_version = 0; 71982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 72982edd19a092114c479134cb16e0af54730edf1fPrashant Malanichar patch_file[PATH_MAX]; 73982edd19a092114c479134cb16e0af54730edf1fPrashant Malanichar ps_file[PATH_MAX]; 74982edd19a092114c479134cb16e0af54730edf1fPrashant MalaniFILE *stream; 75982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint tag_count=0; 76982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 77982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* for friendly debugging outpout string */ 78982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic char *lpm_mode[] = { 79982edd19a092114c479134cb16e0af54730edf1fPrashant Malani "UNKNOWN", 80982edd19a092114c479134cb16e0af54730edf1fPrashant Malani "disabled", 81982edd19a092114c479134cb16e0af54730edf1fPrashant Malani "enabled" 82982edd19a092114c479134cb16e0af54730edf1fPrashant Malani}; 83982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 84982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic char *lpm_state[] = { 85982edd19a092114c479134cb16e0af54730edf1fPrashant Malani "UNKNOWN", 86982edd19a092114c479134cb16e0af54730edf1fPrashant Malani "de-asserted", 87982edd19a092114c479134cb16e0af54730edf1fPrashant Malani "asserted" 88982edd19a092114c479134cb16e0af54730edf1fPrashant Malani}; 89982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 90982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic uint8_t upio_state[UPIO_MAX_COUNT]; 91982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistruct ps_cfg_entry ps_list[MAX_TAGS]; 92982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 93982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_EVENT_LEN 100 94982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 95982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#ifdef __cplusplus 96982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 97982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#endif 98982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 99982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/***************************************************************************** 100982edd19a092114c479134cb16e0af54730edf1fPrashant Malani** Functions 101982edd19a092114c479134cb16e0af54730edf1fPrashant Malani*****************************************************************************/ 102982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 103982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint is_bt_soc_ath() { 104982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int ret = 0; 105982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char bt_soc_type[PROPERTY_VALUE_MAX]; 106982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL); 107982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (ret != 0) { 108982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type); 109982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!strncasecmp(bt_soc_type, "ath3k", sizeof("ath3k"))) 110982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 1; 111982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } else { 112982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("qcom.bluetooth.soc not set, so using default.\n"); 113982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 114982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 115982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 116982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 117982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 118982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* 119982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Send HCI command and wait for command complete event. 120982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * The event buffer has to be freed by the caller. 121982edd19a092114c479134cb16e0af54730edf1fPrashant Malani */ 122982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 123982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int send_hci_cmd_sync(int dev, uint8_t *cmd, int len, uint8_t **event) 124982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 125982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int err; 126982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *hci_event; 127982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t pkt_type = HCI_COMMAND_PKT; 128982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 129982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (len == 0) 130982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return len; 131982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 132982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write(dev, &pkt_type, 1) != 1) 133982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 134982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write(dev, (unsigned char *)cmd, len) != len) 135982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 136982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 137982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_event = (uint8_t *)malloc(PS_EVENT_LEN); 138982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!hci_event) 139982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -ENOMEM; 140982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 141982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = read_hci_event(dev, (unsigned char *)hci_event, PS_EVENT_LEN); 142982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err > 0) { 143982edd19a092114c479134cb16e0af54730edf1fPrashant Malani *event = hci_event; 144982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } else { 145982edd19a092114c479134cb16e0af54730edf1fPrashant Malani free(hci_event); 146982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 147982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 148982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 149982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return len; 150982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 151982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 152982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic void convert_bdaddr(char *str_bdaddr, char *bdaddr) 153982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 154982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char bdbyte[3]; 155982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char *str_byte = str_bdaddr; 156982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int i, j; 157982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int colon_present = 0; 158982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 159982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (strstr(str_bdaddr, ":")) 160982edd19a092114c479134cb16e0af54730edf1fPrashant Malani colon_present = 1; 161982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 162982edd19a092114c479134cb16e0af54730edf1fPrashant Malani bdbyte[2] = '\0'; 163982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 164982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Reverse the BDADDR to LSB first */ 165982edd19a092114c479134cb16e0af54730edf1fPrashant Malani for (i = 0, j = 5; i < 6; i++, j--) { 166982edd19a092114c479134cb16e0af54730edf1fPrashant Malani bdbyte[0] = str_byte[0]; 167982edd19a092114c479134cb16e0af54730edf1fPrashant Malani bdbyte[1] = str_byte[1]; 168982edd19a092114c479134cb16e0af54730edf1fPrashant Malani bdaddr[j] = strtol(bdbyte, NULL, 16); 169982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 170982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (colon_present == 1) 171982edd19a092114c479134cb16e0af54730edf1fPrashant Malani str_byte += 3; 172982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 173982edd19a092114c479134cb16e0af54730edf1fPrashant Malani str_byte += 2; 174982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 175982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 176982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 177982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int uart_speed(int s) 178982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 179982edd19a092114c479134cb16e0af54730edf1fPrashant Malani switch (s) { 180982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 9600: 181982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B9600; 182982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 19200: 183982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B19200; 184982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 38400: 185982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B38400; 186982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 57600: 187982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B57600; 188982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 115200: 189982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B115200; 190982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 230400: 191982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B230400; 192982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 460800: 193982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B460800; 194982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 500000: 195982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B500000; 196982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 576000: 197982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B576000; 198982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 921600: 199982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B921600; 200982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 1000000: 201982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B1000000; 202982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 1152000: 203982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B1152000; 204982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 1500000: 205982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B1500000; 206982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 2000000: 207982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B2000000; 208982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#ifdef B2500000 209982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 2500000: 210982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B2500000; 211982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#endif 212982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#ifdef B3000000 213982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 3000000: 214982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B3000000; 215982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#endif 216982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#ifdef B3500000 217982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 3500000: 218982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B3500000; 219982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#endif 220982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#ifdef B4000000 221982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case 4000000: 222982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B4000000; 223982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#endif 224982edd19a092114c479134cb16e0af54730edf1fPrashant Malani default: 225982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return B57600; 226982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 227982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 228982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 229982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint set_speed(int fd, struct termios *ti, int speed) 230982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 231982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (cfsetospeed(ti, uart_speed(speed)) < 0) 232982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -errno; 233982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 234982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (cfsetispeed(ti, uart_speed(speed)) < 0) 235982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -errno; 236982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 237982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (tcsetattr(fd, TCSANOW, ti) < 0) 238982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -errno; 239982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 240982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 241982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 242982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 243982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic void load_hci_ps_hdr(uint8_t *cmd, uint8_t ps_op, int len, int index) 244982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 245982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_command_hdr *ch = (void *)cmd; 246982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 247982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 248982edd19a092114c479134cb16e0af54730edf1fPrashant Malani HCI_PS_CMD_OCF)); 249982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->plen = len + PS_HDR_LEN; 250982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd += HCI_COMMAND_HDR_SIZE; 251982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 252982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[0] = ps_op; 253982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[1] = index; 254982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[2] = index >> 8; 255982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[3] = len; 256982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 257982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 258982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 259982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int read_ps_event(uint8_t *event, uint16_t ocf) 260982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 261982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_event_hdr *eh; 262982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint16_t opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, ocf)); 263982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 264982edd19a092114c479134cb16e0af54730edf1fPrashant Malani event++; 265982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 266982edd19a092114c479134cb16e0af54730edf1fPrashant Malani eh = (void *)event; 267982edd19a092114c479134cb16e0af54730edf1fPrashant Malani event += HCI_EVENT_HDR_SIZE; 268982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 269982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (eh->evt == EVT_CMD_COMPLETE) { 270982edd19a092114c479134cb16e0af54730edf1fPrashant Malani evt_cmd_complete *cc = (void *)event; 271982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 272982edd19a092114c479134cb16e0af54730edf1fPrashant Malani event += EVT_CMD_COMPLETE_SIZE; 273982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 274982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (cc->opcode == opcode && event[0] == HCI_EV_SUCCESS) 275982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 276982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 277982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 278982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 279982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 280982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 281982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 282982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 283982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_WRITE 1 284982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_RESET 2 285982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define WRITE_PATCH 8 286982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define ENABLE_PATCH 11 287982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 288982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define HCI_PS_CMD_HDR_LEN 7 289982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 290982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int write_cmd(int fd, uint8_t *buffer, int len) 291982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 292982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *event; 293982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int err; 294982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 295982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = send_hci_cmd_sync(fd, buffer, len, &event); 296982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 297982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 298982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 299982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = read_ps_event(event, HCI_PS_CMD_OCF); 300982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 301982edd19a092114c479134cb16e0af54730edf1fPrashant Malani free(event); 302982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 303982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 304982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 305982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 306982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_RESET_PARAM_LEN 6 307982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_RESET_CMD_LEN (HCI_PS_CMD_HDR_LEN + PS_RESET_PARAM_LEN) 308982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 309982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_ID_MASK 0xFF 310982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 311982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* Sends PS commands using vendor specficic HCI commands */ 312982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int write_ps_cmd(int fd, uint8_t opcode, uint32_t ps_param) 313982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 314982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t cmd[HCI_MAX_CMD_SIZE]; 315982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint32_t i; 316982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 317982edd19a092114c479134cb16e0af54730edf1fPrashant Malani switch (opcode) { 318982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case ENABLE_PATCH: 319982edd19a092114c479134cb16e0af54730edf1fPrashant Malani load_hci_ps_hdr(cmd, opcode, 0, 0x00); 320982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 321982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write_cmd(fd, cmd, HCI_PS_CMD_HDR_LEN) < 0) 322982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 323982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 324982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 325982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case PS_RESET: 326982edd19a092114c479134cb16e0af54730edf1fPrashant Malani load_hci_ps_hdr(cmd, opcode, PS_RESET_PARAM_LEN, 0x00); 327982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 328982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[7] = 0x00; 329982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[PS_RESET_CMD_LEN - 2] = ps_param & PS_ID_MASK; 330982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[PS_RESET_CMD_LEN - 1] = (ps_param >> 8) & PS_ID_MASK; 331982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 332982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write_cmd(fd, cmd, PS_RESET_CMD_LEN) < 0) 333982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 334982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 335982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 336982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case PS_WRITE: 337982edd19a092114c479134cb16e0af54730edf1fPrashant Malani for (i = 0; i < ps_param; i++) { 338982edd19a092114c479134cb16e0af54730edf1fPrashant Malani load_hci_ps_hdr(cmd, opcode, ps_list[i].len, 339982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ps_list[i].id); 340982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 341982edd19a092114c479134cb16e0af54730edf1fPrashant Malani memcpy(&cmd[HCI_PS_CMD_HDR_LEN], ps_list[i].data, 342982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ps_list[i].len); 343982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 344982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write_cmd(fd, cmd, ps_list[i].len + 345982edd19a092114c479134cb16e0af54730edf1fPrashant Malani HCI_PS_CMD_HDR_LEN) < 0) 346982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 347982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 348982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 349982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 350982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 351982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 352982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 353982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 354982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_ASIC_FILE "PS_ASIC.pst" 355982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_FPGA_FILE "PS_FPGA.pst" 356982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define MAXPATHLEN 4096 357982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic void get_ps_file_name(uint32_t devtype, uint32_t rom_version,char *path) 358982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 359982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char *filename; 360982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 361982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (devtype == 0xdeadc0de) 362982edd19a092114c479134cb16e0af54730edf1fPrashant Malani filename = PS_ASIC_FILE; 363982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 364982edd19a092114c479134cb16e0af54730edf1fPrashant Malani filename = PS_FPGA_FILE; 365982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 366982edd19a092114c479134cb16e0af54730edf1fPrashant Malani snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, filename); 367982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 368982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 369982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PATCH_FILE "RamPatch.txt" 370982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define FPGA_ROM_VERSION 0x99999999 371982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define ROM_DEV_TYPE 0xdeadc0de 372982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 373982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic void get_patch_file_name(uint32_t dev_type, uint32_t rom_version, 374982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint32_t build_version, char *path) 375982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 376982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (rom_version == FPGA_ROM_VERSION && dev_type != ROM_DEV_TYPE 377982edd19a092114c479134cb16e0af54730edf1fPrashant Malani &&dev_type != 0 && build_version == 1) 378982edd19a092114c479134cb16e0af54730edf1fPrashant Malani path[0] = '\0'; 379982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 380982edd19a092114c479134cb16e0af54730edf1fPrashant Malani snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, PATCH_FILE); 381982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 382982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 383982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int set_cntrlr_baud(int fd, int speed) 384982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 385982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int baud; 386982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct timespec tm = { 0, 500000}; 387982edd19a092114c479134cb16e0af54730edf1fPrashant Malani unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE]; 388982edd19a092114c479134cb16e0af54730edf1fPrashant Malani unsigned char *ptr = cmd + 1; 389982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_command_hdr *ch = (void *)ptr; 390982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 391982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[0] = HCI_COMMAND_PKT; 392982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 393982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* set controller baud rate to user specified value */ 394982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr = cmd + 1; 395982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 396982edd19a092114c479134cb16e0af54730edf1fPrashant Malani HCI_CHG_BAUD_CMD_OCF)); 397982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->plen = 2; 398982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr += HCI_COMMAND_HDR_SIZE; 399982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 400982edd19a092114c479134cb16e0af54730edf1fPrashant Malani baud = speed/100; 401982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[0] = (char)baud; 402982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[1] = (char)(baud >> 8); 403982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 404982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write(fd, cmd, WRITE_BAUD_CMD_LEN) != WRITE_BAUD_CMD_LEN) { 405982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Failed to write change baud rate command"); 406982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -ETIMEDOUT; 407982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 408982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 409982edd19a092114c479134cb16e0af54730edf1fPrashant Malani nanosleep(&tm, NULL); 410982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 411982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) 412982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -ETIMEDOUT; 413982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 414982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 415982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 416982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 417982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_UNDEF 0 418982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_ID 1 419982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_LEN 2 420982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_DATA 3 421982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 422982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_MAX_LEN 500 423982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define LINE_SIZE_MAX (PS_MAX_LEN * 2) 424982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define ENTRY_PER_LINE 16 425982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 426982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define __check_comment(buf) (((buf)[0] == '/') && ((buf)[1] == '/')) 427982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define __skip_space(str) while (*(str) == ' ') ((str)++) 428982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 429982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 430982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define __is_delim(ch) ((ch) == ':') 431982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define MAX_PREAMBLE_LEN 4 432982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 433982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* Parse PS entry preamble of format [X:X] for main type and subtype */ 434982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int get_ps_type(char *ptr, int index, char *type, char *sub_type) 435982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 436982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int i; 437982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int delim = FALSE; 438982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 439982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (index > MAX_PREAMBLE_LEN) 440982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 441982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 442982edd19a092114c479134cb16e0af54730edf1fPrashant Malani for (i = 1; i < index; i++) { 443982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (__is_delim(ptr[i])) { 444982edd19a092114c479134cb16e0af54730edf1fPrashant Malani delim = TRUE; 445982edd19a092114c479134cb16e0af54730edf1fPrashant Malani continue; 446982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 447982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 448982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (isalpha(ptr[i])) { 449982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (delim == FALSE) 450982edd19a092114c479134cb16e0af54730edf1fPrashant Malani (*type) = toupper(ptr[i]); 451982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 452982edd19a092114c479134cb16e0af54730edf1fPrashant Malani (*sub_type) = toupper(ptr[i]); 453982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 454982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 455982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 456982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 457982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 458982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 459982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define ARRAY 'A' 460982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define STRING 'S' 461982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define DECIMAL 'D' 462982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define BINARY 'B' 463982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 464982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_HEX 0 465982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_DEC 1 466982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 467982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int get_input_format(char *buf, struct ps_entry_type *format) 468982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 469982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char *ptr = NULL; 470982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char type = '\0'; 471982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char sub_type = '\0'; 472982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 473982edd19a092114c479134cb16e0af54730edf1fPrashant Malani format->type = PS_HEX; 474982edd19a092114c479134cb16e0af54730edf1fPrashant Malani format->array = TRUE; 475982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 476982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (strstr(buf, "[") != buf) 477982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 478982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 479982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr = strstr(buf, "]"); 480982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!ptr) 481982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 482982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 483982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (get_ps_type(buf, ptr - buf, &type, &sub_type) < 0) 484982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 485982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 486982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Check is data type is of array */ 487982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (type == ARRAY || sub_type == ARRAY) 488982edd19a092114c479134cb16e0af54730edf1fPrashant Malani format->array = TRUE; 489982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 490982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (type == STRING || sub_type == STRING) 491982edd19a092114c479134cb16e0af54730edf1fPrashant Malani format->array = FALSE; 492982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 493982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (type == DECIMAL || type == BINARY) 494982edd19a092114c479134cb16e0af54730edf1fPrashant Malani format->type = PS_DEC; 495982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 496982edd19a092114c479134cb16e0af54730edf1fPrashant Malani format->type = PS_HEX; 497982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 498982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 499982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 500982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 501982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 502982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 503982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define UNDEFINED 0xFFFF 504982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 505982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic unsigned int read_data_in_section(char *buf, struct ps_entry_type type) 506982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 507982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char *ptr = buf; 508982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 509982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!buf) 510982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return UNDEFINED; 511982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 512982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (buf == strstr(buf, "[")) { 513982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr = strstr(buf, "]"); 514982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!ptr) 515982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return UNDEFINED; 516982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 517982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr++; 518982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 519982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 520982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (type.type == PS_HEX && type.array != TRUE) 521982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return strtol(ptr, NULL, 16); 522982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 523982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return UNDEFINED; 524982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 525982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 526982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 527982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* Read PS entries as string, convert and add to Hex array */ 528982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic void update_tag_data(struct ps_cfg_entry *tag, 529982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct tag_info *info, const char *ptr) 530982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 531982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char buf[3]; 532982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 533982edd19a092114c479134cb16e0af54730edf1fPrashant Malani buf[2] = '\0'; 534982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 535982edd19a092114c479134cb16e0af54730edf1fPrashant Malani strlcpy(buf, &ptr[info->char_cnt],sizeof(buf)); 536982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tag->data[info->byte_count] = strtol(buf, NULL, 16); 537982edd19a092114c479134cb16e0af54730edf1fPrashant Malani info->char_cnt += 3; 538982edd19a092114c479134cb16e0af54730edf1fPrashant Malani info->byte_count++; 539982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 540982edd19a092114c479134cb16e0af54730edf1fPrashant Malani strlcpy(buf, &ptr[info->char_cnt], sizeof(buf)); 541982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tag->data[info->byte_count] = strtol(buf, NULL, 16); 542982edd19a092114c479134cb16e0af54730edf1fPrashant Malani info->char_cnt += 3; 543982edd19a092114c479134cb16e0af54730edf1fPrashant Malani info->byte_count++; 544982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 545982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 546982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic inline int update_char_count(const char *buf) 547982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 548982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char *end_ptr; 549982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 550982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (strstr(buf, "[") == buf) { 551982edd19a092114c479134cb16e0af54730edf1fPrashant Malani end_ptr = strstr(buf, "]"); 552982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!end_ptr) 553982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 554982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 555982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return(end_ptr - buf) + 1; 556982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 557982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 558982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 559982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 560982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 561982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_HEX 0 562982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_DEC 1 563982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 564982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int ath_parse_ps(FILE *stream) 565982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 566982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char buf[LINE_SIZE_MAX + 1]; 567982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char *ptr; 568982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t tag_cnt = 0; 569982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int16_t byte_count = 0; 570982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct ps_entry_type format; 571982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct tag_info status = { 0, 0, 0, 0}; 572982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 573982edd19a092114c479134cb16e0af54730edf1fPrashant Malani do { 574982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int read_count; 575982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct ps_cfg_entry *tag; 576982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 577982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr = fgets(buf, LINE_SIZE_MAX, stream); 578982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!ptr) 579982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 580982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 581982edd19a092114c479134cb16e0af54730edf1fPrashant Malani __skip_space(ptr); 582982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (__check_comment(ptr)) 583982edd19a092114c479134cb16e0af54730edf1fPrashant Malani continue; 584982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 585982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Lines with a '#' will be followed by new PS entry */ 586982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (ptr == strstr(ptr, "#")) { 587982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (status.section != PS_UNDEF) { 588982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 589982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } else { 590982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status.section = PS_ID; 591982edd19a092114c479134cb16e0af54730edf1fPrashant Malani continue; 592982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 593982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 594982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 595982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tag = &ps_list[tag_cnt]; 596982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 597982edd19a092114c479134cb16e0af54730edf1fPrashant Malani switch (status.section) { 598982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case PS_ID: 599982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (get_input_format(ptr, &format) < 0) 600982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 601982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 602982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tag->id = read_data_in_section(ptr, format); 603982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status.section = PS_LEN; 604982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 605982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 606982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case PS_LEN: 607982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (get_input_format(ptr, &format) < 0) 608982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 609982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 610982edd19a092114c479134cb16e0af54730edf1fPrashant Malani byte_count = read_data_in_section(ptr, format); 611982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (byte_count > PS_MAX_LEN) 612982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 613982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 614982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tag->len = byte_count; 615982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tag->data = (uint8_t *)malloc(byte_count); 616982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 617982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status.section = PS_DATA; 618982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status.line_count = 0; 619982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 620982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 621982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case PS_DATA: 622982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (status.line_count == 0) 623982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (get_input_format(ptr, &format) < 0) 624982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 625982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 626982edd19a092114c479134cb16e0af54730edf1fPrashant Malani __skip_space(ptr); 627982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 628982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status.char_cnt = update_char_count(ptr); 629982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 630982edd19a092114c479134cb16e0af54730edf1fPrashant Malani read_count = (byte_count > ENTRY_PER_LINE) ? 631982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ENTRY_PER_LINE : byte_count; 632982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 633982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (format.type == PS_HEX && format.array == TRUE) { 634982edd19a092114c479134cb16e0af54730edf1fPrashant Malani while (read_count > 0) { 635982edd19a092114c479134cb16e0af54730edf1fPrashant Malani update_tag_data(tag, &status, ptr); 636982edd19a092114c479134cb16e0af54730edf1fPrashant Malani read_count -= 2; 637982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 638982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 639982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (byte_count > ENTRY_PER_LINE) 640982edd19a092114c479134cb16e0af54730edf1fPrashant Malani byte_count -= ENTRY_PER_LINE; 641982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 642982edd19a092114c479134cb16e0af54730edf1fPrashant Malani byte_count = 0; 643982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 644982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 645982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status.line_count++; 646982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 647982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (byte_count == 0) 648982edd19a092114c479134cb16e0af54730edf1fPrashant Malani memset(&status, 0x00, sizeof(struct tag_info)); 649982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 650982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (status.section == PS_UNDEF) 651982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tag_cnt++; 652982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 653982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (tag_cnt == MAX_TAGS) 654982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -EILSEQ; 655982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 656982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 657982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } while (ptr); 658982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 659982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return tag_cnt; 660982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 661982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 662982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_RAM_SIZE 2048 663982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 664982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int ps_config_download(int fd, int tag_count) 665982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 666982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write_ps_cmd(fd, PS_RESET, PS_RAM_SIZE) < 0) 667982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 668982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 669982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (tag_count > 0) 670982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write_ps_cmd(fd, PS_WRITE, tag_count) < 0) 671982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 672982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 673982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 674982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 675982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int write_bdaddr(int pConfig, char *bdaddr) 676982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 677982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *event; 678982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int err; 679982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t cmd[13]; 680982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *ptr = cmd; 681982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_command_hdr *ch = (void *)cmd; 682982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 683982edd19a092114c479134cb16e0af54730edf1fPrashant Malani memset(cmd, 0, sizeof(cmd)); 684982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 685982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 686982edd19a092114c479134cb16e0af54730edf1fPrashant Malani HCI_PS_CMD_OCF)); 687982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->plen = 10; 688982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr += HCI_COMMAND_HDR_SIZE; 689982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 690982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[0] = 0x01; 691982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[1] = 0x01; 692982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[2] = 0x00; 693982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[3] = 0x06; 694982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 695982edd19a092114c479134cb16e0af54730edf1fPrashant Malani convert_bdaddr(bdaddr, (char *)&ptr[4]); 696982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 697982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event); 698982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 699982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 700982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 701982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = read_ps_event(event, HCI_PS_CMD_OCF); 702982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 703982edd19a092114c479134cb16e0af54730edf1fPrashant Malani free(event); 704982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 705982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 706982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 707982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 708982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic void write_bdaddr_from_file(int rom_version, int fd) 709982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 710982edd19a092114c479134cb16e0af54730edf1fPrashant Malani FILE *stream; 711982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char bdaddr[PATH_MAX]; 712982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char bdaddr_file[PATH_MAX]; 713982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 714982edd19a092114c479134cb16e0af54730edf1fPrashant Malani snprintf(bdaddr_file, MAXPATHLEN, "%s%x/%s", 715982edd19a092114c479134cb16e0af54730edf1fPrashant Malani FW_PATH, rom_version, BDADDR_FILE); 716982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 717982edd19a092114c479134cb16e0af54730edf1fPrashant Malani stream = fopen(bdaddr_file, "r"); 718982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!stream) 719982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return; 720982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 721982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (fgets(bdaddr, PATH_MAX - 1, stream)) 722982edd19a092114c479134cb16e0af54730edf1fPrashant Malani write_bdaddr(fd, bdaddr); 723982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 724982edd19a092114c479134cb16e0af54730edf1fPrashant Malani fclose(stream); 725982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 726982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 727982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define HCI_EVT_CMD_CMPL_OPCODE 3 728982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5 729982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 730982edd19a092114c479134cb16e0af54730edf1fPrashant Malanivoid baswap(bdaddr_t *dst, const bdaddr_t *src) 731982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 732982edd19a092114c479134cb16e0af54730edf1fPrashant Malani register unsigned char *d = (unsigned char *) dst; 733982edd19a092114c479134cb16e0af54730edf1fPrashant Malani register const unsigned char *s = (const unsigned char *) src; 734982edd19a092114c479134cb16e0af54730edf1fPrashant Malani register int i; 735982edd19a092114c479134cb16e0af54730edf1fPrashant Malani for (i = 0; i < 6; i++) 736982edd19a092114c479134cb16e0af54730edf1fPrashant Malani d[i] = s[5-i]; 737982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 738982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 739982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 740982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint str2ba(const char *str, bdaddr_t *ba) 741982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 742982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t b[6]; 743982edd19a092114c479134cb16e0af54730edf1fPrashant Malani const char *ptr = str; 744982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int i; 745982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 746982edd19a092114c479134cb16e0af54730edf1fPrashant Malani for (i = 0; i < 6; i++) { 747982edd19a092114c479134cb16e0af54730edf1fPrashant Malani b[i] = (uint8_t) strtol(ptr, NULL, 16); 748982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr = strchr(ptr, ':'); 749982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (i != 5 && !ptr) 750982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr = ":00:00:00:00:00"; 751982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr++; 752982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 753982edd19a092114c479134cb16e0af54730edf1fPrashant Malani baswap(ba, (bdaddr_t *) b); 754982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 755982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 756982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 757982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define DEV_REGISTER 0x4FFC 758982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define GET_DEV_TYPE_OCF 0x05 759982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 760982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int get_device_type(int dev, uint32_t *code) 761982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 762982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t cmd[8] = {0}; 763982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *event; 764982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint32_t reg; 765982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int err; 766982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *ptr = cmd; 767982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_command_hdr *ch = (void *)cmd; 768982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 769982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 770982edd19a092114c479134cb16e0af54730edf1fPrashant Malani GET_DEV_TYPE_OCF)); 771982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->plen = 5; 772982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr += HCI_COMMAND_HDR_SIZE; 773982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 774982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[0] = (uint8_t)DEV_REGISTER; 775982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[1] = (uint8_t)DEV_REGISTER >> 8; 776982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[2] = (uint8_t)DEV_REGISTER >> 16; 777982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[3] = (uint8_t)DEV_REGISTER >> 24; 778982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[4] = 0x04; 779982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 780982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event); 781982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 782982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 783982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 784982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = read_ps_event(event, GET_DEV_TYPE_OCF); 785982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 786982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto cleanup; 787982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 788982edd19a092114c479134cb16e0af54730edf1fPrashant Malani reg = event[10]; 789982edd19a092114c479134cb16e0af54730edf1fPrashant Malani reg = (reg << 8) | event[9]; 790982edd19a092114c479134cb16e0af54730edf1fPrashant Malani reg = (reg << 8) | event[8]; 791982edd19a092114c479134cb16e0af54730edf1fPrashant Malani reg = (reg << 8) | event[7]; 792982edd19a092114c479134cb16e0af54730edf1fPrashant Malani *code = reg; 793982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 794982edd19a092114c479134cb16e0af54730edf1fPrashant Malanicleanup: 795982edd19a092114c479134cb16e0af54730edf1fPrashant Malani free(event); 796982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 797982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 798982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 799982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 800982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define GET_VERSION_OCF 0x1E 801982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 802982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int read_ath3k_version(int pConfig, uint32_t *rom_version, 803982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint32_t *build_version) 804982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 805982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t cmd[3] = {0}; 806982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *event; 807982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int err; 808982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int status; 809982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_command_hdr *ch = (void *)cmd; 810982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 811982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 812982edd19a092114c479134cb16e0af54730edf1fPrashant Malani GET_VERSION_OCF)); 813982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->plen = 0; 814982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 815982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event); 816982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 817982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 818982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 819982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = read_ps_event(event, GET_VERSION_OCF); 820982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 821982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto cleanup; 822982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 823982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status = event[10]; 824982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status = (status << 8) | event[9]; 825982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status = (status << 8) | event[8]; 826982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status = (status << 8) | event[7]; 827982edd19a092114c479134cb16e0af54730edf1fPrashant Malani *rom_version = status; 828982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 829982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status = event[14]; 830982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status = (status << 8) | event[13]; 831982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status = (status << 8) | event[12]; 832982edd19a092114c479134cb16e0af54730edf1fPrashant Malani status = (status << 8) | event[11]; 833982edd19a092114c479134cb16e0af54730edf1fPrashant Malani *build_version = status; 834982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 835982edd19a092114c479134cb16e0af54730edf1fPrashant Malanicleanup: 836982edd19a092114c479134cb16e0af54730edf1fPrashant Malani free(event); 837982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 838982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 839982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 840982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 841982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define VERIFY_CRC 9 842982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PS_REGION 1 843982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PATCH_REGION 2 844982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 845982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int get_ath3k_crc(int dev) 846982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 847982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t cmd[7] = {0}; 848982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *event; 849982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int err; 850982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 851982edd19a092114c479134cb16e0af54730edf1fPrashant Malani load_hci_ps_hdr(cmd, VERIFY_CRC, 0, PS_REGION | PATCH_REGION); 852982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 853982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event); 854982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 855982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 856982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Send error code if CRC check patched */ 857982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (read_ps_event(event, HCI_PS_CMD_OCF) >= 0) 858982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -EILSEQ; 859982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 860982edd19a092114c479134cb16e0af54730edf1fPrashant Malani free(event); 861982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 862982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 863982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 864982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 865982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define SET_PATCH_RAM_ID 0x0D 866982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define SET_PATCH_RAM_CMD_SIZE 11 867982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define ADDRESS_LEN 4 868982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int set_patch_ram(int dev, char *patch_loc, int len) 869982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 870982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int err; 871982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t cmd[20] = {0}; 872982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int i, j; 873982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char loc_byte[3]; 874982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *event; 875982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t *loc_ptr = &cmd[7]; 876982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 877982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!patch_loc) 878982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 879982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 880982edd19a092114c479134cb16e0af54730edf1fPrashant Malani loc_byte[2] = '\0'; 881982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 882982edd19a092114c479134cb16e0af54730edf1fPrashant Malani load_hci_ps_hdr(cmd, SET_PATCH_RAM_ID, ADDRESS_LEN, 0); 883982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 884982edd19a092114c479134cb16e0af54730edf1fPrashant Malani for (i = 0, j = 3; i < 4; i++, j--) { 885982edd19a092114c479134cb16e0af54730edf1fPrashant Malani loc_byte[0] = patch_loc[0]; 886982edd19a092114c479134cb16e0af54730edf1fPrashant Malani loc_byte[1] = patch_loc[1]; 887982edd19a092114c479134cb16e0af54730edf1fPrashant Malani loc_ptr[j] = strtol(loc_byte, NULL, 16); 888982edd19a092114c479134cb16e0af54730edf1fPrashant Malani patch_loc += 2; 889982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 890982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 891982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = send_hci_cmd_sync(dev, cmd, SET_PATCH_RAM_CMD_SIZE, &event); 892982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 893982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 894982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 895982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = read_ps_event(event, HCI_PS_CMD_OCF); 896982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 897982edd19a092114c479134cb16e0af54730edf1fPrashant Malani free(event); 898982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 899982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 900982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 901982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 902982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PATCH_LOC_KEY "DA:" 903982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define PATCH_LOC_STRING_LEN 8 904982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int ps_patch_download(int fd, FILE *stream) 905982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 906982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char byte[3]; 907982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char ptr[MAX_PATCH_CMD + 1]; 908982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int byte_cnt; 909982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int patch_count = 0; 910982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char patch_loc[PATCH_LOC_STRING_LEN + 1]; 911982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 912982edd19a092114c479134cb16e0af54730edf1fPrashant Malani byte[2] = '\0'; 913982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 914982edd19a092114c479134cb16e0af54730edf1fPrashant Malani while (fgets(ptr, MAX_PATCH_CMD, stream)) { 915982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (strlen(ptr) <= 1) 916982edd19a092114c479134cb16e0af54730edf1fPrashant Malani continue; 917982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else if (strstr(ptr, PATCH_LOC_KEY) == ptr) { 918982edd19a092114c479134cb16e0af54730edf1fPrashant Malani strlcpy(patch_loc, &ptr[sizeof(PATCH_LOC_KEY) - 1], 919982edd19a092114c479134cb16e0af54730edf1fPrashant Malani PATCH_LOC_STRING_LEN); 920982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (set_patch_ram(fd, patch_loc, sizeof(patch_loc)) < 0) 921982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 922982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } else if (isxdigit(ptr[0])) 923982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 924982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 925982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 926982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 927982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 928982edd19a092114c479134cb16e0af54730edf1fPrashant Malani byte_cnt = strtol(ptr, NULL, 16); 929982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 930982edd19a092114c479134cb16e0af54730edf1fPrashant Malani while (byte_cnt > 0) { 931982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int i; 932982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t cmd[HCI_MAX_CMD_SIZE] = {0}; 933982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct patch_entry patch; 934982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 935982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (byte_cnt > MAX_PATCH_CMD) 936982edd19a092114c479134cb16e0af54730edf1fPrashant Malani patch.len = MAX_PATCH_CMD; 937982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 938982edd19a092114c479134cb16e0af54730edf1fPrashant Malani patch.len = byte_cnt; 939982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 940982edd19a092114c479134cb16e0af54730edf1fPrashant Malani for (i = 0; i < patch.len; i++) { 941982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!fgets(byte, 3, stream)) 942982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 943982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 944982edd19a092114c479134cb16e0af54730edf1fPrashant Malani patch.data[i] = strtoul(byte, NULL, 16); 945982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 946982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 947982edd19a092114c479134cb16e0af54730edf1fPrashant Malani load_hci_ps_hdr(cmd, WRITE_PATCH, patch.len, patch_count); 948982edd19a092114c479134cb16e0af54730edf1fPrashant Malani memcpy(&cmd[HCI_PS_CMD_HDR_LEN], patch.data, patch.len); 949982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 950982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write_cmd(fd, cmd, patch.len + HCI_PS_CMD_HDR_LEN) < 0) 951982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 952982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 953982edd19a092114c479134cb16e0af54730edf1fPrashant Malani patch_count++; 954982edd19a092114c479134cb16e0af54730edf1fPrashant Malani byte_cnt = byte_cnt - MAX_PATCH_CMD; 955982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 956982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 957982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write_ps_cmd(fd, ENABLE_PATCH, 0) < 0) 958982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 959982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 960982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return patch_count; 961982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 962982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 963982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int ath_ps_download(int fd) 964982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 965982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int err = 0; 966982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int tag_count; 967982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int patch_count = 0; 968982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint32_t rom_version = 0; 969982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint32_t build_version = 0; 970982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint32_t dev_type = 0; 971982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char patch_file[PATH_MAX]; 972982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char ps_file[PATH_MAX]; 973982edd19a092114c479134cb16e0af54730edf1fPrashant Malani FILE *stream; 974982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 975982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* 976982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Verfiy firmware version. depending on it select the PS 977982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * config file to download. 978982edd19a092114c479134cb16e0af54730edf1fPrashant Malani */ 979982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (get_device_type(fd, &dev_type) < 0) { 980982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -EILSEQ; 981982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto download_cmplete; 982982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 983982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 984982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (read_ath3k_version(fd, &rom_version, &build_version) < 0) { 985982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -EILSEQ; 986982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto download_cmplete; 987982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 988982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 989982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Do not download configuration if CRC passes */ 990982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (get_ath3k_crc(fd) < 0) { 991982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = 0; 992982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto download_cmplete; 993982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 994982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 995982edd19a092114c479134cb16e0af54730edf1fPrashant Malani get_ps_file_name(dev_type, rom_version, ps_file); 996982edd19a092114c479134cb16e0af54730edf1fPrashant Malani get_patch_file_name(dev_type, rom_version, build_version, patch_file); 997982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 998982edd19a092114c479134cb16e0af54730edf1fPrashant Malani stream = fopen(ps_file, "r"); 999982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!stream) { 1000982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("firmware file open error:%s, ver:%x\n",ps_file, rom_version); 1001982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (rom_version == 0x1020201) 1002982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = 0; 1003982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 1004982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -EILSEQ; 1005982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto download_cmplete; 1006982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1007982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tag_count = ath_parse_ps(stream); 1008982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1009982edd19a092114c479134cb16e0af54730edf1fPrashant Malani fclose(stream); 1010982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1011982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (tag_count < 0) { 1012982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -EILSEQ; 1013982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto download_cmplete; 1014982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1015982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1016982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* 1017982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * It is not necessary that Patch file be available, 1018982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * continue with PS Operations if patch file is not available. 1019982edd19a092114c479134cb16e0af54730edf1fPrashant Malani */ 1020982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (patch_file[0] == '\0') 1021982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = 0; 1022982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1023982edd19a092114c479134cb16e0af54730edf1fPrashant Malani stream = fopen(patch_file, "r"); 1024982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!stream) 1025982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = 0; 1026982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else { 1027982edd19a092114c479134cb16e0af54730edf1fPrashant Malani patch_count = ps_patch_download(fd, stream); 1028982edd19a092114c479134cb16e0af54730edf1fPrashant Malani fclose(stream); 1029982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1030982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (patch_count < 0) { 1031982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -EILSEQ; 1032982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto download_cmplete; 1033982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1034982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1035982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1036982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = ps_config_download(fd, tag_count); 1037982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1038982edd19a092114c479134cb16e0af54730edf1fPrashant Malanidownload_cmplete: 1039982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (!err) 1040982edd19a092114c479134cb16e0af54730edf1fPrashant Malani write_bdaddr_from_file(rom_version, fd); 1041982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1042982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 1043982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 1044982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1045982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti) 1046982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 1047982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI(" %s ", __FUNCTION__); 1048982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1049982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int r; 1050982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int err = 0; 1051982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct timespec tm = { 0, 500000}; 1052982edd19a092114c479134cb16e0af54730edf1fPrashant Malani unsigned char cmd[MAX_CMD_LEN] = {0}; 1053982edd19a092114c479134cb16e0af54730edf1fPrashant Malani unsigned char rsp[HCI_MAX_EVENT_SIZE]; 1054982edd19a092114c479134cb16e0af54730edf1fPrashant Malani unsigned char *ptr = cmd + 1; 1055982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_command_hdr *ch = (void *)ptr; 1056982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int flags = 0; 1057982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1058982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (ioctl(fd, TIOCMGET, &flags) < 0) { 1059982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("TIOCMGET failed in init\n"); 1060982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1061982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1062982edd19a092114c479134cb16e0af54730edf1fPrashant Malani flags |= TIOCM_RTS; 1063982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (ioctl(fd, TIOCMSET, &flags) < 0) { 1064982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("TIOCMSET failed in init: HW Flow-on error\n"); 1065982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1066982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1067982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1068982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* set both controller and host baud rate to maximum possible value */ 1069982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = set_cntrlr_baud(fd, speed); 1070982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("set_cntrlr_baud : ret:%d \n", err); 1071982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 1072982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 1073982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1074982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = set_speed(fd, ti, speed); 1075982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) { 1076982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Can't set required baud rate"); 1077982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 1078982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1079982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1080982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Download PS and patch */ 1081982edd19a092114c479134cb16e0af54730edf1fPrashant Malani r = ath_ps_download(fd); 1082982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (r < 0) { 1083982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Failed to Download configuration"); 1084982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -ETIMEDOUT; 1085982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto failed; 1086982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1087982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1088982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("ath_ps_download is done\n"); 1089982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1090982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[0] = HCI_COMMAND_PKT; 1091982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Write BDADDR */ 1092982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (bdaddr) { 1093982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 1094982edd19a092114c479134cb16e0af54730edf1fPrashant Malani HCI_PS_CMD_OCF)); 1095982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ch->plen = 10; 1096982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr += HCI_COMMAND_HDR_SIZE; 1097982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1098982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[0] = 0x01; 1099982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[1] = 0x01; 1100982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[2] = 0x00; 1101982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ptr[3] = 0x06; 1102982edd19a092114c479134cb16e0af54730edf1fPrashant Malani str2ba(bdaddr, (bdaddr_t *)(ptr + 4)); 1103982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1104982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write(fd, cmd, WRITE_BDADDR_CMD_LEN) != 1105982edd19a092114c479134cb16e0af54730edf1fPrashant Malani WRITE_BDADDR_CMD_LEN) { 1106982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Failed to write BD_ADDR command\n"); 1107982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -ETIMEDOUT; 1108982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto failed; 1109982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1110982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1111982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) { 1112982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Failed to set BD_ADDR\n"); 1113982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -ETIMEDOUT; 1114982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto failed; 1115982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1116982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1117982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1118982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Send HCI Reset */ 1119982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[1] = 0x03; 1120982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[2] = 0x0C; 1121982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cmd[3] = 0x00; 1122982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1123982edd19a092114c479134cb16e0af54730edf1fPrashant Malani r = write(fd, cmd, 4); 1124982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (r != 4) { 1125982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -ETIMEDOUT; 1126982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto failed; 1127982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1128982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1129982edd19a092114c479134cb16e0af54730edf1fPrashant Malani nanosleep(&tm, NULL); 1130982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) { 1131982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = -ETIMEDOUT; 1132982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto failed; 1133982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1134982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1135982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("HCI Reset is done\n"); 1136982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = set_cntrlr_baud(fd, speed); 1137982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) 1138982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("set_cntrlr_baud0:%d,%d\n", speed, err); 1139982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1140982edd19a092114c479134cb16e0af54730edf1fPrashant Malanifailed: 1141982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (err < 0) { 1142982edd19a092114c479134cb16e0af54730edf1fPrashant Malani set_cntrlr_baud(fd, init_speed); 1143982edd19a092114c479134cb16e0af54730edf1fPrashant Malani set_speed(fd, ti, init_speed); 1144982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1145982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1146982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return err; 1147982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1148982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 1149982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define BTPROTO_HCI 1 1150982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1151982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* Open HCI device. 1152982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Returns device descriptor (dd). */ 1153982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint hci_open_dev(int dev_id) 1154982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 1155982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct sockaddr_hci a; 1156982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int dd, err; 1157982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1158982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Create HCI socket */ 1159982edd19a092114c479134cb16e0af54730edf1fPrashant Malani dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 1160982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (dd < 0) 1161982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return dd; 1162982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1163982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* Bind socket to the HCI device */ 1164982edd19a092114c479134cb16e0af54730edf1fPrashant Malani memset(&a, 0, sizeof(a)); 1165982edd19a092114c479134cb16e0af54730edf1fPrashant Malani a.hci_family = AF_BLUETOOTH; 1166982edd19a092114c479134cb16e0af54730edf1fPrashant Malani a.hci_dev = dev_id; 1167982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (bind(dd, (struct sockaddr *) &a, sizeof(a)) < 0) 1168982edd19a092114c479134cb16e0af54730edf1fPrashant Malani goto failed; 1169982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1170982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return dd; 1171982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1172982edd19a092114c479134cb16e0af54730edf1fPrashant Malanifailed: 1173982edd19a092114c479134cb16e0af54730edf1fPrashant Malani err = errno; 1174982edd19a092114c479134cb16e0af54730edf1fPrashant Malani close(dd); 1175982edd19a092114c479134cb16e0af54730edf1fPrashant Malani errno = err; 1176982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1177982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1178982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 1179982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1180982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint hci_close_dev(int dd) 1181982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 1182982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return close(dd); 1183982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 1184982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1185982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* HCI functions that require open device 1186982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * dd - Device descriptor returned by hci_open_dev. */ 1187982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1188982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint hci_send_cmd(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, void *param) 1189982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 1190982edd19a092114c479134cb16e0af54730edf1fPrashant Malani uint8_t type = HCI_COMMAND_PKT; 1191982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_command_hdr hc; 1192982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct iovec iv[3]; 1193982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int ivn; 1194982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1195982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hc.opcode = htobs(cmd_opcode_pack(ogf, ocf)); 1196982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hc.plen= plen; 1197982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1198982edd19a092114c479134cb16e0af54730edf1fPrashant Malani iv[0].iov_base = &type; 1199982edd19a092114c479134cb16e0af54730edf1fPrashant Malani iv[0].iov_len = 1; 1200982edd19a092114c479134cb16e0af54730edf1fPrashant Malani iv[1].iov_base = &hc; 1201982edd19a092114c479134cb16e0af54730edf1fPrashant Malani iv[1].iov_len = HCI_COMMAND_HDR_SIZE; 1202982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ivn = 2; 1203982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1204982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (plen) { 1205982edd19a092114c479134cb16e0af54730edf1fPrashant Malani iv[2].iov_base = param; 1206982edd19a092114c479134cb16e0af54730edf1fPrashant Malani iv[2].iov_len = plen; 1207982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ivn = 3; 1208982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1209982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1210982edd19a092114c479134cb16e0af54730edf1fPrashant Malani while (writev(dd, iv, ivn) < 0) { 1211982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (errno == EAGAIN || errno == EINTR) 1212982edd19a092114c479134cb16e0af54730edf1fPrashant Malani continue; 1213982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1214982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1215982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 1216982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 1217982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1218982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define HCI_SLEEP_CMD_OCF 0x04 1219982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define TIOCSETD 0x5423 1220982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define HCIUARTSETFLAGS _IOW('U', 204, int) 1221982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define HCIUARTSETPROTO _IOW('U', 200, int) 1222982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define HCIUARTGETDEVICE _IOW('U', 202, int) 1223982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* 1224982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * Atheros AR300x specific initialization post callback 1225982edd19a092114c479134cb16e0af54730edf1fPrashant Malani */ 1226982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint ath3k_post(int fd, int pm) 1227982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 1228982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int dev_id, dd; 1229982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct timespec tm = { 0, 50000}; 1230982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1231982edd19a092114c479134cb16e0af54730edf1fPrashant Malani sleep(1); 1232982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1233982edd19a092114c479134cb16e0af54730edf1fPrashant Malani dev_id = ioctl(fd, HCIUARTGETDEVICE, 0); 1234982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (dev_id < 0) { 1235982edd19a092114c479134cb16e0af54730edf1fPrashant Malani perror("cannot get device id"); 1236982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return dev_id; 1237982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1238982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1239982edd19a092114c479134cb16e0af54730edf1fPrashant Malani dd = hci_open_dev(dev_id); 1240982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (dd < 0) { 1241982edd19a092114c479134cb16e0af54730edf1fPrashant Malani perror("HCI device open failed"); 1242982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return dd; 1243982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1244982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1245982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) { 1246982edd19a092114c479134cb16e0af54730edf1fPrashant Malani perror("hci down:Power management Disabled"); 1247982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_close_dev(dd); 1248982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1249982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1250982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1251982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* send vendor specific command with Sleep feature Enabled */ 1252982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (hci_send_cmd(dd, OGF_VENDOR_CMD, HCI_SLEEP_CMD_OCF, 1, &pm) < 0) 1253982edd19a092114c479134cb16e0af54730edf1fPrashant Malani perror("PM command failed, power management Disabled"); 1254982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1255982edd19a092114c479134cb16e0af54730edf1fPrashant Malani nanosleep(&tm, NULL); 1256982edd19a092114c479134cb16e0af54730edf1fPrashant Malani hci_close_dev(dd); 1257982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1258982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return 0; 1259982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 1260982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1261982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1262982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1263982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define FLOW_CTL 0x0001 1264982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define ENABLE_PM 1 1265982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#define DISABLE_PM 0 1266982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1267982edd19a092114c479134cb16e0af54730edf1fPrashant Malani/* Initialize UART driver */ 1268982edd19a092114c479134cb16e0af54730edf1fPrashant Malanistatic int init_uart(char *dev, struct uart_t *u, int send_break, int raw) 1269982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 1270982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI(" %s ", __FUNCTION__); 1271982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1272982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct termios ti; 1273982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1274982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int i, fd; 1275982edd19a092114c479134cb16e0af54730edf1fPrashant Malani unsigned long flags = 0; 1276982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1277982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (raw) 1278982edd19a092114c479134cb16e0af54730edf1fPrashant Malani flags |= 1 << HCI_UART_RAW_DEVICE; 1279982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1280982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1281982edd19a092114c479134cb16e0af54730edf1fPrashant Malani fd = open(dev, O_RDWR | O_NOCTTY); 1282982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1283982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (fd < 0) { 1284982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Can't open serial port"); 1285982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1286982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1287982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1288982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1289982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tcflush(fd, TCIOFLUSH); 1290982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1291982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (tcgetattr(fd, &ti) < 0) { 1292982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Can't get port settings: %d\n", errno); 1293982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1294982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1295982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1296982edd19a092114c479134cb16e0af54730edf1fPrashant Malani cfmakeraw(&ti); 1297982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1298982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ti.c_cflag |= CLOCAL; 1299982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (u->flags & FLOW_CTL) 1300982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ti.c_cflag |= CRTSCTS; 1301982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 1302982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ti.c_cflag &= ~CRTSCTS; 1303982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1304982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (tcsetattr(fd, TCSANOW, &ti) < 0) { 1305982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Can't set port settings"); 1306982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1307982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1308982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1309982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (set_speed(fd, &ti, u->init_speed) < 0) { 1310982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Can't set initial baud rate"); 1311982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1312982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1313982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1314982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tcflush(fd, TCIOFLUSH); 1315982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1316982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (send_break) { 1317982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tcsendbreak(fd, 0); 1318982edd19a092114c479134cb16e0af54730edf1fPrashant Malani usleep(500000); 1319982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1320982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1321982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ath3k_init(fd,u->speed,u->init_speed,u->bdaddr, &ti); 1322982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1323982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Device setup complete\n"); 1324982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1325982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1326982edd19a092114c479134cb16e0af54730edf1fPrashant Malani tcflush(fd, TCIOFLUSH); 1327982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1328982edd19a092114c479134cb16e0af54730edf1fPrashant Malani // Set actual baudrate 1329982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* 1330982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (set_speed(fd, &ti, u->speed) < 0) { 1331982edd19a092114c479134cb16e0af54730edf1fPrashant Malani perror("Can't set baud rate"); 1332982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1333982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1334982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1335982edd19a092114c479134cb16e0af54730edf1fPrashant Malani i = N_HCI; 1336982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (ioctl(fd, TIOCSETD, &i) < 0) { 1337982edd19a092114c479134cb16e0af54730edf1fPrashant Malani perror("Can't set line discipline"); 1338982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1339982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1340982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1341982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) { 1342982edd19a092114c479134cb16e0af54730edf1fPrashant Malani perror("Can't set UART flags"); 1343982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1344982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1345982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1346982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) { 1347982edd19a092114c479134cb16e0af54730edf1fPrashant Malani perror("Can't set device"); 1348982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return -1; 1349982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1350982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1351982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#if !defined(SW_BOARD_HAVE_BLUETOOTH_RTK) 1352982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ath3k_post(fd, u->pm); 1353982edd19a092114c479134cb16e0af54730edf1fPrashant Malani#endif 1354982edd19a092114c479134cb16e0af54730edf1fPrashant Malani */ 1355982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1356982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return fd; 1357982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 1358982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1359982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1360982edd19a092114c479134cb16e0af54730edf1fPrashant Malaniint hw_config_ath3k(char *port_name) 1361982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 1362982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI(" %s ", __FUNCTION__); 1363982edd19a092114c479134cb16e0af54730edf1fPrashant Malani PSCounter=0; 1364982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct sigaction sa; 1365982edd19a092114c479134cb16e0af54730edf1fPrashant Malani struct uart_t u ; 1366982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int n=0,send_break=0,raw=0; 1367982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1368982edd19a092114c479134cb16e0af54730edf1fPrashant Malani memset(&u, 0, sizeof(u)); 1369982edd19a092114c479134cb16e0af54730edf1fPrashant Malani u.speed =3000000; 1370982edd19a092114c479134cb16e0af54730edf1fPrashant Malani u.init_speed =115200; 1371982edd19a092114c479134cb16e0af54730edf1fPrashant Malani u.flags |= FLOW_CTL; 1372982edd19a092114c479134cb16e0af54730edf1fPrashant Malani u.pm = DISABLE_PM; 1373982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1374982edd19a092114c479134cb16e0af54730edf1fPrashant Malani n = init_uart(port_name, &u, send_break, raw); 1375982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (n < 0) { 1376982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("Can't initialize device"); 1377982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1378982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1379982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return n; 1380982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 1381982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1382982edd19a092114c479134cb16e0af54730edf1fPrashant Malanivoid lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity) 1383982edd19a092114c479134cb16e0af54730edf1fPrashant Malani{ 1384982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int rc; 1385982edd19a092114c479134cb16e0af54730edf1fPrashant Malani int fd = -1; 1386982edd19a092114c479134cb16e0af54730edf1fPrashant Malani char buffer; 1387982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1388982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("lpm mode: %d action: %d", pio, action); 1389982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1390982edd19a092114c479134cb16e0af54730edf1fPrashant Malani switch (pio) 1391982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1392982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case UPIO_LPM_MODE: 1393982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (upio_state[UPIO_LPM_MODE] == action) 1394982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1395982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("LPM is %s already", lpm_mode[action]); 1396982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return; 1397982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1398982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1399982edd19a092114c479134cb16e0af54730edf1fPrashant Malani fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY); 1400982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1401982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (fd < 0) 1402982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1403982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGE("upio_set : open(%s) for write failed: %s (%d)", 1404982edd19a092114c479134cb16e0af54730edf1fPrashant Malani VENDOR_LPM_PROC_NODE, strerror(errno), errno); 1405982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return; 1406982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1407982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1408982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (action == UPIO_ASSERT) 1409982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1410982edd19a092114c479134cb16e0af54730edf1fPrashant Malani buffer = '1'; 1411982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1412982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 1413982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1414982edd19a092114c479134cb16e0af54730edf1fPrashant Malani buffer = '0'; 1415982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1416982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1417982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write(fd, &buffer, 1) < 0) 1418982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1419982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGE("upio_set : write(%s) failed: %s (%d)", 1420982edd19a092114c479134cb16e0af54730edf1fPrashant Malani VENDOR_LPM_PROC_NODE, strerror(errno),errno); 1421982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1422982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 1423982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1424982edd19a092114c479134cb16e0af54730edf1fPrashant Malani upio_state[UPIO_LPM_MODE] = action; 1425982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("LPM is set to %s", lpm_mode[action]); 1426982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1427982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1428982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (fd >= 0) 1429982edd19a092114c479134cb16e0af54730edf1fPrashant Malani close(fd); 1430982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1431982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 1432982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1433982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case UPIO_BT_WAKE: 1434982edd19a092114c479134cb16e0af54730edf1fPrashant Malani /* UPIO_DEASSERT should be allowed because in Rx case assert occur 1435982edd19a092114c479134cb16e0af54730edf1fPrashant Malani * from the remote side where as deassert will be initiated from Host 1436982edd19a092114c479134cb16e0af54730edf1fPrashant Malani */ 1437982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if ((action == UPIO_ASSERT) && (upio_state[UPIO_BT_WAKE] == action)) 1438982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1439982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("BT_WAKE is %s already", lpm_state[action]); 1440982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1441982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return; 1442982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1443982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1444982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (action == UPIO_DEASSERT) 1445982edd19a092114c479134cb16e0af54730edf1fPrashant Malani buffer = '0'; 1446982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 1447982edd19a092114c479134cb16e0af54730edf1fPrashant Malani buffer = '1'; 1448982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1449982edd19a092114c479134cb16e0af54730edf1fPrashant Malani fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY); 1450982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1451982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (fd < 0) 1452982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1453982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGE("upio_set : open(%s) for write failed: %s (%d)", 1454982edd19a092114c479134cb16e0af54730edf1fPrashant Malani VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno); 1455982edd19a092114c479134cb16e0af54730edf1fPrashant Malani return; 1456982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1457982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1458982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (write(fd, &buffer, 1) < 0) 1459982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1460982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGE("upio_set : write(%s) failed: %s (%d)", 1461982edd19a092114c479134cb16e0af54730edf1fPrashant Malani VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno); 1462982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1463982edd19a092114c479134cb16e0af54730edf1fPrashant Malani else 1464982edd19a092114c479134cb16e0af54730edf1fPrashant Malani { 1465982edd19a092114c479134cb16e0af54730edf1fPrashant Malani upio_state[UPIO_BT_WAKE] = action; 1466982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("BT_WAKE is set to %s", lpm_state[action]); 1467982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1468982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1469982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("proc btwrite assertion"); 1470982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1471982edd19a092114c479134cb16e0af54730edf1fPrashant Malani if (fd >= 0) 1472982edd19a092114c479134cb16e0af54730edf1fPrashant Malani close(fd); 1473982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1474982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 1475982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1476982edd19a092114c479134cb16e0af54730edf1fPrashant Malani case UPIO_HOST_WAKE: 1477982edd19a092114c479134cb16e0af54730edf1fPrashant Malani ALOGI("upio_set: UPIO_HOST_WAKE"); 1478982edd19a092114c479134cb16e0af54730edf1fPrashant Malani break; 1479982edd19a092114c479134cb16e0af54730edf1fPrashant Malani } 1480982edd19a092114c479134cb16e0af54730edf1fPrashant Malani 1481982edd19a092114c479134cb16e0af54730edf1fPrashant Malani} 1482