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