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