1635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* 2635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * 3635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Copyright (c) 2013, The Linux Foundation. All rights reserved. 4635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Not a Contribution. 5635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * 6635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Copyright 2012 The Android Open Source Project 7635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * 8635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Licensed under the Apache License, Version 2.0 (the "License"); you 9635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * may not use this file except in compliance with the License. You may 10635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * obtain a copy of the License at 11635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * 12635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * http://www.apache.org/licenses/LICENSE-2.0 13635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * 14635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Unless required by applicable law or agreed to in writing, software 15635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * distributed under the License is distributed on an "AS IS" BASIS, 16635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 17635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * implied. See the License for the specific language governing 18635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * permissions and limitations under the License. 19635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * 20635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch */ 21635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 22635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/****************************************************************************** 23635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * 24635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Filename: hw_ar3k.c 25635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * 26635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Description: Contains controller-specific functions, like 27635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * firmware patch download 28635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * low power mode operations 29635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * 30635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ******************************************************************************/ 31635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#ifdef __cplusplus 32635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschextern "C" { 33635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#endif 34635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 35635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define LOG_TAG "bt_vendor" 36635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 37dce6a114229a6ecf183a45ef9f95e3147afdb07aSteven Moreland#include <sys/uio.h> 38635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <sys/socket.h> 39dce6a114229a6ecf183a45ef9f95e3147afdb07aSteven Moreland#include <log/log.h> 40635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <sys/types.h> 41635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <sys/stat.h> 42635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <signal.h> 43635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <time.h> 44635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <errno.h> 45635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <fcntl.h> 46635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <dirent.h> 47635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <ctype.h> 48635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <cutils/properties.h> 49635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <stdlib.h> 50635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <string.h> 51635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <termios.h> 52635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include <string.h> 53dce6a114229a6ecf183a45ef9f95e3147afdb07aSteven Moreland#include <unistd.h> 54635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 55635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include "bt_hci_bdroid.h" 56635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include "hci_uart.h" 57635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#include "hw_ar3k.h" 58635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 59635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/****************************************************************************** 60635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch** Variables 61635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch******************************************************************************/ 62635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint cbstat = 0; 63635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PATCH_LOC_STRING_LEN 8 64635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschchar ARbyte[3]; 65635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschchar ARptr[MAX_PATCH_CMD + 1]; 66635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint byte_cnt; 67635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint patch_count = 0; 68635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschchar patch_loc[PATCH_LOC_STRING_LEN + 1]; 69635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint PSCounter=0; 70635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 71635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschuint32_t dev_type = 0; 72635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschuint32_t rom_version = 0; 73635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschuint32_t build_version = 0; 74635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 75635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschchar patch_file[PATH_MAX]; 76635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschchar ps_file[PATH_MAX]; 77635682da6daf370cdba78511b917e166f0b6dbecSteve PfetschFILE *stream; 78635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint tag_count=0; 79635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 80635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* for friendly debugging outpout string */ 81635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic char *lpm_mode[] = { 82635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch "UNKNOWN", 83635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch "disabled", 84635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch "enabled" 85635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch}; 86635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 87635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic char *lpm_state[] = { 88635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch "UNKNOWN", 89635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch "de-asserted", 90635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch "asserted" 91635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch}; 92635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 93635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic uint8_t upio_state[UPIO_MAX_COUNT]; 94635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstruct ps_cfg_entry ps_list[MAX_TAGS]; 95635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 96635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_EVENT_LEN 100 97635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 98635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#ifdef __cplusplus 99635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 100635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#endif 101635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 102635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define RESERVED(p) if(p) ALOGI( "%s: reserved param", __FUNCTION__); 103635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 104635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/***************************************************************************** 105635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch** Functions 106635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch*****************************************************************************/ 107635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 108635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint is_bt_soc_ath() { 109635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int ret = 0; 110635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char bt_soc_type[PROPERTY_VALUE_MAX]; 111635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL); 112635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (ret != 0) { 113635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type); 114635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!strncasecmp(bt_soc_type, "ath3k", sizeof("ath3k"))) 115635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 1; 116635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } else { 117635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("qcom.bluetooth.soc not set, so using default.\n"); 118635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 119635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 120635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 121635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 122635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 123635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* 124635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Send HCI command and wait for command complete event. 125635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * The event buffer has to be freed by the caller. 126635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch */ 127635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 128635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int send_hci_cmd_sync(int dev, uint8_t *cmd, int len, uint8_t **event) 129635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 130635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int err; 131635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *hci_event; 132635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t pkt_type = HCI_COMMAND_PKT; 133635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 134635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (len == 0) 135635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return len; 136635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 137635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write(dev, &pkt_type, 1) != 1) 138635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 139635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write(dev, (unsigned char *)cmd, len) != len) 140635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 141635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 142635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_event = (uint8_t *)malloc(PS_EVENT_LEN); 143635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!hci_event) 144635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -ENOMEM; 145635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 146635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = read_hci_event(dev, (unsigned char *)hci_event, PS_EVENT_LEN); 147635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err > 0) { 148635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch *event = hci_event; 149635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } else { 150635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch free(hci_event); 151635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 152635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 153635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 154635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return len; 155635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 156635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 157635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic void convert_bdaddr(char *str_bdaddr, char *bdaddr) 158635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 159635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char bdbyte[3]; 160635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char *str_byte = str_bdaddr; 161635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int i, j; 162635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int colon_present = 0; 163635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 164635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (strstr(str_bdaddr, ":")) 165635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch colon_present = 1; 166635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 167635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch bdbyte[2] = '\0'; 168635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 169635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Reverse the BDADDR to LSB first */ 170635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch for (i = 0, j = 5; i < 6; i++, j--) { 171635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch bdbyte[0] = str_byte[0]; 172635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch bdbyte[1] = str_byte[1]; 173635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch bdaddr[j] = strtol(bdbyte, NULL, 16); 174635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 175635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (colon_present == 1) 176635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch str_byte += 3; 177635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 178635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch str_byte += 2; 179635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 180635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 181635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 182635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int uart_speed(int s) 183635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 184635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch switch (s) { 185635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 9600: 186635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B9600; 187635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 19200: 188635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B19200; 189635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 38400: 190635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B38400; 191635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 57600: 192635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B57600; 193635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 115200: 194635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B115200; 195635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 230400: 196635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B230400; 197635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 460800: 198635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B460800; 199635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 500000: 200635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B500000; 201635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 576000: 202635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B576000; 203635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 921600: 204635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B921600; 205635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 1000000: 206635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B1000000; 207635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 1152000: 208635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B1152000; 209635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 1500000: 210635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B1500000; 211635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 2000000: 212635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B2000000; 213635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#ifdef B2500000 214635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 2500000: 215635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B2500000; 216635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#endif 217635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#ifdef B3000000 218635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 3000000: 219635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B3000000; 220635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#endif 221635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#ifdef B3500000 222635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 3500000: 223635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B3500000; 224635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#endif 225635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#ifdef B4000000 226635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case 4000000: 227635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B4000000; 228635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#endif 229635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch default: 230635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return B57600; 231635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 232635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 233635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 234635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint set_speed(int fd, struct termios *ti, int speed) 235635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 236635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (cfsetospeed(ti, uart_speed(speed)) < 0) 237635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -errno; 238635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 239635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (cfsetispeed(ti, uart_speed(speed)) < 0) 240635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -errno; 241635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 242635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (tcsetattr(fd, TCSANOW, ti) < 0) 243635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -errno; 244635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 245635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 246635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 247635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 248635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic void load_hci_ps_hdr(uint8_t *cmd, uint8_t ps_op, int len, int index) 249635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 250635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_command_hdr *ch = (void *)cmd; 251635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 252635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 253635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch HCI_PS_CMD_OCF)); 254635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->plen = len + PS_HDR_LEN; 255635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd += HCI_COMMAND_HDR_SIZE; 256635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 257635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[0] = ps_op; 258635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[1] = index; 259635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[2] = index >> 8; 260635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[3] = len; 261635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 262635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 263635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 264635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int read_ps_event(uint8_t *event, uint16_t ocf) 265635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 266635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_event_hdr *eh; 267635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint16_t opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, ocf)); 268635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 269635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch event++; 270635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 271635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch eh = (void *)event; 272635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch event += HCI_EVENT_HDR_SIZE; 273635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 274635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (eh->evt == EVT_CMD_COMPLETE) { 275635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch evt_cmd_complete *cc = (void *)event; 276635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 277635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch event += EVT_CMD_COMPLETE_SIZE; 278635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 279635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (cc->opcode == opcode && event[0] == HCI_EV_SUCCESS) 280635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 281635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 282635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 283635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 284635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 285635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 286635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 287635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 288635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_WRITE 1 289635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_RESET 2 290635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define WRITE_PATCH 8 291635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define ENABLE_PATCH 11 292635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 293635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define HCI_PS_CMD_HDR_LEN 7 294635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 295635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int write_cmd(int fd, uint8_t *buffer, int len) 296635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 297635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *event; 298635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int err; 299635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 300635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = send_hci_cmd_sync(fd, buffer, len, &event); 301635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 302635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 303635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 304635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = read_ps_event(event, HCI_PS_CMD_OCF); 305635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 306635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch free(event); 307635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 308635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 309635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 310635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 311635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_RESET_PARAM_LEN 6 312635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_RESET_CMD_LEN (HCI_PS_CMD_HDR_LEN + PS_RESET_PARAM_LEN) 313635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 314635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_ID_MASK 0xFF 315635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 316635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* Sends PS commands using vendor specficic HCI commands */ 317635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int write_ps_cmd(int fd, uint8_t opcode, uint32_t ps_param) 318635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 319635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t cmd[HCI_MAX_CMD_SIZE]; 320635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint32_t i; 321635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 322635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch switch (opcode) { 323635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case ENABLE_PATCH: 324635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch load_hci_ps_hdr(cmd, opcode, 0, 0x00); 325635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 326635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write_cmd(fd, cmd, HCI_PS_CMD_HDR_LEN) < 0) 327635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 328635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 329635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 330635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case PS_RESET: 331635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch load_hci_ps_hdr(cmd, opcode, PS_RESET_PARAM_LEN, 0x00); 332635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 333635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[7] = 0x00; 334635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[PS_RESET_CMD_LEN - 2] = ps_param & PS_ID_MASK; 335635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[PS_RESET_CMD_LEN - 1] = (ps_param >> 8) & PS_ID_MASK; 336635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 337635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write_cmd(fd, cmd, PS_RESET_CMD_LEN) < 0) 338635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 339635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 340635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 341635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case PS_WRITE: 342635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch for (i = 0; i < ps_param; i++) { 343635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch load_hci_ps_hdr(cmd, opcode, ps_list[i].len, 344635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ps_list[i].id); 345635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 346635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch memcpy(&cmd[HCI_PS_CMD_HDR_LEN], ps_list[i].data, 347635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ps_list[i].len); 348635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 349635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write_cmd(fd, cmd, ps_list[i].len + 350635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch HCI_PS_CMD_HDR_LEN) < 0) 351635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 352635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 353635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 354635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 355635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 356635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 357635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 358635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 359635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_ASIC_FILE "PS_ASIC.pst" 360635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_FPGA_FILE "PS_FPGA.pst" 361635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define MAXPATHLEN 4096 362635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic void get_ps_file_name(uint32_t devtype, uint32_t rom_version,char *path) 363635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 364635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char *filename; 365635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 366635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (devtype == 0xdeadc0de) 367635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch filename = PS_ASIC_FILE; 368635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 369635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch filename = PS_FPGA_FILE; 370635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 371635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, filename); 372635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 373635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 374635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PATCH_FILE "RamPatch.txt" 375635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define FPGA_ROM_VERSION 0x99999999 376635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define ROM_DEV_TYPE 0xdeadc0de 377635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 378635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic void get_patch_file_name(uint32_t dev_type, uint32_t rom_version, 379635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint32_t build_version, char *path) 380635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 381635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (rom_version == FPGA_ROM_VERSION && dev_type != ROM_DEV_TYPE 382635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch &&dev_type != 0 && build_version == 1) 383635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch path[0] = '\0'; 384635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 385635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, PATCH_FILE); 386635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 387635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 388635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int set_cntrlr_baud(int fd, int speed) 389635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 390635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int baud; 391635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct timespec tm = { 0, 500000}; 392635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE]; 393635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch unsigned char *ptr = cmd + 1; 394635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_command_hdr *ch = (void *)ptr; 395635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 396635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[0] = HCI_COMMAND_PKT; 397635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 398635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* set controller baud rate to user specified value */ 399635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr = cmd + 1; 400635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 401635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch HCI_CHG_BAUD_CMD_OCF)); 402635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->plen = 2; 403635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr += HCI_COMMAND_HDR_SIZE; 404635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 405635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch baud = speed/100; 406635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[0] = (char)baud; 407635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[1] = (char)(baud >> 8); 408635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 409635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write(fd, cmd, WRITE_BAUD_CMD_LEN) != WRITE_BAUD_CMD_LEN) { 410635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Failed to write change baud rate command"); 411635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -ETIMEDOUT; 412635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 413635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 414635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch nanosleep(&tm, NULL); 415635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 416635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) 417635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -ETIMEDOUT; 418635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 419635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 420635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 421635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 422635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_UNDEF 0 423635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_ID 1 424635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_LEN 2 425635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_DATA 3 426635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 427635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_MAX_LEN 500 428635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define LINE_SIZE_MAX (PS_MAX_LEN * 2) 429635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define ENTRY_PER_LINE 16 430635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 431635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define __check_comment(buf) (((buf)[0] == '/') && ((buf)[1] == '/')) 432635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define __skip_space(str) while (*(str) == ' ') ((str)++) 433635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 434635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 435635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define __is_delim(ch) ((ch) == ':') 436635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define MAX_PREAMBLE_LEN 4 437635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 438635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* Parse PS entry preamble of format [X:X] for main type and subtype */ 439635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int get_ps_type(char *ptr, int index, char *type, char *sub_type) 440635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 441635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int i; 442e2440ccce4e310cc64ca4f9feb71c61f3e148e8fMarie Janssen int delim = false; 443635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 444635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (index > MAX_PREAMBLE_LEN) 445635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 446635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 447635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch for (i = 1; i < index; i++) { 448635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (__is_delim(ptr[i])) { 449e2440ccce4e310cc64ca4f9feb71c61f3e148e8fMarie Janssen delim = true; 450635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch continue; 451635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 452635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 453635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (isalpha(ptr[i])) { 454e2440ccce4e310cc64ca4f9feb71c61f3e148e8fMarie Janssen if (delim == false) 455635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch (*type) = toupper(ptr[i]); 456635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 457635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch (*sub_type) = toupper(ptr[i]); 458635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 459635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 460635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 461635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 462635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 463635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 464635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define ARRAY 'A' 465635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define STRING 'S' 466635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define DECIMAL 'D' 467635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define BINARY 'B' 468635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 469635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_HEX 0 470635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_DEC 1 471635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 472635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int get_input_format(char *buf, struct ps_entry_type *format) 473635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 474635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char *ptr = NULL; 475635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char type = '\0'; 476635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char sub_type = '\0'; 477635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 478635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch format->type = PS_HEX; 479e2440ccce4e310cc64ca4f9feb71c61f3e148e8fMarie Janssen format->array = true; 480635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 481635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (strstr(buf, "[") != buf) 482635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 483635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 484635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr = strstr(buf, "]"); 485635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!ptr) 486635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 487635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 488635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (get_ps_type(buf, ptr - buf, &type, &sub_type) < 0) 489635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 490635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 491635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Check is data type is of array */ 492635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (type == ARRAY || sub_type == ARRAY) 493e2440ccce4e310cc64ca4f9feb71c61f3e148e8fMarie Janssen format->array = true; 494635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 495635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (type == STRING || sub_type == STRING) 496e2440ccce4e310cc64ca4f9feb71c61f3e148e8fMarie Janssen format->array = false; 497635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 498635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (type == DECIMAL || type == BINARY) 499635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch format->type = PS_DEC; 500635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 501635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch format->type = PS_HEX; 502635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 503635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 504635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 505635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 506635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 507635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 508635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define UNDEFINED 0xFFFF 509635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 510635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic unsigned int read_data_in_section(char *buf, struct ps_entry_type type) 511635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 512635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char *ptr = buf; 513635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 514635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!buf) 515635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return UNDEFINED; 516635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 517635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (buf == strstr(buf, "[")) { 518635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr = strstr(buf, "]"); 519635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!ptr) 520635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return UNDEFINED; 521635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 522635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr++; 523635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 524635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 525e2440ccce4e310cc64ca4f9feb71c61f3e148e8fMarie Janssen if (type.type == PS_HEX && type.array != true) 526635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return strtol(ptr, NULL, 16); 527635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 528635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return UNDEFINED; 529635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 530635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 531635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 532635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* Read PS entries as string, convert and add to Hex array */ 533635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic void update_tag_data(struct ps_cfg_entry *tag, 534635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct tag_info *info, const char *ptr) 535635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 536635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char buf[3]; 537635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 538635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch buf[2] = '\0'; 539635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 540635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch strlcpy(buf, &ptr[info->char_cnt],sizeof(buf)); 541635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tag->data[info->byte_count] = strtol(buf, NULL, 16); 542635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch info->char_cnt += 3; 543635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch info->byte_count++; 544635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 545635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch strlcpy(buf, &ptr[info->char_cnt], sizeof(buf)); 546635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tag->data[info->byte_count] = strtol(buf, NULL, 16); 547635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch info->char_cnt += 3; 548635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch info->byte_count++; 549635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 550635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 551635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic inline int update_char_count(const char *buf) 552635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 553635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char *end_ptr; 554635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 555635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (strstr(buf, "[") == buf) { 556635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch end_ptr = strstr(buf, "]"); 557635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!end_ptr) 558635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 559635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 560635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return(end_ptr - buf) + 1; 561635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 562635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 563635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 564635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 565635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 566635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_HEX 0 567635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_DEC 1 568635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 569635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int ath_parse_ps(FILE *stream) 570635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 571635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char buf[LINE_SIZE_MAX + 1]; 572635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char *ptr; 573635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t tag_cnt = 0; 574635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int16_t byte_count = 0; 575635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct ps_entry_type format; 576635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct tag_info status = { 0, 0, 0, 0}; 577635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 578635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch do { 579635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int read_count; 580635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct ps_cfg_entry *tag; 581635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 582635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr = fgets(buf, LINE_SIZE_MAX, stream); 583635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!ptr) 584635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 585635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 586635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch __skip_space(ptr); 587635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (__check_comment(ptr)) 588635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch continue; 589635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 590635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Lines with a '#' will be followed by new PS entry */ 591635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (ptr == strstr(ptr, "#")) { 592635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (status.section != PS_UNDEF) { 593635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 594635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } else { 595635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status.section = PS_ID; 596635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch continue; 597635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 598635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 599635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 600635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tag = &ps_list[tag_cnt]; 601635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 602635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch switch (status.section) { 603635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case PS_ID: 604635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (get_input_format(ptr, &format) < 0) 605635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 606635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 607635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tag->id = read_data_in_section(ptr, format); 608635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status.section = PS_LEN; 609635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 610635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 611635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case PS_LEN: 612635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (get_input_format(ptr, &format) < 0) 613635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 614635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 615635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch byte_count = read_data_in_section(ptr, format); 616635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (byte_count > PS_MAX_LEN) 617635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 618635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 619635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tag->len = byte_count; 620635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tag->data = (uint8_t *)malloc(byte_count); 621635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 622635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status.section = PS_DATA; 623635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status.line_count = 0; 624635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 625635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 626635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case PS_DATA: 627635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (status.line_count == 0) 628635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (get_input_format(ptr, &format) < 0) 629635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 630635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 631635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch __skip_space(ptr); 632635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 633635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status.char_cnt = update_char_count(ptr); 634635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 635635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch read_count = (byte_count > ENTRY_PER_LINE) ? 636635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ENTRY_PER_LINE : byte_count; 637635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 638e2440ccce4e310cc64ca4f9feb71c61f3e148e8fMarie Janssen if (format.type == PS_HEX && format.array == true) { 639635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch while (read_count > 0) { 640635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch update_tag_data(tag, &status, ptr); 641635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch read_count -= 2; 642635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 643635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 644635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (byte_count > ENTRY_PER_LINE) 645635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch byte_count -= ENTRY_PER_LINE; 646635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 647635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch byte_count = 0; 648635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 649635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 650635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status.line_count++; 651635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 652635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (byte_count == 0) 653635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch memset(&status, 0x00, sizeof(struct tag_info)); 654635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 655635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (status.section == PS_UNDEF) 656635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tag_cnt++; 657635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 658635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (tag_cnt == MAX_TAGS) 659635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -EILSEQ; 660635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 661635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 662635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } while (ptr); 663635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 664635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return tag_cnt; 665635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 666635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 667635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_RAM_SIZE 2048 668635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 669635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int ps_config_download(int fd, int tag_count) 670635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 671635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write_ps_cmd(fd, PS_RESET, PS_RAM_SIZE) < 0) 672635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 673635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 674635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (tag_count > 0) 675635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write_ps_cmd(fd, PS_WRITE, tag_count) < 0) 676635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 677635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 678635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 679635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 680635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int write_bdaddr(int pConfig, char *bdaddr) 681635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 682635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *event; 683635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int err; 684635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t cmd[13]; 685635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *ptr = cmd; 686635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_command_hdr *ch = (void *)cmd; 687635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 688635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch memset(cmd, 0, sizeof(cmd)); 689635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 690635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 691635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch HCI_PS_CMD_OCF)); 692635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->plen = 10; 693635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr += HCI_COMMAND_HDR_SIZE; 694635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 695635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[0] = 0x01; 696635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[1] = 0x01; 697635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[2] = 0x00; 698635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[3] = 0x06; 699635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 700635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch convert_bdaddr(bdaddr, (char *)&ptr[4]); 701635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 702635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event); 703635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 704635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 705635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 706635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = read_ps_event(event, HCI_PS_CMD_OCF); 707635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 708635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch free(event); 709635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 710635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 711635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 712635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 713635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic void write_bdaddr_from_file(int rom_version, int fd) 714635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 715635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch FILE *stream; 716635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char bdaddr[PATH_MAX]; 717635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char bdaddr_file[PATH_MAX]; 718635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 719635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch snprintf(bdaddr_file, MAXPATHLEN, "%s%x/%s", 720635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch FW_PATH, rom_version, BDADDR_FILE); 721635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 722635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch stream = fopen(bdaddr_file, "r"); 723635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!stream) 724635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return; 725635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 726635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (fgets(bdaddr, PATH_MAX - 1, stream)) 727635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch write_bdaddr(fd, bdaddr); 728635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 729635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch fclose(stream); 730635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 731635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 732635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define HCI_EVT_CMD_CMPL_OPCODE 3 733635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5 734635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 735635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschvoid baswap(bdaddr_t *dst, const bdaddr_t *src) 736635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 737635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch register unsigned char *d = (unsigned char *) dst; 738635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch register const unsigned char *s = (const unsigned char *) src; 739635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch register int i; 740635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch for (i = 0; i < 6; i++) 741635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch d[i] = s[5-i]; 742635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 743635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 744635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 745635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint str2ba(const char *str, bdaddr_t *ba) 746635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 747635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t b[6]; 748635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch const char *ptr = str; 749635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int i; 750635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 751635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch for (i = 0; i < 6; i++) { 752635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch b[i] = (uint8_t) strtol(ptr, NULL, 16); 753635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr = strchr(ptr, ':'); 754635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (i != 5 && !ptr) 755635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr = ":00:00:00:00:00"; 756635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr++; 757635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 758635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch baswap(ba, (bdaddr_t *) b); 759635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 760635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 761635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 762635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define DEV_REGISTER 0x4FFC 763635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define GET_DEV_TYPE_OCF 0x05 764635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 765635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int get_device_type(int dev, uint32_t *code) 766635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 767635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t cmd[8] = {0}; 768635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *event; 769635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint32_t reg; 770635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int err; 771635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *ptr = cmd; 772635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_command_hdr *ch = (void *)cmd; 773635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 774635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 775635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch GET_DEV_TYPE_OCF)); 776635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->plen = 5; 777635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr += HCI_COMMAND_HDR_SIZE; 778635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 779635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[0] = (uint8_t)DEV_REGISTER; 780635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[1] = (uint8_t)DEV_REGISTER >> 8; 781635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[2] = (uint8_t)DEV_REGISTER >> 16; 782635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[3] = (uint8_t)DEV_REGISTER >> 24; 783635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[4] = 0x04; 784635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 785635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event); 786635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 787635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 788635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 789635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = read_ps_event(event, GET_DEV_TYPE_OCF); 790635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 791635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto cleanup; 792635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 793635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch reg = event[10]; 794635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch reg = (reg << 8) | event[9]; 795635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch reg = (reg << 8) | event[8]; 796635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch reg = (reg << 8) | event[7]; 797635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch *code = reg; 798635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 799635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschcleanup: 800635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch free(event); 801635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 802635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 803635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 804635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 805635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define GET_VERSION_OCF 0x1E 806635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 807635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int read_ath3k_version(int pConfig, uint32_t *rom_version, 808635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint32_t *build_version) 809635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 810635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t cmd[3] = {0}; 811635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *event; 812635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int err; 813635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int status; 814635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_command_hdr *ch = (void *)cmd; 815635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 816635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 817635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch GET_VERSION_OCF)); 818635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->plen = 0; 819635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 820635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event); 821635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 822635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 823635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 824635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = read_ps_event(event, GET_VERSION_OCF); 825635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 826635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto cleanup; 827635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 828635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status = event[10]; 829635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status = (status << 8) | event[9]; 830635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status = (status << 8) | event[8]; 831635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status = (status << 8) | event[7]; 832635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch *rom_version = status; 833635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 834635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status = event[14]; 835635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status = (status << 8) | event[13]; 836635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status = (status << 8) | event[12]; 837635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch status = (status << 8) | event[11]; 838635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch *build_version = status; 839635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 840635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschcleanup: 841635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch free(event); 842635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 843635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 844635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 845635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 846635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define VERIFY_CRC 9 847635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PS_REGION 1 848635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PATCH_REGION 2 849635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 850635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int get_ath3k_crc(int dev) 851635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 852635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t cmd[7] = {0}; 853635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *event; 854635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int err; 855635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 856635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch load_hci_ps_hdr(cmd, VERIFY_CRC, 0, PS_REGION | PATCH_REGION); 857635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 858635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event); 859635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 860635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 861635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Send error code if CRC check patched */ 862635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (read_ps_event(event, HCI_PS_CMD_OCF) >= 0) 863635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -EILSEQ; 864635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 865635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch free(event); 866635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 867635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 868635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 869635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 870635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define SET_PATCH_RAM_ID 0x0D 871635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define SET_PATCH_RAM_CMD_SIZE 11 872635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define ADDRESS_LEN 4 873635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int set_patch_ram(int dev, char *patch_loc, int len) 874635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 875635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int err; 876635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t cmd[20] = {0}; 877635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int i, j; 878635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char loc_byte[3]; 879635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *event; 880635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t *loc_ptr = &cmd[7]; 881635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 882635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch RESERVED(len); 883635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 884635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!patch_loc) 885635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 886635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 887635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch loc_byte[2] = '\0'; 888635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 889635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch load_hci_ps_hdr(cmd, SET_PATCH_RAM_ID, ADDRESS_LEN, 0); 890635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 891635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch for (i = 0, j = 3; i < 4; i++, j--) { 892635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch loc_byte[0] = patch_loc[0]; 893635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch loc_byte[1] = patch_loc[1]; 894635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch loc_ptr[j] = strtol(loc_byte, NULL, 16); 895635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch patch_loc += 2; 896635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 897635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 898635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = send_hci_cmd_sync(dev, cmd, SET_PATCH_RAM_CMD_SIZE, &event); 899635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 900635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 901635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 902635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = read_ps_event(event, HCI_PS_CMD_OCF); 903635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 904635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch free(event); 905635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 906635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 907635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 908635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 909635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PATCH_LOC_KEY "DA:" 910635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define PATCH_LOC_STRING_LEN 8 911635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int ps_patch_download(int fd, FILE *stream) 912635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 913635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char byte[3]; 914635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char ptr[MAX_PATCH_CMD + 1]; 915635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int byte_cnt; 916635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int patch_count = 0; 917635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char patch_loc[PATCH_LOC_STRING_LEN + 1]; 918635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 919635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch byte[2] = '\0'; 920635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 921635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch while (fgets(ptr, MAX_PATCH_CMD, stream)) { 922635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (strlen(ptr) <= 1) 923635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch continue; 924635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else if (strstr(ptr, PATCH_LOC_KEY) == ptr) { 925635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch strlcpy(patch_loc, &ptr[sizeof(PATCH_LOC_KEY) - 1], 926635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch PATCH_LOC_STRING_LEN); 927635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (set_patch_ram(fd, patch_loc, sizeof(patch_loc)) < 0) 928635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 929635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } else if (isxdigit(ptr[0])) 930635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 931635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 932635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 933635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 934635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 935635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch byte_cnt = strtol(ptr, NULL, 16); 936635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 937635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch while (byte_cnt > 0) { 938635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int i; 939635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t cmd[HCI_MAX_CMD_SIZE] = {0}; 940635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct patch_entry patch; 941635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 942635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (byte_cnt > MAX_PATCH_CMD) 943635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch patch.len = MAX_PATCH_CMD; 944635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 945635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch patch.len = byte_cnt; 946635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 947635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch for (i = 0; i < patch.len; i++) { 948635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!fgets(byte, 3, stream)) 949635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 950635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 951635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch patch.data[i] = strtoul(byte, NULL, 16); 952635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 953635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 954635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch load_hci_ps_hdr(cmd, WRITE_PATCH, patch.len, patch_count); 955635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch memcpy(&cmd[HCI_PS_CMD_HDR_LEN], patch.data, patch.len); 956635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 957635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write_cmd(fd, cmd, patch.len + HCI_PS_CMD_HDR_LEN) < 0) 958635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 959635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 960635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch patch_count++; 961635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch byte_cnt = byte_cnt - MAX_PATCH_CMD; 962635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 963635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 964635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write_ps_cmd(fd, ENABLE_PATCH, 0) < 0) 965635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 966635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 967635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return patch_count; 968635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 969635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 970635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int ath_ps_download(int fd) 971635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 972635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int err = 0; 973635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int tag_count; 974635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int patch_count = 0; 975635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint32_t rom_version = 0; 976635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint32_t build_version = 0; 977635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint32_t dev_type = 0; 978635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char patch_file[PATH_MAX]; 979635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char ps_file[PATH_MAX]; 980635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch FILE *stream; 981635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 982635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* 983635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Verfiy firmware version. depending on it select the PS 984635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * config file to download. 985635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch */ 986635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (get_device_type(fd, &dev_type) < 0) { 987635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -EILSEQ; 988635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto download_cmplete; 989635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 990635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 991635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (read_ath3k_version(fd, &rom_version, &build_version) < 0) { 992635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -EILSEQ; 993635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto download_cmplete; 994635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 995635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 996635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Do not download configuration if CRC passes */ 997635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (get_ath3k_crc(fd) < 0) { 998635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = 0; 999635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto download_cmplete; 1000635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1001635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1002635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch get_ps_file_name(dev_type, rom_version, ps_file); 1003635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch get_patch_file_name(dev_type, rom_version, build_version, patch_file); 1004635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1005635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch stream = fopen(ps_file, "r"); 1006635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!stream) { 1007635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("firmware file open error:%s, ver:%x\n",ps_file, rom_version); 1008635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (rom_version == 0x1020201) 1009635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = 0; 1010635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 1011635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -EILSEQ; 1012635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto download_cmplete; 1013635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1014635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tag_count = ath_parse_ps(stream); 1015635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1016635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch fclose(stream); 1017635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1018635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (tag_count < 0) { 1019635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -EILSEQ; 1020635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto download_cmplete; 1021635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1022635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1023635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* 1024635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * It is not necessary that Patch file be available, 1025635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * continue with PS Operations if patch file is not available. 1026635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch */ 1027635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (patch_file[0] == '\0') 1028635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = 0; 1029635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1030635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch stream = fopen(patch_file, "r"); 1031635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!stream) 1032635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = 0; 1033635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else { 1034635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch patch_count = ps_patch_download(fd, stream); 1035635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch fclose(stream); 1036635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1037635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (patch_count < 0) { 1038635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -EILSEQ; 1039635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto download_cmplete; 1040635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1041635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1042635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1043635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = ps_config_download(fd, tag_count); 1044635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1045635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschdownload_cmplete: 1046635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (!err) 1047635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch write_bdaddr_from_file(rom_version, fd); 1048635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1049635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 1050635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 1051635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1052635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti) 1053635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 1054635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI(" %s ", __FUNCTION__); 1055635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1056635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int r; 1057635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int err = 0; 1058635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct timespec tm = { 0, 500000}; 1059635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch unsigned char cmd[MAX_CMD_LEN] = {0}; 1060635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch unsigned char rsp[HCI_MAX_EVENT_SIZE]; 1061635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch unsigned char *ptr = cmd + 1; 1062635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_command_hdr *ch = (void *)ptr; 1063635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int flags = 0; 1064635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1065635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (ioctl(fd, TIOCMGET, &flags) < 0) { 1066635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("TIOCMGET failed in init\n"); 1067635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1068635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1069635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch flags |= TIOCM_RTS; 1070635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (ioctl(fd, TIOCMSET, &flags) < 0) { 1071635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("TIOCMSET failed in init: HW Flow-on error\n"); 1072635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1073635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1074635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1075635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* set both controller and host baud rate to maximum possible value */ 1076635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = set_cntrlr_baud(fd, speed); 1077635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("set_cntrlr_baud : ret:%d \n", err); 1078635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 1079635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 1080635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1081635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = set_speed(fd, ti, speed); 1082635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) { 1083635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Can't set required baud rate"); 1084635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 1085635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1086635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1087635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Download PS and patch */ 1088635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch r = ath_ps_download(fd); 1089635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (r < 0) { 1090635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Failed to Download configuration"); 1091635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -ETIMEDOUT; 1092635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto failed; 1093635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1094635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1095635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("ath_ps_download is done\n"); 1096635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1097635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[0] = HCI_COMMAND_PKT; 1098635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Write BDADDR */ 1099635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (bdaddr) { 1100635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 1101635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch HCI_PS_CMD_OCF)); 1102635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ch->plen = 10; 1103635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr += HCI_COMMAND_HDR_SIZE; 1104635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1105635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[0] = 0x01; 1106635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[1] = 0x01; 1107635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[2] = 0x00; 1108635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ptr[3] = 0x06; 1109635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch str2ba(bdaddr, (bdaddr_t *)(ptr + 4)); 1110635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1111635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write(fd, cmd, WRITE_BDADDR_CMD_LEN) != 1112635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch WRITE_BDADDR_CMD_LEN) { 1113635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Failed to write BD_ADDR command\n"); 1114635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -ETIMEDOUT; 1115635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto failed; 1116635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1117635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1118635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) { 1119635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Failed to set BD_ADDR\n"); 1120635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -ETIMEDOUT; 1121635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto failed; 1122635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1123635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1124635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1125635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Send HCI Reset */ 1126635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[1] = 0x03; 1127635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[2] = 0x0C; 1128635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cmd[3] = 0x00; 1129635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1130635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch r = write(fd, cmd, 4); 1131635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (r != 4) { 1132635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -ETIMEDOUT; 1133635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto failed; 1134635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1135635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1136635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch nanosleep(&tm, NULL); 1137635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) { 1138635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = -ETIMEDOUT; 1139635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto failed; 1140635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1141635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1142635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("HCI Reset is done\n"); 1143635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = set_cntrlr_baud(fd, speed); 1144635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) 1145635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("set_cntrlr_baud0:%d,%d\n", speed, err); 1146635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1147635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschfailed: 1148635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (err < 0) { 1149635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch set_cntrlr_baud(fd, init_speed); 1150635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch set_speed(fd, ti, init_speed); 1151635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1152635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1153635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return err; 1154635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1155635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 1156635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define BTPROTO_HCI 1 1157635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1158635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* Open HCI device. 1159635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Returns device descriptor (dd). */ 1160635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint hci_open_dev(int dev_id) 1161635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 1162635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct sockaddr_hci a; 1163635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int dd, err; 1164635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1165635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Create HCI socket */ 1166635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 1167635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (dd < 0) 1168635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return dd; 1169635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1170635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* Bind socket to the HCI device */ 1171635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch memset(&a, 0, sizeof(a)); 1172635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch a.hci_family = AF_BLUETOOTH; 1173635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch a.hci_dev = dev_id; 1174635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (bind(dd, (struct sockaddr *) &a, sizeof(a)) < 0) 1175635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch goto failed; 1176635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1177635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return dd; 1178635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1179635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschfailed: 1180635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch err = errno; 1181635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch close(dd); 1182635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch errno = err; 1183635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1184635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1185635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 1186635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1187635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint hci_close_dev(int dd) 1188635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 1189635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return close(dd); 1190635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 1191635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1192635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* HCI functions that require open device 1193635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * dd - Device descriptor returned by hci_open_dev. */ 1194635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1195635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint hci_send_cmd(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, void *param) 1196635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 1197635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch uint8_t type = HCI_COMMAND_PKT; 1198635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_command_hdr hc; 1199635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct iovec iv[3]; 1200635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int ivn; 1201635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1202635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hc.opcode = htobs(cmd_opcode_pack(ogf, ocf)); 1203635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hc.plen= plen; 1204635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1205635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch iv[0].iov_base = &type; 1206635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch iv[0].iov_len = 1; 1207635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch iv[1].iov_base = &hc; 1208635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch iv[1].iov_len = HCI_COMMAND_HDR_SIZE; 1209635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ivn = 2; 1210635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1211635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (plen) { 1212635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch iv[2].iov_base = param; 1213635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch iv[2].iov_len = plen; 1214635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ivn = 3; 1215635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1216635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1217635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch while (writev(dd, iv, ivn) < 0) { 1218635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (errno == EAGAIN || errno == EINTR) 1219635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch continue; 1220635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1221635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1222635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 1223635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 1224635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1225635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define HCI_SLEEP_CMD_OCF 0x04 1226635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define TIOCSETD 0x5423 1227635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define HCIUARTSETFLAGS _IOW('U', 204, int) 1228635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define HCIUARTSETPROTO _IOW('U', 200, int) 1229635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define HCIUARTGETDEVICE _IOW('U', 202, int) 1230635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* 1231635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * Atheros AR300x specific initialization post callback 1232635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch */ 1233635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint ath3k_post(int fd, int pm) 1234635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 1235635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int dev_id, dd; 1236635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct timespec tm = { 0, 50000}; 1237635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1238635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch sleep(1); 1239635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1240635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch dev_id = ioctl(fd, HCIUARTGETDEVICE, 0); 1241635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (dev_id < 0) { 1242635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch perror("cannot get device id"); 1243635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return dev_id; 1244635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1245635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1246635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch dd = hci_open_dev(dev_id); 1247635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (dd < 0) { 1248635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch perror("HCI device open failed"); 1249635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return dd; 1250635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1251635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1252635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) { 1253635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch perror("hci down:Power management Disabled"); 1254635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_close_dev(dd); 1255635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1256635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1257635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1258635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* send vendor specific command with Sleep feature Enabled */ 1259635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (hci_send_cmd(dd, OGF_VENDOR_CMD, HCI_SLEEP_CMD_OCF, 1, &pm) < 0) 1260635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch perror("PM command failed, power management Disabled"); 1261635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1262635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch nanosleep(&tm, NULL); 1263635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch hci_close_dev(dd); 1264635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1265635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return 0; 1266635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 1267635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1268635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1269635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1270635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define FLOW_CTL 0x0001 1271635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define ENABLE_PM 1 1272635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#define DISABLE_PM 0 1273635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1274635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch/* Initialize UART driver */ 1275635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschstatic int init_uart(char *dev, struct uart_t *u, int send_break, int raw) 1276635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 1277635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI(" %s ", __FUNCTION__); 1278635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1279635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct termios ti; 1280635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1281635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int i, fd; 1282635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch unsigned long flags = 0; 1283635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1284635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (raw) 1285635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch flags |= 1 << HCI_UART_RAW_DEVICE; 1286635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1287635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1288635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch fd = open(dev, O_RDWR | O_NOCTTY); 1289635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1290635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (fd < 0) { 1291635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Can't open serial port"); 1292635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1293635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1294635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1295635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1296635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tcflush(fd, TCIOFLUSH); 1297635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1298635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (tcgetattr(fd, &ti) < 0) { 1299635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Can't get port settings: %d\n", errno); 1300635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1301635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1302635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1303635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch cfmakeraw(&ti); 1304635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1305635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ti.c_cflag |= CLOCAL; 1306635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (u->flags & FLOW_CTL) 1307635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ti.c_cflag |= CRTSCTS; 1308635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 1309635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ti.c_cflag &= ~CRTSCTS; 1310635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1311635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (tcsetattr(fd, TCSANOW, &ti) < 0) { 1312635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Can't set port settings"); 1313635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1314635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1315635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1316635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (set_speed(fd, &ti, u->init_speed) < 0) { 1317635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Can't set initial baud rate"); 1318635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1319635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1320635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1321635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tcflush(fd, TCIOFLUSH); 1322635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1323635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (send_break) { 1324635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tcsendbreak(fd, 0); 1325635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch usleep(500000); 1326635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1327635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1328635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ath3k_init(fd,u->speed,u->init_speed,u->bdaddr, &ti); 1329635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1330635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Device setup complete\n"); 1331635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1332635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1333635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch tcflush(fd, TCIOFLUSH); 1334635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1335635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch // Set actual baudrate 1336635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* 1337635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (set_speed(fd, &ti, u->speed) < 0) { 1338635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch perror("Can't set baud rate"); 1339635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1340635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1341635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1342635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch i = N_HCI; 1343635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (ioctl(fd, TIOCSETD, &i) < 0) { 1344635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch perror("Can't set line discipline"); 1345635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1346635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1347635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1348635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) { 1349635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch perror("Can't set UART flags"); 1350635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1351635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1352635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1353635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) { 1354635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch perror("Can't set device"); 1355635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return -1; 1356635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1357635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1358635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#if !defined(SW_BOARD_HAVE_BLUETOOTH_RTK) 1359635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ath3k_post(fd, u->pm); 1360635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch#endif 1361635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch */ 1362635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1363635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return fd; 1364635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 1365635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1366635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1367635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschint hw_config_ath3k(char *port_name) 1368635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 1369635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI(" %s ", __FUNCTION__); 1370635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch PSCounter=0; 1371635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct sigaction sa; 1372635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch struct uart_t u ; 1373635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int n=0,send_break=0,raw=0; 1374635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1375635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch memset(&u, 0, sizeof(u)); 1376635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch u.speed =3000000; 1377635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch u.init_speed =115200; 1378635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch u.flags |= FLOW_CTL; 1379635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch u.pm = DISABLE_PM; 1380635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1381635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch n = init_uart(port_name, &u, send_break, raw); 1382635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (n < 0) { 1383635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("Can't initialize device"); 1384635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1385635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1386635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return n; 1387635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 1388635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1389635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetschvoid lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity) 1390635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch{ 1391635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int rc; 1392635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch int fd = -1; 1393635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch char buffer; 1394635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1395635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("lpm mode: %d action: %d", pio, action); 1396635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1397635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch RESERVED(polarity); 1398635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1399635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch switch (pio) 1400635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1401635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case UPIO_LPM_MODE: 1402635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (upio_state[UPIO_LPM_MODE] == action) 1403635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1404635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("LPM is %s already", lpm_mode[action]); 1405635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return; 1406635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1407635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1408635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY); 1409635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1410635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (fd < 0) 1411635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1412635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGE("upio_set : open(%s) for write failed: %s (%d)", 1413635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch VENDOR_LPM_PROC_NODE, strerror(errno), errno); 1414635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return; 1415635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1416635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1417635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (action == UPIO_ASSERT) 1418635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1419635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch buffer = '1'; 1420635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1421635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 1422635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1423635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch buffer = '0'; 1424635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1425635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1426635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write(fd, &buffer, 1) < 0) 1427635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1428635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGE("upio_set : write(%s) failed: %s (%d)", 1429635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch VENDOR_LPM_PROC_NODE, strerror(errno),errno); 1430635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1431635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 1432635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1433635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch upio_state[UPIO_LPM_MODE] = action; 1434635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("LPM is set to %s", lpm_mode[action]); 1435635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1436635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1437635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (fd >= 0) 1438635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch close(fd); 1439635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1440635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 1441635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1442635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case UPIO_BT_WAKE: 1443635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch /* UPIO_DEASSERT should be allowed because in Rx case assert occur 1444635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch * from the remote side where as deassert will be initiated from Host 1445635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch */ 1446635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if ((action == UPIO_ASSERT) && (upio_state[UPIO_BT_WAKE] == action)) 1447635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1448635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("BT_WAKE is %s already", lpm_state[action]); 1449635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1450635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return; 1451635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1452635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1453635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (action == UPIO_DEASSERT) 1454635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch buffer = '0'; 1455635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 1456635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch buffer = '1'; 1457635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1458635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY); 1459635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1460635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (fd < 0) 1461635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1462635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGE("upio_set : open(%s) for write failed: %s (%d)", 1463635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno); 1464635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch return; 1465635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1466635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1467635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (write(fd, &buffer, 1) < 0) 1468635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1469635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGE("upio_set : write(%s) failed: %s (%d)", 1470635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno); 1471635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1472635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch else 1473635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch { 1474635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch upio_state[UPIO_BT_WAKE] = action; 1475635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("BT_WAKE is set to %s", lpm_state[action]); 1476635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1477635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1478635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("proc btwrite assertion"); 1479635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1480635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch if (fd >= 0) 1481635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch close(fd); 1482635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1483635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 1484635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1485635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch case UPIO_HOST_WAKE: 1486635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch ALOGI("upio_set: UPIO_HOST_WAKE"); 1487635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch break; 1488635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch } 1489635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch 1490635682da6daf370cdba78511b917e166f0b6dbecSteve Pfetsch} 1491