13877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* 23877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * 33877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Copyright (c) 2013, The Linux Foundation. All rights reserved. 43877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Not a Contribution. 53877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * 63877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Copyright 2012 The Android Open Source Project 73877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * 83877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Licensed under the Apache License, Version 2.0 (the "License"); you 93877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * may not use this file except in compliance with the License. You may 103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * obtain a copy of the License at 113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * 123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * http://www.apache.org/licenses/LICENSE-2.0 133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * 143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Unless required by applicable law or agreed to in writing, software 153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * distributed under the License is distributed on an "AS IS" BASIS, 163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * implied. See the License for the specific language governing 183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * permissions and limitations under the License. 193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * 203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan */ 213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/****************************************************************************** 233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * 243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Filename: hw_ar3k.c 253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * 263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Description: Contains controller-specific functions, like 273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * firmware patch download 283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * low power mode operations 293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * 303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ******************************************************************************/ 313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#ifdef __cplusplus 323877697852db58569e9fab3aad46494bca561a9aMekala Natarajanextern "C" { 333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#endif 343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define LOG_TAG "bt_vendor" 363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <sys/socket.h> 383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <utils/Log.h> 393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <sys/types.h> 403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <sys/stat.h> 413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <signal.h> 423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <time.h> 433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <errno.h> 443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <fcntl.h> 453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <dirent.h> 463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <ctype.h> 473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <cutils/properties.h> 483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <stdlib.h> 493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <string.h> 503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include <termios.h> 513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include "bt_hci_bdroid.h" 533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include "hci_uart.h" 543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#include "hw_ar3k.h" 553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/****************************************************************************** 573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan** Variables 583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan******************************************************************************/ 593877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint cbstat = 0; 603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PATCH_LOC_STRING_LEN 8 613877697852db58569e9fab3aad46494bca561a9aMekala Natarajanchar ARbyte[3]; 623877697852db58569e9fab3aad46494bca561a9aMekala Natarajanchar ARptr[MAX_PATCH_CMD + 1]; 633877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint byte_cnt; 643877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint patch_count = 0; 653877697852db58569e9fab3aad46494bca561a9aMekala Natarajanchar patch_loc[PATCH_LOC_STRING_LEN + 1]; 663877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint PSCounter=0; 673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 683877697852db58569e9fab3aad46494bca561a9aMekala Natarajanuint32_t dev_type = 0; 693877697852db58569e9fab3aad46494bca561a9aMekala Natarajanuint32_t rom_version = 0; 703877697852db58569e9fab3aad46494bca561a9aMekala Natarajanuint32_t build_version = 0; 713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 723877697852db58569e9fab3aad46494bca561a9aMekala Natarajanchar patch_file[PATH_MAX]; 733877697852db58569e9fab3aad46494bca561a9aMekala Natarajanchar ps_file[PATH_MAX]; 743877697852db58569e9fab3aad46494bca561a9aMekala NatarajanFILE *stream; 753877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint tag_count=0; 763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* for friendly debugging outpout string */ 783877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic char *lpm_mode[] = { 793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan "UNKNOWN", 803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan "disabled", 813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan "enabled" 823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan}; 833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 843877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic char *lpm_state[] = { 853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan "UNKNOWN", 863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan "de-asserted", 873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan "asserted" 883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan}; 893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 903877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic uint8_t upio_state[UPIO_MAX_COUNT]; 913877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstruct ps_cfg_entry ps_list[MAX_TAGS]; 923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_EVENT_LEN 100 943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#ifdef __cplusplus 963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#endif 983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/***************************************************************************** 1003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan** Functions 1013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan*****************************************************************************/ 1023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1033877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint is_bt_soc_ath() { 1043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int ret = 0; 1053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char bt_soc_type[PROPERTY_VALUE_MAX]; 1063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL); 1073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (ret != 0) { 1083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type); 1093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!strncasecmp(bt_soc_type, "ath3k", sizeof("ath3k"))) 1103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 1; 1113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } else { 1123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("qcom.bluetooth.soc not set, so using default.\n"); 1133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 1143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 1163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 1173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* 1193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Send HCI command and wait for command complete event. 1203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * The event buffer has to be freed by the caller. 1213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan */ 1223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1233877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int send_hci_cmd_sync(int dev, uint8_t *cmd, int len, uint8_t **event) 1243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 1253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int err; 1263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *hci_event; 1273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t pkt_type = HCI_COMMAND_PKT; 1283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (len == 0) 1303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return len; 1313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write(dev, &pkt_type, 1) != 1) 1333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 1343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write(dev, (unsigned char *)cmd, len) != len) 1353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 1363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_event = (uint8_t *)malloc(PS_EVENT_LEN); 1383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!hci_event) 1393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -ENOMEM; 1403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = read_hci_event(dev, (unsigned char *)hci_event, PS_EVENT_LEN); 1423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err > 0) { 1433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan *event = hci_event; 1443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } else { 1453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan free(hci_event); 1463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 1473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 1483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return len; 1503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 1513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1523877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic void convert_bdaddr(char *str_bdaddr, char *bdaddr) 1533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 1543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char bdbyte[3]; 1553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char *str_byte = str_bdaddr; 1563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int i, j; 1573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int colon_present = 0; 1583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (strstr(str_bdaddr, ":")) 1603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan colon_present = 1; 1613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan bdbyte[2] = '\0'; 1633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Reverse the BDADDR to LSB first */ 1653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan for (i = 0, j = 5; i < 6; i++, j--) { 1663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan bdbyte[0] = str_byte[0]; 1673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan bdbyte[1] = str_byte[1]; 1683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan bdaddr[j] = strtol(bdbyte, NULL, 16); 1693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (colon_present == 1) 1713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan str_byte += 3; 1723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 1733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan str_byte += 2; 1743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 1753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 1763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 1773877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int uart_speed(int s) 1783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 1793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan switch (s) { 1803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 9600: 1813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B9600; 1823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 19200: 1833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B19200; 1843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 38400: 1853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B38400; 1863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 57600: 1873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B57600; 1883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 115200: 1893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B115200; 1903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 230400: 1913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B230400; 1923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 460800: 1933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B460800; 1943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 500000: 1953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B500000; 1963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 576000: 1973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B576000; 1983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 921600: 1993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B921600; 2003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 1000000: 2013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B1000000; 2023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 1152000: 2033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B1152000; 2043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 1500000: 2053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B1500000; 2063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 2000000: 2073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B2000000; 2083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#ifdef B2500000 2093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 2500000: 2103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B2500000; 2113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#endif 2123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#ifdef B3000000 2133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 3000000: 2143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B3000000; 2153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#endif 2163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#ifdef B3500000 2173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 3500000: 2183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B3500000; 2193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#endif 2203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#ifdef B4000000 2213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case 4000000: 2223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B4000000; 2233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#endif 2243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan default: 2253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return B57600; 2263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 2273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 2283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2293877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint set_speed(int fd, struct termios *ti, int speed) 2303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 2313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (cfsetospeed(ti, uart_speed(speed)) < 0) 2323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -errno; 2333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (cfsetispeed(ti, uart_speed(speed)) < 0) 2353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -errno; 2363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (tcsetattr(fd, TCSANOW, ti) < 0) 2383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -errno; 2393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 2413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 2423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2433877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic void load_hci_ps_hdr(uint8_t *cmd, uint8_t ps_op, int len, int index) 2443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 2453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_command_hdr *ch = (void *)cmd; 2463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 2483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan HCI_PS_CMD_OCF)); 2493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->plen = len + PS_HDR_LEN; 2503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd += HCI_COMMAND_HDR_SIZE; 2513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[0] = ps_op; 2533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[1] = index; 2543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[2] = index >> 8; 2553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[3] = len; 2563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 2573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2593877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int read_ps_event(uint8_t *event, uint16_t ocf) 2603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 2613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_event_hdr *eh; 2623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint16_t opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, ocf)); 2633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan event++; 2653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan eh = (void *)event; 2673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan event += HCI_EVENT_HDR_SIZE; 2683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (eh->evt == EVT_CMD_COMPLETE) { 2703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan evt_cmd_complete *cc = (void *)event; 2713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan event += EVT_CMD_COMPLETE_SIZE; 2733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (cc->opcode == opcode && event[0] == HCI_EV_SUCCESS) 2753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 2763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 2773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 2783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 2793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 2813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 2823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_WRITE 1 2843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_RESET 2 2853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define WRITE_PATCH 8 2863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define ENABLE_PATCH 11 2873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define HCI_PS_CMD_HDR_LEN 7 2893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2903877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int write_cmd(int fd, uint8_t *buffer, int len) 2913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 2923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *event; 2933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int err; 2943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = send_hci_cmd_sync(fd, buffer, len, &event); 2963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 2973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 2983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 2993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = read_ps_event(event, HCI_PS_CMD_OCF); 3003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan free(event); 3023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 3043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 3053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_RESET_PARAM_LEN 6 3073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_RESET_CMD_LEN (HCI_PS_CMD_HDR_LEN + PS_RESET_PARAM_LEN) 3083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_ID_MASK 0xFF 3103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* Sends PS commands using vendor specficic HCI commands */ 3123877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int write_ps_cmd(int fd, uint8_t opcode, uint32_t ps_param) 3133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 3143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t cmd[HCI_MAX_CMD_SIZE]; 3153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint32_t i; 3163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan switch (opcode) { 3183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case ENABLE_PATCH: 3193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan load_hci_ps_hdr(cmd, opcode, 0, 0x00); 3203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write_cmd(fd, cmd, HCI_PS_CMD_HDR_LEN) < 0) 3223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 3233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 3243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case PS_RESET: 3263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan load_hci_ps_hdr(cmd, opcode, PS_RESET_PARAM_LEN, 0x00); 3273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[7] = 0x00; 3293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[PS_RESET_CMD_LEN - 2] = ps_param & PS_ID_MASK; 3303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[PS_RESET_CMD_LEN - 1] = (ps_param >> 8) & PS_ID_MASK; 3313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write_cmd(fd, cmd, PS_RESET_CMD_LEN) < 0) 3333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 3343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 3353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case PS_WRITE: 3373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan for (i = 0; i < ps_param; i++) { 3383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan load_hci_ps_hdr(cmd, opcode, ps_list[i].len, 3393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ps_list[i].id); 3403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan memcpy(&cmd[HCI_PS_CMD_HDR_LEN], ps_list[i].data, 3423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ps_list[i].len); 3433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write_cmd(fd, cmd, ps_list[i].len + 3453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan HCI_PS_CMD_HDR_LEN) < 0) 3463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 3473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 3483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 3493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 3503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 3523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 3533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_ASIC_FILE "PS_ASIC.pst" 3553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_FPGA_FILE "PS_FPGA.pst" 3563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define MAXPATHLEN 4096 3573877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic void get_ps_file_name(uint32_t devtype, uint32_t rom_version,char *path) 3583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 3593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char *filename; 3603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (devtype == 0xdeadc0de) 3623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan filename = PS_ASIC_FILE; 3633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 3643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan filename = PS_FPGA_FILE; 3653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, filename); 3673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 3683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PATCH_FILE "RamPatch.txt" 3703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define FPGA_ROM_VERSION 0x99999999 3713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define ROM_DEV_TYPE 0xdeadc0de 3723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3733877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic void get_patch_file_name(uint32_t dev_type, uint32_t rom_version, 3743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint32_t build_version, char *path) 3753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 3763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (rom_version == FPGA_ROM_VERSION && dev_type != ROM_DEV_TYPE 3773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan &&dev_type != 0 && build_version == 1) 3783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan path[0] = '\0'; 3793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 3803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan snprintf(path, MAXPATHLEN, "%s%x/%s", FW_PATH, rom_version, PATCH_FILE); 3813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 3823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3833877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int set_cntrlr_baud(int fd, int speed) 3843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 3853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int baud; 3863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct timespec tm = { 0, 500000}; 3873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan unsigned char cmd[MAX_CMD_LEN], rsp[HCI_MAX_EVENT_SIZE]; 3883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan unsigned char *ptr = cmd + 1; 3893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_command_hdr *ch = (void *)ptr; 3903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[0] = HCI_COMMAND_PKT; 3923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 3933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* set controller baud rate to user specified value */ 3943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr = cmd + 1; 3953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 3963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan HCI_CHG_BAUD_CMD_OCF)); 3973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->plen = 2; 3983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr += HCI_COMMAND_HDR_SIZE; 3993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan baud = speed/100; 4013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[0] = (char)baud; 4023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[1] = (char)(baud >> 8); 4033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write(fd, cmd, WRITE_BAUD_CMD_LEN) != WRITE_BAUD_CMD_LEN) { 4053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Failed to write change baud rate command"); 4063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -ETIMEDOUT; 4073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 4083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan nanosleep(&tm, NULL); 4103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) 4123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -ETIMEDOUT; 4133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 4153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 4163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_UNDEF 0 4183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_ID 1 4193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_LEN 2 4203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_DATA 3 4213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_MAX_LEN 500 4233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define LINE_SIZE_MAX (PS_MAX_LEN * 2) 4243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define ENTRY_PER_LINE 16 4253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define __check_comment(buf) (((buf)[0] == '/') && ((buf)[1] == '/')) 4273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define __skip_space(str) while (*(str) == ' ') ((str)++) 4283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define __is_delim(ch) ((ch) == ':') 4313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define MAX_PREAMBLE_LEN 4 4323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* Parse PS entry preamble of format [X:X] for main type and subtype */ 4343877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int get_ps_type(char *ptr, int index, char *type, char *sub_type) 4353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 4363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int i; 4373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int delim = FALSE; 4383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (index > MAX_PREAMBLE_LEN) 4403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 4413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan for (i = 1; i < index; i++) { 4433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (__is_delim(ptr[i])) { 4443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan delim = TRUE; 4453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan continue; 4463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 4473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (isalpha(ptr[i])) { 4493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (delim == FALSE) 4503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan (*type) = toupper(ptr[i]); 4513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 4523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan (*sub_type) = toupper(ptr[i]); 4533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 4543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 4553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 4573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 4583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define ARRAY 'A' 4603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define STRING 'S' 4613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define DECIMAL 'D' 4623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define BINARY 'B' 4633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_HEX 0 4653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_DEC 1 4663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4673877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int get_input_format(char *buf, struct ps_entry_type *format) 4683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 4693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char *ptr = NULL; 4703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char type = '\0'; 4713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char sub_type = '\0'; 4723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan format->type = PS_HEX; 4743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan format->array = TRUE; 4753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (strstr(buf, "[") != buf) 4773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 4783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr = strstr(buf, "]"); 4803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!ptr) 4813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 4823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (get_ps_type(buf, ptr - buf, &type, &sub_type) < 0) 4843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 4853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Check is data type is of array */ 4873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (type == ARRAY || sub_type == ARRAY) 4883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan format->array = TRUE; 4893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (type == STRING || sub_type == STRING) 4913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan format->array = FALSE; 4923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (type == DECIMAL || type == BINARY) 4943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan format->type = PS_DEC; 4953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 4963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan format->type = PS_HEX; 4973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 4983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 4993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 5003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define UNDEFINED 0xFFFF 5043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5053877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic unsigned int read_data_in_section(char *buf, struct ps_entry_type type) 5063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 5073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char *ptr = buf; 5083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!buf) 5103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return UNDEFINED; 5113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (buf == strstr(buf, "[")) { 5133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr = strstr(buf, "]"); 5143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!ptr) 5153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return UNDEFINED; 5163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr++; 5183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 5193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (type.type == PS_HEX && type.array != TRUE) 5213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return strtol(ptr, NULL, 16); 5223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return UNDEFINED; 5243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 5253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* Read PS entries as string, convert and add to Hex array */ 5283877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic void update_tag_data(struct ps_cfg_entry *tag, 5293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct tag_info *info, const char *ptr) 5303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 5313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char buf[3]; 5323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan buf[2] = '\0'; 5343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan strlcpy(buf, &ptr[info->char_cnt],sizeof(buf)); 5363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tag->data[info->byte_count] = strtol(buf, NULL, 16); 5373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan info->char_cnt += 3; 5383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan info->byte_count++; 5393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan strlcpy(buf, &ptr[info->char_cnt], sizeof(buf)); 5413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tag->data[info->byte_count] = strtol(buf, NULL, 16); 5423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan info->char_cnt += 3; 5433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan info->byte_count++; 5443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 5453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5463877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic inline int update_char_count(const char *buf) 5473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 5483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char *end_ptr; 5493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (strstr(buf, "[") == buf) { 5513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan end_ptr = strstr(buf, "]"); 5523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!end_ptr) 5533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 5543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 5553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return(end_ptr - buf) + 1; 5563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 5573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 5593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 5603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_HEX 0 5623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_DEC 1 5633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5643877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int ath_parse_ps(FILE *stream) 5653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 5663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char buf[LINE_SIZE_MAX + 1]; 5673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char *ptr; 5683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t tag_cnt = 0; 5693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int16_t byte_count = 0; 5703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct ps_entry_type format; 5713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct tag_info status = { 0, 0, 0, 0}; 5723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan do { 5743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int read_count; 5753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct ps_cfg_entry *tag; 5763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr = fgets(buf, LINE_SIZE_MAX, stream); 5783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!ptr) 5793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 5803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan __skip_space(ptr); 5823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (__check_comment(ptr)) 5833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan continue; 5843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Lines with a '#' will be followed by new PS entry */ 5863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (ptr == strstr(ptr, "#")) { 5873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (status.section != PS_UNDEF) { 5883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 5893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } else { 5903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status.section = PS_ID; 5913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan continue; 5923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 5933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 5943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tag = &ps_list[tag_cnt]; 5963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 5973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan switch (status.section) { 5983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case PS_ID: 5993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (get_input_format(ptr, &format) < 0) 6003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 6013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tag->id = read_data_in_section(ptr, format); 6033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status.section = PS_LEN; 6043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 6053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case PS_LEN: 6073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (get_input_format(ptr, &format) < 0) 6083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 6093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan byte_count = read_data_in_section(ptr, format); 6113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (byte_count > PS_MAX_LEN) 6123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 6133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tag->len = byte_count; 6153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tag->data = (uint8_t *)malloc(byte_count); 6163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status.section = PS_DATA; 6183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status.line_count = 0; 6193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 6203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case PS_DATA: 6223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (status.line_count == 0) 6233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (get_input_format(ptr, &format) < 0) 6243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 6253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan __skip_space(ptr); 6273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status.char_cnt = update_char_count(ptr); 6293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan read_count = (byte_count > ENTRY_PER_LINE) ? 6313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ENTRY_PER_LINE : byte_count; 6323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (format.type == PS_HEX && format.array == TRUE) { 6343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan while (read_count > 0) { 6353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan update_tag_data(tag, &status, ptr); 6363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan read_count -= 2; 6373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 6383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (byte_count > ENTRY_PER_LINE) 6403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan byte_count -= ENTRY_PER_LINE; 6413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 6423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan byte_count = 0; 6433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 6443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status.line_count++; 6463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (byte_count == 0) 6483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan memset(&status, 0x00, sizeof(struct tag_info)); 6493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (status.section == PS_UNDEF) 6513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tag_cnt++; 6523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (tag_cnt == MAX_TAGS) 6543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -EILSEQ; 6553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 6563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 6573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } while (ptr); 6583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return tag_cnt; 6603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 6613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_RAM_SIZE 2048 6633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6643877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int ps_config_download(int fd, int tag_count) 6653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 6663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write_ps_cmd(fd, PS_RESET, PS_RAM_SIZE) < 0) 6673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 6683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (tag_count > 0) 6703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write_ps_cmd(fd, PS_WRITE, tag_count) < 0) 6713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 6723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 6733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 6743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6753877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int write_bdaddr(int pConfig, char *bdaddr) 6763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 6773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *event; 6783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int err; 6793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t cmd[13]; 6803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *ptr = cmd; 6813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_command_hdr *ch = (void *)cmd; 6823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan memset(cmd, 0, sizeof(cmd)); 6843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 6863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan HCI_PS_CMD_OCF)); 6873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->plen = 10; 6883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr += HCI_COMMAND_HDR_SIZE; 6893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[0] = 0x01; 6913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[1] = 0x01; 6923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[2] = 0x00; 6933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[3] = 0x06; 6943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan convert_bdaddr(bdaddr, (char *)&ptr[4]); 6963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 6973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event); 6983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 6993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 7003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = read_ps_event(event, HCI_PS_CMD_OCF); 7023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan free(event); 7043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 7063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 7073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7083877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic void write_bdaddr_from_file(int rom_version, int fd) 7093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 7103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan FILE *stream; 7113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char bdaddr[PATH_MAX]; 7123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char bdaddr_file[PATH_MAX]; 7133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan snprintf(bdaddr_file, MAXPATHLEN, "%s%x/%s", 7153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan FW_PATH, rom_version, BDADDR_FILE); 7163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan stream = fopen(bdaddr_file, "r"); 7183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!stream) 7193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return; 7203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (fgets(bdaddr, PATH_MAX - 1, stream)) 7223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan write_bdaddr(fd, bdaddr); 7233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan fclose(stream); 7253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 7263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define HCI_EVT_CMD_CMPL_OPCODE 3 7283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define HCI_EVT_CMD_CMPL_STATUS_RET_BYTE 5 7293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7303877697852db58569e9fab3aad46494bca561a9aMekala Natarajanvoid baswap(bdaddr_t *dst, const bdaddr_t *src) 7313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 7323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan register unsigned char *d = (unsigned char *) dst; 7333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan register const unsigned char *s = (const unsigned char *) src; 7343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan register int i; 7353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan for (i = 0; i < 6; i++) 7363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan d[i] = s[5-i]; 7373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 7383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7403877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint str2ba(const char *str, bdaddr_t *ba) 7413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 7423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t b[6]; 7433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan const char *ptr = str; 7443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int i; 7453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan for (i = 0; i < 6; i++) { 7473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan b[i] = (uint8_t) strtol(ptr, NULL, 16); 7483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr = strchr(ptr, ':'); 7493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (i != 5 && !ptr) 7503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr = ":00:00:00:00:00"; 7513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr++; 7523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 7533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan baswap(ba, (bdaddr_t *) b); 7543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 7553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 7563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define DEV_REGISTER 0x4FFC 7583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define GET_DEV_TYPE_OCF 0x05 7593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7603877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int get_device_type(int dev, uint32_t *code) 7613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 7623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t cmd[8] = {0}; 7633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *event; 7643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint32_t reg; 7653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int err; 7663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *ptr = cmd; 7673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_command_hdr *ch = (void *)cmd; 7683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 7703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan GET_DEV_TYPE_OCF)); 7713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->plen = 5; 7723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr += HCI_COMMAND_HDR_SIZE; 7733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[0] = (uint8_t)DEV_REGISTER; 7753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[1] = (uint8_t)DEV_REGISTER >> 8; 7763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[2] = (uint8_t)DEV_REGISTER >> 16; 7773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[3] = (uint8_t)DEV_REGISTER >> 24; 7783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[4] = 0x04; 7793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event); 7813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 7823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 7833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = read_ps_event(event, GET_DEV_TYPE_OCF); 7853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 7863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto cleanup; 7873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan reg = event[10]; 7893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan reg = (reg << 8) | event[9]; 7903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan reg = (reg << 8) | event[8]; 7913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan reg = (reg << 8) | event[7]; 7923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan *code = reg; 7933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7943877697852db58569e9fab3aad46494bca561a9aMekala Natarajancleanup: 7953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan free(event); 7963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 7973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 7983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 7993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define GET_VERSION_OCF 0x1E 8013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8023877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int read_ath3k_version(int pConfig, uint32_t *rom_version, 8033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint32_t *build_version) 8043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 8053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t cmd[3] = {0}; 8063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *event; 8073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int err; 8083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int status; 8093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_command_hdr *ch = (void *)cmd; 8103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 8123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan GET_VERSION_OCF)); 8133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->plen = 0; 8143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = send_hci_cmd_sync(pConfig, cmd, sizeof(cmd), &event); 8163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 8173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 8183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = read_ps_event(event, GET_VERSION_OCF); 8203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 8213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto cleanup; 8223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status = event[10]; 8243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status = (status << 8) | event[9]; 8253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status = (status << 8) | event[8]; 8263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status = (status << 8) | event[7]; 8273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan *rom_version = status; 8283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status = event[14]; 8303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status = (status << 8) | event[13]; 8313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status = (status << 8) | event[12]; 8323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan status = (status << 8) | event[11]; 8333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan *build_version = status; 8343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8353877697852db58569e9fab3aad46494bca561a9aMekala Natarajancleanup: 8363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan free(event); 8373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 8393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 8403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define VERIFY_CRC 9 8423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PS_REGION 1 8433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PATCH_REGION 2 8443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8453877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int get_ath3k_crc(int dev) 8463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 8473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t cmd[7] = {0}; 8483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *event; 8493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int err; 8503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan load_hci_ps_hdr(cmd, VERIFY_CRC, 0, PS_REGION | PATCH_REGION); 8523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = send_hci_cmd_sync(dev, cmd, sizeof(cmd), &event); 8543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 8553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 8563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Send error code if CRC check patched */ 8573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (read_ps_event(event, HCI_PS_CMD_OCF) >= 0) 8583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -EILSEQ; 8593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan free(event); 8613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 8633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 8643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define SET_PATCH_RAM_ID 0x0D 8663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define SET_PATCH_RAM_CMD_SIZE 11 8673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define ADDRESS_LEN 4 8683877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int set_patch_ram(int dev, char *patch_loc, int len) 8693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 8703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int err; 8713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t cmd[20] = {0}; 8723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int i, j; 8733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char loc_byte[3]; 8743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *event; 8753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t *loc_ptr = &cmd[7]; 8763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!patch_loc) 8783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 8793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan loc_byte[2] = '\0'; 8813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan load_hci_ps_hdr(cmd, SET_PATCH_RAM_ID, ADDRESS_LEN, 0); 8833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan for (i = 0, j = 3; i < 4; i++, j--) { 8853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan loc_byte[0] = patch_loc[0]; 8863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan loc_byte[1] = patch_loc[1]; 8873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan loc_ptr[j] = strtol(loc_byte, NULL, 16); 8883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan patch_loc += 2; 8893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 8903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = send_hci_cmd_sync(dev, cmd, SET_PATCH_RAM_CMD_SIZE, &event); 8923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 8933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 8943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = read_ps_event(event, HCI_PS_CMD_OCF); 8963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan free(event); 8983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 8993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 9003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 9013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PATCH_LOC_KEY "DA:" 9033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define PATCH_LOC_STRING_LEN 8 9043877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int ps_patch_download(int fd, FILE *stream) 9053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 9063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char byte[3]; 9073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char ptr[MAX_PATCH_CMD + 1]; 9083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int byte_cnt; 9093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int patch_count = 0; 9103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char patch_loc[PATCH_LOC_STRING_LEN + 1]; 9113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan byte[2] = '\0'; 9133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan while (fgets(ptr, MAX_PATCH_CMD, stream)) { 9153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (strlen(ptr) <= 1) 9163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan continue; 9173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else if (strstr(ptr, PATCH_LOC_KEY) == ptr) { 9183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan strlcpy(patch_loc, &ptr[sizeof(PATCH_LOC_KEY) - 1], 9193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan PATCH_LOC_STRING_LEN); 9203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (set_patch_ram(fd, patch_loc, sizeof(patch_loc)) < 0) 9213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 9223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } else if (isxdigit(ptr[0])) 9233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 9243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 9253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 9263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 9273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan byte_cnt = strtol(ptr, NULL, 16); 9293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan while (byte_cnt > 0) { 9313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int i; 9323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t cmd[HCI_MAX_CMD_SIZE] = {0}; 9333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct patch_entry patch; 9343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (byte_cnt > MAX_PATCH_CMD) 9363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan patch.len = MAX_PATCH_CMD; 9373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 9383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan patch.len = byte_cnt; 9393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan for (i = 0; i < patch.len; i++) { 9413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!fgets(byte, 3, stream)) 9423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 9433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan patch.data[i] = strtoul(byte, NULL, 16); 9453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 9463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan load_hci_ps_hdr(cmd, WRITE_PATCH, patch.len, patch_count); 9483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan memcpy(&cmd[HCI_PS_CMD_HDR_LEN], patch.data, patch.len); 9493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write_cmd(fd, cmd, patch.len + HCI_PS_CMD_HDR_LEN) < 0) 9513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 9523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan patch_count++; 9543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan byte_cnt = byte_cnt - MAX_PATCH_CMD; 9553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 9563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write_ps_cmd(fd, ENABLE_PATCH, 0) < 0) 9583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 9593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return patch_count; 9613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 9623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9633877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int ath_ps_download(int fd) 9643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 9653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int err = 0; 9663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int tag_count; 9673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int patch_count = 0; 9683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint32_t rom_version = 0; 9693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint32_t build_version = 0; 9703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint32_t dev_type = 0; 9713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char patch_file[PATH_MAX]; 9723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char ps_file[PATH_MAX]; 9733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan FILE *stream; 9743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* 9763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Verfiy firmware version. depending on it select the PS 9773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * config file to download. 9783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan */ 9793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (get_device_type(fd, &dev_type) < 0) { 9803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -EILSEQ; 9813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto download_cmplete; 9823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 9833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (read_ath3k_version(fd, &rom_version, &build_version) < 0) { 9853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -EILSEQ; 9863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto download_cmplete; 9873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 9883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Do not download configuration if CRC passes */ 9903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (get_ath3k_crc(fd) < 0) { 9913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = 0; 9923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto download_cmplete; 9933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 9943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan get_ps_file_name(dev_type, rom_version, ps_file); 9963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan get_patch_file_name(dev_type, rom_version, build_version, patch_file); 9973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 9983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan stream = fopen(ps_file, "r"); 9993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!stream) { 10003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("firmware file open error:%s, ver:%x\n",ps_file, rom_version); 10013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (rom_version == 0x1020201) 10023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = 0; 10033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 10043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -EILSEQ; 10053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto download_cmplete; 10063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 10073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tag_count = ath_parse_ps(stream); 10083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan fclose(stream); 10103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (tag_count < 0) { 10123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -EILSEQ; 10133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto download_cmplete; 10143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 10153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* 10173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * It is not necessary that Patch file be available, 10183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * continue with PS Operations if patch file is not available. 10193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan */ 10203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (patch_file[0] == '\0') 10213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = 0; 10223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan stream = fopen(patch_file, "r"); 10243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!stream) 10253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = 0; 10263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else { 10273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan patch_count = ps_patch_download(fd, stream); 10283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan fclose(stream); 10293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (patch_count < 0) { 10313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -EILSEQ; 10323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto download_cmplete; 10333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 10343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 10353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = ps_config_download(fd, tag_count); 10373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10383877697852db58569e9fab3aad46494bca561a9aMekala Natarajandownload_cmplete: 10393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (!err) 10403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan write_bdaddr_from_file(rom_version, fd); 10413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 10433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 10443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10453877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti) 10463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 10473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI(" %s ", __FUNCTION__); 10483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int r; 10503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int err = 0; 10513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct timespec tm = { 0, 500000}; 10523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan unsigned char cmd[MAX_CMD_LEN] = {0}; 10533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan unsigned char rsp[HCI_MAX_EVENT_SIZE]; 10543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan unsigned char *ptr = cmd + 1; 10553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_command_hdr *ch = (void *)ptr; 10563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int flags = 0; 10573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (ioctl(fd, TIOCMGET, &flags) < 0) { 10593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("TIOCMGET failed in init\n"); 10603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 10613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 10623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan flags |= TIOCM_RTS; 10633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (ioctl(fd, TIOCMSET, &flags) < 0) { 10643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("TIOCMSET failed in init: HW Flow-on error\n"); 10653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 10663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 10673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* set both controller and host baud rate to maximum possible value */ 10693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = set_cntrlr_baud(fd, speed); 10703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("set_cntrlr_baud : ret:%d \n", err); 10713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 10723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 10733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = set_speed(fd, ti, speed); 10753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) { 10763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Can't set required baud rate"); 10773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 10783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 10793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Download PS and patch */ 10813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan r = ath_ps_download(fd); 10823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (r < 0) { 10833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Failed to Download configuration"); 10843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -ETIMEDOUT; 10853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto failed; 10863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 10873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("ath_ps_download is done\n"); 10893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[0] = HCI_COMMAND_PKT; 10913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Write BDADDR */ 10923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (bdaddr) { 10933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->opcode = htobs(cmd_opcode_pack(HCI_VENDOR_CMD_OGF, 10943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan HCI_PS_CMD_OCF)); 10953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ch->plen = 10; 10963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr += HCI_COMMAND_HDR_SIZE; 10973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 10983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[0] = 0x01; 10993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[1] = 0x01; 11003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[2] = 0x00; 11013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ptr[3] = 0x06; 11023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan str2ba(bdaddr, (bdaddr_t *)(ptr + 4)); 11033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write(fd, cmd, WRITE_BDADDR_CMD_LEN) != 11053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan WRITE_BDADDR_CMD_LEN) { 11063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Failed to write BD_ADDR command\n"); 11073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -ETIMEDOUT; 11083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto failed; 11093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 11103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) { 11123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Failed to set BD_ADDR\n"); 11133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -ETIMEDOUT; 11143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto failed; 11153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 11163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 11173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Send HCI Reset */ 11193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[1] = 0x03; 11203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[2] = 0x0C; 11213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cmd[3] = 0x00; 11223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan r = write(fd, cmd, 4); 11243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (r != 4) { 11253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -ETIMEDOUT; 11263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto failed; 11273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 11283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan nanosleep(&tm, NULL); 11303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (read_hci_event(fd, rsp, sizeof(rsp)) < 0) { 11313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = -ETIMEDOUT; 11323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto failed; 11333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 11343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("HCI Reset is done\n"); 11363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = set_cntrlr_baud(fd, speed); 11373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) 11383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("set_cntrlr_baud0:%d,%d\n", speed, err); 11393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11403877697852db58569e9fab3aad46494bca561a9aMekala Natarajanfailed: 11413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (err < 0) { 11423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan set_cntrlr_baud(fd, init_speed); 11433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan set_speed(fd, ti, init_speed); 11443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 11453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return err; 11473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 11493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define BTPROTO_HCI 1 11503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* Open HCI device. 11523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Returns device descriptor (dd). */ 11533877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint hci_open_dev(int dev_id) 11543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 11553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct sockaddr_hci a; 11563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int dd, err; 11573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Create HCI socket */ 11593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 11603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (dd < 0) 11613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return dd; 11623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* Bind socket to the HCI device */ 11643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan memset(&a, 0, sizeof(a)); 11653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan a.hci_family = AF_BLUETOOTH; 11663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan a.hci_dev = dev_id; 11673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (bind(dd, (struct sockaddr *) &a, sizeof(a)) < 0) 11683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan goto failed; 11693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return dd; 11713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11723877697852db58569e9fab3aad46494bca561a9aMekala Natarajanfailed: 11733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan err = errno; 11743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan close(dd); 11753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan errno = err; 11763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 11783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 11793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11803877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint hci_close_dev(int dd) 11813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 11823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return close(dd); 11833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 11843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* HCI functions that require open device 11863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * dd - Device descriptor returned by hci_open_dev. */ 11873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11883877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint hci_send_cmd(int dd, uint16_t ogf, uint16_t ocf, uint8_t plen, void *param) 11893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 11903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan uint8_t type = HCI_COMMAND_PKT; 11913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_command_hdr hc; 11923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct iovec iv[3]; 11933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int ivn; 11943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hc.opcode = htobs(cmd_opcode_pack(ogf, ocf)); 11963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hc.plen= plen; 11973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 11983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan iv[0].iov_base = &type; 11993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan iv[0].iov_len = 1; 12003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan iv[1].iov_base = &hc; 12013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan iv[1].iov_len = HCI_COMMAND_HDR_SIZE; 12023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ivn = 2; 12033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (plen) { 12053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan iv[2].iov_base = param; 12063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan iv[2].iov_len = plen; 12073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ivn = 3; 12083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 12093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan while (writev(dd, iv, ivn) < 0) { 12113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (errno == EAGAIN || errno == EINTR) 12123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan continue; 12133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 12143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 12153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 12163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 12173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define HCI_SLEEP_CMD_OCF 0x04 12193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define TIOCSETD 0x5423 12203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define HCIUARTSETFLAGS _IOW('U', 204, int) 12213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define HCIUARTSETPROTO _IOW('U', 200, int) 12223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define HCIUARTGETDEVICE _IOW('U', 202, int) 12233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* 12243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * Atheros AR300x specific initialization post callback 12253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan */ 12263877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint ath3k_post(int fd, int pm) 12273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 12283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int dev_id, dd; 12293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct timespec tm = { 0, 50000}; 12303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan sleep(1); 12323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan dev_id = ioctl(fd, HCIUARTGETDEVICE, 0); 12343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (dev_id < 0) { 12353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan perror("cannot get device id"); 12363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return dev_id; 12373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 12383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan dd = hci_open_dev(dev_id); 12403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (dd < 0) { 12413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan perror("HCI device open failed"); 12423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return dd; 12433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 12443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) { 12463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan perror("hci down:Power management Disabled"); 12473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_close_dev(dd); 12483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 12493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 12503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* send vendor specific command with Sleep feature Enabled */ 12523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (hci_send_cmd(dd, OGF_VENDOR_CMD, HCI_SLEEP_CMD_OCF, 1, &pm) < 0) 12533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan perror("PM command failed, power management Disabled"); 12543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan nanosleep(&tm, NULL); 12563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan hci_close_dev(dd); 12573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return 0; 12593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 12603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define FLOW_CTL 0x0001 12643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define ENABLE_PM 1 12653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#define DISABLE_PM 0 12663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan/* Initialize UART driver */ 12683877697852db58569e9fab3aad46494bca561a9aMekala Natarajanstatic int init_uart(char *dev, struct uart_t *u, int send_break, int raw) 12693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 12703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI(" %s ", __FUNCTION__); 12713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct termios ti; 12733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int i, fd; 12753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan unsigned long flags = 0; 12763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (raw) 12783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan flags |= 1 << HCI_UART_RAW_DEVICE; 12793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan fd = open(dev, O_RDWR | O_NOCTTY); 12823877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (fd < 0) { 12843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Can't open serial port"); 12853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 12863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 12873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tcflush(fd, TCIOFLUSH); 12903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (tcgetattr(fd, &ti) < 0) { 12923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Can't get port settings: %d\n", errno); 12933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 12943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 12953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan cfmakeraw(&ti); 12973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 12983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ti.c_cflag |= CLOCAL; 12993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (u->flags & FLOW_CTL) 13003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ti.c_cflag |= CRTSCTS; 13013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 13023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ti.c_cflag &= ~CRTSCTS; 13033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (tcsetattr(fd, TCSANOW, &ti) < 0) { 13053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Can't set port settings"); 13063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 13073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 13083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (set_speed(fd, &ti, u->init_speed) < 0) { 13103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Can't set initial baud rate"); 13113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 13123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 13133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tcflush(fd, TCIOFLUSH); 13153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (send_break) { 13173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tcsendbreak(fd, 0); 13183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan usleep(500000); 13193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 13203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ath3k_init(fd,u->speed,u->init_speed,u->bdaddr, &ti); 13223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Device setup complete\n"); 13243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan tcflush(fd, TCIOFLUSH); 13273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan // Set actual baudrate 13293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* 13303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (set_speed(fd, &ti, u->speed) < 0) { 13313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan perror("Can't set baud rate"); 13323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 13333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 13343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan i = N_HCI; 13363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (ioctl(fd, TIOCSETD, &i) < 0) { 13373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan perror("Can't set line discipline"); 13383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 13393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 13403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) { 13423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan perror("Can't set UART flags"); 13433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 13443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 13453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) { 13473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan perror("Can't set device"); 13483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return -1; 13493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 13503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#if !defined(SW_BOARD_HAVE_BLUETOOTH_RTK) 13523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ath3k_post(fd, u->pm); 13533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan#endif 13543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan */ 13553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return fd; 13573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 13583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13603877697852db58569e9fab3aad46494bca561a9aMekala Natarajanint hw_config_ath3k(char *port_name) 13613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 13623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI(" %s ", __FUNCTION__); 13633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan PSCounter=0; 13643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct sigaction sa; 13653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan struct uart_t u ; 13663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int n=0,send_break=0,raw=0; 13673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan memset(&u, 0, sizeof(u)); 13693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan u.speed =3000000; 13703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan u.init_speed =115200; 13713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan u.flags |= FLOW_CTL; 13723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan u.pm = DISABLE_PM; 13733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan n = init_uart(port_name, &u, send_break, raw); 13753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (n < 0) { 13763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("Can't initialize device"); 13773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 13783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return n; 13803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 13813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13823877697852db58569e9fab3aad46494bca561a9aMekala Natarajanvoid lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity) 13833877697852db58569e9fab3aad46494bca561a9aMekala Natarajan{ 13843877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int rc; 13853877697852db58569e9fab3aad46494bca561a9aMekala Natarajan int fd = -1; 13863877697852db58569e9fab3aad46494bca561a9aMekala Natarajan char buffer; 13873877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13883877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("lpm mode: %d action: %d", pio, action); 13893877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13903877697852db58569e9fab3aad46494bca561a9aMekala Natarajan switch (pio) 13913877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 13923877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case UPIO_LPM_MODE: 13933877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (upio_state[UPIO_LPM_MODE] == action) 13943877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 13953877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("LPM is %s already", lpm_mode[action]); 13963877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return; 13973877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 13983877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 13993877697852db58569e9fab3aad46494bca561a9aMekala Natarajan fd = open(VENDOR_LPM_PROC_NODE, O_WRONLY); 14003877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14013877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (fd < 0) 14023877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 14033877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGE("upio_set : open(%s) for write failed: %s (%d)", 14043877697852db58569e9fab3aad46494bca561a9aMekala Natarajan VENDOR_LPM_PROC_NODE, strerror(errno), errno); 14053877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return; 14063877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14073877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14083877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (action == UPIO_ASSERT) 14093877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 14103877697852db58569e9fab3aad46494bca561a9aMekala Natarajan buffer = '1'; 14113877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14123877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 14133877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 14143877697852db58569e9fab3aad46494bca561a9aMekala Natarajan buffer = '0'; 14153877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14163877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14173877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write(fd, &buffer, 1) < 0) 14183877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 14193877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGE("upio_set : write(%s) failed: %s (%d)", 14203877697852db58569e9fab3aad46494bca561a9aMekala Natarajan VENDOR_LPM_PROC_NODE, strerror(errno),errno); 14213877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14223877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 14233877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 14243877697852db58569e9fab3aad46494bca561a9aMekala Natarajan upio_state[UPIO_LPM_MODE] = action; 14253877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("LPM is set to %s", lpm_mode[action]); 14263877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14273877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14283877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (fd >= 0) 14293877697852db58569e9fab3aad46494bca561a9aMekala Natarajan close(fd); 14303877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14313877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 14323877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14333877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case UPIO_BT_WAKE: 14343877697852db58569e9fab3aad46494bca561a9aMekala Natarajan /* UPIO_DEASSERT should be allowed because in Rx case assert occur 14353877697852db58569e9fab3aad46494bca561a9aMekala Natarajan * from the remote side where as deassert will be initiated from Host 14363877697852db58569e9fab3aad46494bca561a9aMekala Natarajan */ 14373877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if ((action == UPIO_ASSERT) && (upio_state[UPIO_BT_WAKE] == action)) 14383877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 14393877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("BT_WAKE is %s already", lpm_state[action]); 14403877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14413877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return; 14423877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14433877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14443877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (action == UPIO_DEASSERT) 14453877697852db58569e9fab3aad46494bca561a9aMekala Natarajan buffer = '0'; 14463877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 14473877697852db58569e9fab3aad46494bca561a9aMekala Natarajan buffer = '1'; 14483877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14493877697852db58569e9fab3aad46494bca561a9aMekala Natarajan fd = open(VENDOR_BTWRITE_PROC_NODE, O_WRONLY); 14503877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14513877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (fd < 0) 14523877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 14533877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGE("upio_set : open(%s) for write failed: %s (%d)", 14543877697852db58569e9fab3aad46494bca561a9aMekala Natarajan VENDOR_BTWRITE_PROC_NODE, strerror(errno), errno); 14553877697852db58569e9fab3aad46494bca561a9aMekala Natarajan return; 14563877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14573877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14583877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (write(fd, &buffer, 1) < 0) 14593877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 14603877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGE("upio_set : write(%s) failed: %s (%d)", 14613877697852db58569e9fab3aad46494bca561a9aMekala Natarajan VENDOR_BTWRITE_PROC_NODE, strerror(errno),errno); 14623877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14633877697852db58569e9fab3aad46494bca561a9aMekala Natarajan else 14643877697852db58569e9fab3aad46494bca561a9aMekala Natarajan { 14653877697852db58569e9fab3aad46494bca561a9aMekala Natarajan upio_state[UPIO_BT_WAKE] = action; 14663877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("BT_WAKE is set to %s", lpm_state[action]); 14673877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14683877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14693877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("proc btwrite assertion"); 14703877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14713877697852db58569e9fab3aad46494bca561a9aMekala Natarajan if (fd >= 0) 14723877697852db58569e9fab3aad46494bca561a9aMekala Natarajan close(fd); 14733877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14743877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 14753877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14763877697852db58569e9fab3aad46494bca561a9aMekala Natarajan case UPIO_HOST_WAKE: 14773877697852db58569e9fab3aad46494bca561a9aMekala Natarajan ALOGI("upio_set: UPIO_HOST_WAKE"); 14783877697852db58569e9fab3aad46494bca561a9aMekala Natarajan break; 14793877697852db58569e9fab3aad46494bca561a9aMekala Natarajan } 14803877697852db58569e9fab3aad46494bca561a9aMekala Natarajan 14813877697852db58569e9fab3aad46494bca561a9aMekala Natarajan} 1482