10ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/*
20ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Copyright 2012 The Android Open Source Project
30ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Copyright (c) 2013, The Linux Foundation. All rights reserved.
40ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Not a Contribution.
50ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
60ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Licensed under the Apache License, Version 2.0 (the "License");
70ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * you may not use this file except in compliance with the License.
80ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * You may obtain a copy of the License at
90ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *      http://www.apache.org/licenses/LICENSE-2.0
110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * Unless required by applicable law or agreed to in writing, software
130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * distributed under the License is distributed on an "AS IS" BASIS,
140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * See the License for the specific language governing permissions and
160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel * limitations under the License.
170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel */
180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/******************************************************************************
200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *  Filename:      bt_vendor_qcom.c
220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *  Description:   vendor specific library implementation
240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel *
250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel ******************************************************************************/
260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define LOG_TAG "bt_vendor"
270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define BLUETOOTH_MAC_ADDR_BOOT_PROPERTY "ro.boot.btmacaddr"
280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <utils/Log.h>
300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <cutils/properties.h>
310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <fcntl.h>
320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <termios.h>
330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "bt_vendor_qcom.h"
340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "hci_uart.h"
350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "hci_smd.h"
36bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel#include <sys/ioctl.h>
370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <sys/socket.h>
380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <cutils/sockets.h>
390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <linux/un.h>
400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "bt_vendor_persist.h"
410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "hw_rome.h"
420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "bt_vendor_lib.h"
430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define WAIT_TIMEOUT 200000
440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define BT_VND_OP_GET_LINESPEED 30
450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define STOP_WCNSS_FILTER 0xDD
4741464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel#define STOP_WAIT_TIMEOUT   1000
480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define SOC_INIT_PROPERTY "wc_transport.soc_initialized"
500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define BT_VND_FILTER_START "wc_transport.start_hci"
520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define CMD_TIMEOUT  0x22
540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic void wait_for_patch_download(bool is_ant_req);
560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic bool is_debug_force_special_bytes(void);
570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint connect_to_local_socket(char* name);
580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/******************************************************************************
590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**  Externs
600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel******************************************************************************/
610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelextern int hw_config(int nState);
620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelextern int is_hw_ready();
630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelextern int chipset_ver;
640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/******************************************************************************
660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**  Variables
670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel******************************************************************************/
685752ddcecf884adefc166873565da60e70f59400Thierry Strudelstruct bt_qcom_struct *q = NULL;
6920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelpthread_mutex_t q_lock = PTHREAD_MUTEX_INITIALIZER;
700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint userial_clock_operation(int fd, int cmd);
720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint ath3k_init(int fd, int speed, int init_speed, char *bdaddr, struct termios *ti);
730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint userial_vendor_get_baud(void);
740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint readTrpState();
750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelvoid lpm_set_ar3k(uint8_t pio, uint8_t action, uint8_t polarity);
760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelbool is_download_progress();
770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic const tUSERIAL_CFG userial_init_cfg =
790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1),
810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    USERIAL_BAUD_115200
820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel};
830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#if (HW_NEED_END_WITH_HCI_RESET == TRUE)
8520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelvoid __hw_epilog_process(void);
860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <string.h>
900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <errno.h>
910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include <dlfcn.h>
920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#include "cutils/properties.h"
930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic const char WIFI_PROP_NAME[]    = "wlan.driver.status";
950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic const char SERVICE_PROP_NAME[]    = "bluetooth.hsic_ctrl";
960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic const char BT_STATUS_NAME[]    = "bluetooth.enabled";
970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic const char WIFI_SERVICE_PROP[] = "wlan.hsic_ctrl";
980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#define WIFI_BT_STATUS_LOCK    "/data/connectivity/wifi_bt_lock"
1000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint isInit=0;
1010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif /* WIFI_BT_STATUS_SYNC */
1020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelbool is_soc_initialized(void);
1030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/******************************************************************************
1050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**  Local type definitions
1060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel******************************************************************************/
1070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/******************************************************************************
1090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**  Functions
1100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel******************************************************************************/
1110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
1120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint bt_semaphore_create(void)
1130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int fd;
1150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    fd = open(WIFI_BT_STATUS_LOCK, O_RDONLY);
1170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (fd < 0)
1190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("can't create file\n");
1200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return fd;
1220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint bt_semaphore_get(int fd)
1250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int ret;
1270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (fd < 0)
1290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
1300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ret = flock(fd, LOCK_EX);
1320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (ret != 0) {
1330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("can't hold lock: %s\n", strerror(errno));
1340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
1350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
1360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return ret;
1380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint bt_semaphore_release(int fd)
1410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int ret;
1430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (fd < 0)
1450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
1460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ret = flock(fd, LOCK_UN);
1480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (ret != 0) {
1490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("can't release lock: %s\n", strerror(errno));
1500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
1510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
1520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return ret;
1540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint bt_semaphore_destroy(int fd)
1570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (fd < 0)
1590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
1600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return close (fd);
1620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint bt_wait_for_service_done(void)
1650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char service_status[PROPERTY_VALUE_MAX];
1670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int count = 30;
1680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGE("%s: check\n", __func__);
1700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    /* wait for service done */
1720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    while (count-- > 0) {
1730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        property_get(WIFI_SERVICE_PROP, service_status, NULL);
1740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if (strcmp(service_status, "") != 0) {
1760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            usleep(200000);
1770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        } else {
1780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
1790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
1800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
1810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return 0;
1830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
1840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif /* WIFI_BT_STATUS_SYNC */
1860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/** Get Bluetooth SoC type from system setting */
1880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic int get_bt_soc_type()
1890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
1900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int ret = 0;
1910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char bt_soc_type[PROPERTY_VALUE_MAX];
1920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGI("bt-vendor : get_bt_soc_type");
1940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
1950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ret = property_get("qcom.bluetooth.soc", bt_soc_type, NULL);
1960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (ret != 0) {
1970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGI("qcom.bluetooth.soc set to %s\n", bt_soc_type);
1980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if (!strncasecmp(bt_soc_type, "rome", sizeof("rome"))) {
1990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            return BT_SOC_ROME;
2000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
2010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        else if (!strncasecmp(bt_soc_type, "cherokee", sizeof("cherokee"))) {
2020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            return BT_SOC_CHEROKEE;
2030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
2040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        else if (!strncasecmp(bt_soc_type, "ath3k", sizeof("ath3k"))) {
2050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            return BT_SOC_AR3K;
2060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
2070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        else if (!strncasecmp(bt_soc_type, "cherokee", sizeof("cherokee"))) {
2080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            return BT_SOC_CHEROKEE;
2090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
2100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        else {
2110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ALOGI("qcom.bluetooth.soc not set, so using default.\n");
2120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            return BT_SOC_DEFAULT;
2130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
2140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
2150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    else {
2160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("%s: Failed to get soc type", __FUNCTION__);
2170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ret = BT_SOC_DEFAULT;
2180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
2190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return ret;
2210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
2220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelbool can_perform_action(char action) {
2240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bool can_perform = false;
2250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char ref_count[PROPERTY_VALUE_MAX];
2260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
2270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int value, ret;
2280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    property_get("wc_transport.ref_count", ref_count, "0");
2300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    value = atoi(ref_count);
2320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGV("%s: ref_count: %s\n",__func__,  ref_count);
2330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if(action == '1') {
2350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGV("%s: on : value is: %d", __func__, value);
2360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if(value == 1)
2370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        {
2380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            if ((is_soc_initialized() == true)
2390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel               || is_download_progress() || get_bt_soc_type() == BT_SOC_CHEROKEE)
2400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          {
2410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            value++;
2420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ALOGV("%s: on : value is incremented to : %d", __func__, value);
2430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          }
2440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
2450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        else
2460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        {
2470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel             value++;
2480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
2490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if (value == 1)
2510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            can_perform = true;
2520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        else if (value > 3)
2530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            return false;
2540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
2550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    else {
2560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGV("%s: off : value is: %d", __func__, value);
2570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if (--value <= 0) {
2580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ALOGE("%s: BT turn off twice before BT On(ref_count=%d)\n",
2590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    __func__, value);
2600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            value = 0;
2610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            can_perform = true;
2620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
2630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
2640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    snprintf(ref_count, 3, "%d", value);
2660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGV("%s: updated ref_count is: %s", __func__, ref_count);
2670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ret  = property_set("wc_transport.ref_count", ref_count);
2690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (ret < 0) {
2700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("%s: Error while updating property: %d\n", __func__, ret);
2710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return false;
2720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
2730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGV("%s returning %d", __func__, can_perform);
2740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return can_perform;
2750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
2760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelvoid stop_hci_filter() {
2780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       char value[PROPERTY_VALUE_MAX] = {'\0'};
2790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       int retval, filter_ctrl, i;
2800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       char stop_val = STOP_WCNSS_FILTER;
2810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       int soc_type = BT_SOC_DEFAULT;
2820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       ALOGV("%s: Entry ", __func__);
2840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
2850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       if ((soc_type = get_bt_soc_type()) == BT_SOC_CHEROKEE) {
28641464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel           property_get("wc_transport.hci_filter_status", value, "0");
28741464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel           if (strcmp(value, "0") == 0) {
28841464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel               ALOGI("%s: hci_filter has been stopped already", __func__);
28941464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel           }
29041464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel           else {
29141464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel               filter_ctrl = connect_to_local_socket("wcnssfilter_ctrl");
29241464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel               if (filter_ctrl < 0) {
29341464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                   ALOGI("%s: Error while connecting to CTRL_SOCK, filter should stopped: %d",
29441464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                          __func__, filter_ctrl);
29541464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel               }
29641464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel               else {
29741464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                   retval = write(filter_ctrl, &stop_val, 1);
29841464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                   if (retval != 1) {
29941464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                       ALOGI("%s: problem writing to CTRL_SOCK, ignore: %d", __func__, retval);
30041464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                       //Ignore and fallback
30141464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                   }
30241464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel
30341464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                   close(filter_ctrl);
3040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel               }
3050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           }
3060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           /* Ensure Filter is closed by checking the status before
3080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              RFKILL 0 operation. this should ideally comeout very
3090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              quick */
31041464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel           for(i=0; i<500; i++) {
31141464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel               property_get(BT_VND_FILTER_START, value, "false");
31241464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel               if (strcmp(value, "false") == 0) {
3130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                   ALOGI("%s: WCNSS_FILTER stopped", __func__);
31441464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                   usleep(STOP_WAIT_TIMEOUT * 10);
3150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                   break;
3160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel               } else {
31741464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                   /*sleep of 1ms, This should give enough time for FILTER to
3180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                   exit with all necessary cleanup*/
3190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                   usleep(STOP_WAIT_TIMEOUT);
3200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel               }
3210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           }
3220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           /*Never use SIGKILL to stop the filter*/
3240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           /* Filter will be stopped by below two conditions
3250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            - by Itself, When it realizes there are no CONNECTED clients
3260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            - Or through STOP_WCNSS_FILTER byte on Control socket
3270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            both of these ensure clean shutdown of chip
3280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           */
3290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           //property_set(BT_VND_FILTER_START, "false");
3300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       } else if (soc_type == BT_SOC_ROME) {
3310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           property_set(BT_VND_FILTER_START, "false");
3320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       } else {
3330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           ALOGI("%s: Unknown soc type %d, Unexpected!", __func__, soc_type);
3340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       }
3350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       ALOGV("%s: Exit ", __func__);
3370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
3380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint start_hci_filter() {
3400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       ALOGV("%s: Entry ", __func__);
3410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       int i, init_success = -1;
3420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       char value[PROPERTY_VALUE_MAX] = {'\0'};
3430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       property_get(BT_VND_FILTER_START, value, false);
3450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       if (strcmp(value, "true") == 0) {
3470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           ALOGI("%s: hci_filter has been started already", __func__);
3480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           //Filter should have been started OR in the process of initializing
3490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           //Make sure of hci_filter_status and return the state based on it
3500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       } else {
35169ba81cb05c2c2cdb68de73653458367bb342de0Thierry Strudel           property_set("wc_transport.clean_up","0");
3520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           property_set("wc_transport.hci_filter_status", "0");
3530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           property_set(BT_VND_FILTER_START, "true");
3540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           ALOGV("%s: %s set to true ", __func__, BT_VND_FILTER_START );
3550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       }
3560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       /*If there are back to back ON requests from different clients,
3580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel         All client should come and stuck in this while loop till FILTER
3590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel         comesup and ready to accept the connections */
3600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       //sched_yield();
3610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       for(i=0; i<45; i++) {
3620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          property_get("wc_transport.hci_filter_status", value, "0");
3630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          if (strcmp(value, "1") == 0) {
3640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel               init_success = 1;
3650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel               break;
3660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           } else {
3670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel               usleep(WAIT_TIMEOUT);
3680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           }
3690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
3700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGV("start_hcifilter status:%d after %f seconds \n", init_success, 0.2*i);
3710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGV("%s: Exit ", __func__);
3730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return init_success;
3740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
3750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
37620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel/*
37720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel * Bluetooth Controller power up or shutdown, this function is called with
37820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel * q_lock held and q is non-NULL
37920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel */
3800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic int bt_powerup(int en )
3810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
3820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char rfkill_type[64], *enable_ldo_path = NULL;
3830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char type[16], enable_ldo[6];
384bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel    int fd = 0, size, i, ret, fd_ldo, fd_btpower;
3850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char disable[PROPERTY_VALUE_MAX];
3870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char state;
3880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char on = (en)?'1':'0';
3890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
3910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char wifi_status[PROPERTY_VALUE_MAX];
3920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int lock_fd;
3930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif /*WIFI_BT_STATUS_SYNC*/
3940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGI("bt_powerup: %c", on);
3960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
3970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    /* Check if rfkill has been disabled */
3980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ret = property_get("ro.rfkilldisabled", disable, "0");
3990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (!ret ){
4000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("Couldn't get ro.rfkilldisabled (%d)", ret);
4010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
4020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    /* In case rfkill disabled, then no control power*/
4040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (strcmp(disable, "1") == 0) {
4050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGI("ro.rfkilldisabled : %s", disable);
4060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
4070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
4090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
4100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    lock_fd = bt_semaphore_create();
4110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bt_semaphore_get(lock_fd);
4120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bt_wait_for_service_done();
4130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
4140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
4150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    /* Assign rfkill_id and find bluetooth rfkill state path*/
4165752ddcecf884adefc166873565da60e70f59400Thierry Strudel    for(i = 0; (q->rfkill_id == -1) && (q->rfkill_state == NULL); i++)
4170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    {
4180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        snprintf(rfkill_type, sizeof(rfkill_type), "/sys/class/rfkill/rfkill%d/type", i);
4190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if ((fd = open(rfkill_type, O_RDONLY)) < 0)
4200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        {
4210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ALOGE("open(%s) failed: %s (%d)\n", rfkill_type, strerror(errno), errno);
4220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
4230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
4240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            bt_semaphore_release(lock_fd);
4250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            bt_semaphore_destroy(lock_fd);
4260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
4270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            return -1;
4280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
4290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
4300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        size = read(fd, &type, sizeof(type));
4310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        close(fd);
4320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
4330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if ((size >= 9) && !memcmp(type, "bluetooth", 9))
4340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        {
4355752ddcecf884adefc166873565da60e70f59400Thierry Strudel            asprintf(&q->rfkill_state, "/sys/class/rfkill/rfkill%d/state", q->rfkill_id = i);
4360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
4370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
4380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
4400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    /* Get rfkill State to control */
4415752ddcecf884adefc166873565da60e70f59400Thierry Strudel    if (q->rfkill_state != NULL)
4420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    {
4435752ddcecf884adefc166873565da60e70f59400Thierry Strudel        if ((fd = open(q->rfkill_state, O_RDWR)) < 0)
4440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        {
4455752ddcecf884adefc166873565da60e70f59400Thierry Strudel            ALOGE("open(%s) for write failed: %s (%d)", q->rfkill_state, strerror(errno), errno);
4460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
4470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            bt_semaphore_release(lock_fd);
4480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            bt_semaphore_destroy(lock_fd);
4490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
4500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
4510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            return -1;
4520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
4530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if(can_perform_action(on) == false) {
4550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("%s:can't perform action as it is being used by other clients", __func__);
4560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
4570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            bt_semaphore_release(lock_fd);
4580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            bt_semaphore_destroy(lock_fd);
4590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
4600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            goto done;
4610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4625752ddcecf884adefc166873565da60e70f59400Thierry Strudel    ret = asprintf(&enable_ldo_path, "/sys/class/rfkill/rfkill%d/device/extldo", q->rfkill_id);
4630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if( (ret < 0 ) || (enable_ldo_path == NULL) )
4640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    {
4650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("Memory Allocation failure");
4660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
4670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if ((fd_ldo = open(enable_ldo_path, O_RDWR)) < 0) {
4690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("open(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
4700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
4710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    size = read(fd_ldo, &enable_ldo, sizeof(enable_ldo));
4730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    close(fd_ldo);
4740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (size <= 0) {
4750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("read(%s) failed: %s (%d)", enable_ldo_path, strerror(errno), errno);
4760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
4770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (!memcmp(enable_ldo, "true", 4)) {
4790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGI("External LDO has been configured");
4800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ret = property_set("wc_transport.extldo", "enabled");
4810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if (ret < 0) {
4820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ALOGI("%s: Not able to set property wc_transport.extldo\n", __func__);
4830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
4845752ddcecf884adefc166873565da60e70f59400Thierry Strudel        q->enable_extldo = TRUE;
4850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
4870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if(on == '0'){
4880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("Stopping HCI filter as part of CTRL:OFF");
4890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        stop_hci_filter();
4900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        property_set("wc_transport.soc_initialized", "0");
4910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
4920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
4935752ddcecf884adefc166873565da60e70f59400Thierry Strudel    if (q->soc_type >= BT_SOC_CHEROKEE && q->soc_type < BT_SOC_RESERVED) {
494bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel       ALOGI("open bt power devnode,send ioctl power op  :%d ",en);
495bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel       fd_btpower = open(BT_PWR_CNTRL_DEVICE, O_RDWR, O_NONBLOCK);
496bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel       if (fd_btpower < 0) {
497bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel           ALOGE("\nfailed to open bt device error = (%s)\n",strerror(errno));
4980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
499bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel           bt_semaphore_release(lock_fd);
500bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel           bt_semaphore_destroy(lock_fd);
5010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
502bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel           return -1;
503bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel       }
504bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel       ret = ioctl(fd_btpower, BT_CMD_PWR_CTRL, (unsigned long)en);
505bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel        if (ret < 0) {
506bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel            ALOGE(" ioctl failed to power control:%d error =(%s)",ret,strerror(errno));
5070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
508bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel        close(fd_btpower);
509bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel    } else {
510bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel       ALOGI("Write %c to rfkill\n", on);
511bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel       /* Write value to control rfkill */
512bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel       if(fd >= 0) {
513bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel           if ((size = write(fd, &on, 1)) < 0) {
5145752ddcecf884adefc166873565da60e70f59400Thierry Strudel               ALOGE("write(%s) failed: %s (%d)", q->rfkill_state, strerror(errno), errno);
515bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
516bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel               bt_semaphore_release(lock_fd);
517bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel               bt_semaphore_destroy(lock_fd);
518bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel#endif
519bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel               return -1;
520bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel           }
521bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel       }
522bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel   }
5230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
5240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    /* query wifi status */
5250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    property_get(WIFI_PROP_NAME, wifi_status, "");
5260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
5270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGE("bt get wifi status: %s, isInit: %d\n",  wifi_status, isInit);
5280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
5290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    /* If wlan driver is not loaded, and bt is changed from off => on */
5300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (strncmp(wifi_status, "unloaded", strlen("unloaded")) == 0 || strlen(wifi_status) == 0) {
5310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if (on == '1') {
5320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ALOGI("%s: BT_VND_PWR_ON\n", __func__);
5330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            if(property_set(SERVICE_PROP_NAME, "load_wlan") < 0) {
5340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
5350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                close(fd);
5360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                bt_semaphore_release(lock_fd);
5370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                bt_semaphore_destroy(lock_fd);
5380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                return -1;
5390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
5400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
5410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        else if (isInit == 0 && on == '0') {
5420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ALOGI("%s: BT_VND_PWR_OFF\n", __func__);
5430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            if(property_set(SERVICE_PROP_NAME, "unbind_hsic") < 0) {
5440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGE("%s Property setting failed", SERVICE_PROP_NAME);
5450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                close(fd);
5460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                bt_semaphore_release(lock_fd);
5470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                bt_semaphore_destroy(lock_fd);
5480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                return -1;
5490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
5500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       }
5510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
5520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
5530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (isInit == 0 && on == '0')
5540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        property_set(BT_STATUS_NAME, "false");
5550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    else if (on == '1')
5560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        property_set(BT_STATUS_NAME, "true");
5570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
5580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bt_semaphore_release(lock_fd);
5590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bt_semaphore_destroy(lock_fd);
5600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif /* WIFI_BT_STATUS_SYNC */
5610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
5620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudeldone:
5630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (fd >= 0)
5640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        close(fd);
5650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return 0;
5660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
5670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
56820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelstatic inline void soc_init(int soc_type)
56920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel{
57020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    switch (soc_type)
57120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    {
57220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    case BT_SOC_CHEROKEE:
57320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    case BT_SOC_ROME:
57420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    case BT_SOC_AR3K:
57520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        ALOGI("bt-vendor : Initializing UART transport layer");
57620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        userial_vendor_init();
57720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        break;
57820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    case BT_SOC_DEFAULT:
57920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        break;
58020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    default:
58120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        ALOGE("Unknown soc yype: %d", soc_type);
58220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        break;
58320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    }
58420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel}
58520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
58620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel/* Copy BD Address as little-endian byte order */
58720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelstatic inline void le2bd(unsigned char *src, unsigned char *dst)
58820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel{
58920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    int i;
59020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    for (i = 0; i < 6; i++)
59120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        dst[i] = src[5-i];
59220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel}
59320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
59420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelstatic inline void print_bdaddr(unsigned char *addr)
59520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel{
59620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    ALOGI("BD Address: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", addr[0], addr[1],
59720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            addr[2], addr[3], addr[4], addr[5]);
59820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel}
59920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
6000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/*****************************************************************************
6010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
6020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**   BLUETOOTH VENDOR INTERFACE LIBRARY FUNCTIONS
6030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel**
6040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel*****************************************************************************/
6050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
60620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelstatic int init(const bt_vendor_callbacks_t *cb, unsigned char *bdaddr)
6070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
608c326d170da6532d78df3fa18ffacfd9574841a90Thierry Strudel    char prop[PROPERTY_VALUE_MAX] = {0};
6095752ddcecf884adefc166873565da60e70f59400Thierry Strudel    struct bt_qcom_struct *temp = NULL;
61020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    int ret = BT_STATUS_SUCCESS, i;
6110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
61220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    ALOGI("++%s", __FUNCTION__);
6130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
61420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    if (!cb || !bdaddr) {
61520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        ALOGE("Invalid input args cb %p bdaddr %p", cb, bdaddr);
61620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        ret = -BT_STATUS_INVAL;
61720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        goto out;
6180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
6190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
6205752ddcecf884adefc166873565da60e70f59400Thierry Strudel    temp = (struct bt_qcom_struct *) malloc(sizeof(*q));
6215752ddcecf884adefc166873565da60e70f59400Thierry Strudel    if (!temp) {
6225752ddcecf884adefc166873565da60e70f59400Thierry Strudel        ALOGE("Failed to allocate memory. err %s(%d)", strerror(errno), errno);
6235752ddcecf884adefc166873565da60e70f59400Thierry Strudel        ret = -BT_STATUS_NOMEM;
6245752ddcecf884adefc166873565da60e70f59400Thierry Strudel        goto out;
6255752ddcecf884adefc166873565da60e70f59400Thierry Strudel    }
6265752ddcecf884adefc166873565da60e70f59400Thierry Strudel    memset(temp, 0, sizeof(*temp));
62720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
6285752ddcecf884adefc166873565da60e70f59400Thierry Strudel    temp->rfkill_id = -1;
6295752ddcecf884adefc166873565da60e70f59400Thierry Strudel    temp->enable_extldo = FALSE;
6301414527307ab6aae2c497b3d2122278cb9ca1aa1Frank Barchard    temp->cb = (bt_vendor_callbacks_t*)cb;
6315752ddcecf884adefc166873565da60e70f59400Thierry Strudel    temp->ant_fd = -1;
6325752ddcecf884adefc166873565da60e70f59400Thierry Strudel    temp->soc_type = get_bt_soc_type();
6335752ddcecf884adefc166873565da60e70f59400Thierry Strudel    soc_init(temp->soc_type);
6345752ddcecf884adefc166873565da60e70f59400Thierry Strudel
6355752ddcecf884adefc166873565da60e70f59400Thierry Strudel    le2bd(bdaddr, temp->bdaddr);
6365752ddcecf884adefc166873565da60e70f59400Thierry Strudel    print_bdaddr(temp->bdaddr);
637c326d170da6532d78df3fa18ffacfd9574841a90Thierry Strudel    snprintf(prop, sizeof(prop), "%02x:%02x:%02x:%02x:%02x:%02x",
6385752ddcecf884adefc166873565da60e70f59400Thierry Strudel             temp->bdaddr[0], temp->bdaddr[1], temp->bdaddr[2],
6395752ddcecf884adefc166873565da60e70f59400Thierry Strudel             temp->bdaddr[3], temp->bdaddr[4], temp->bdaddr[5]);
640c326d170da6532d78df3fa18ffacfd9574841a90Thierry Strudel    ret = property_set("wc_transport.stack_bdaddr", prop);
641c326d170da6532d78df3fa18ffacfd9574841a90Thierry Strudel    if (ret < 0) {
642c326d170da6532d78df3fa18ffacfd9574841a90Thierry Strudel        ALOGE("Failed to set wc_transport.stack_bdaddr prop, ret = %d", ret);
643c326d170da6532d78df3fa18ffacfd9574841a90Thierry Strudel        ret = -BT_STATUS_PROP_FAILURE;
644c326d170da6532d78df3fa18ffacfd9574841a90Thierry Strudel        goto out;
645c326d170da6532d78df3fa18ffacfd9574841a90Thierry Strudel    }
64620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
64720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel/* TODO: Move these fields inside bt_qcom context */
6480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
6490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    isInit = 1;
6500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif /* WIFI_BT_STATUS_SYNC */
6510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
65220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    /* Everything successful */
6535752ddcecf884adefc166873565da60e70f59400Thierry Strudel    q = temp;
65420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    return ret;
65520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
65620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelout:
6575752ddcecf884adefc166873565da60e70f59400Thierry Strudel    if (temp)
6585752ddcecf884adefc166873565da60e70f59400Thierry Strudel        free(temp);
65920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    ALOGI("--%s ret %d", __FUNCTION__, ret);
66020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    return ret;
6610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
6620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
6630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef READ_BT_ADDR_FROM_PROP
6640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic bool validate_tok(char* bdaddr_tok) {
6650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int i = 0;
6660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bool ret;
6670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
6680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (strlen(bdaddr_tok) != 2) {
6690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ret = FALSE;
6700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("Invalid token length");
6710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    } else {
6720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ret = TRUE;
6730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        for (i=0; i<2; i++) {
6740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            if ((bdaddr_tok[i] >= '0' && bdaddr_tok[i] <= '9') ||
6750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                (bdaddr_tok[i] >= 'A' && bdaddr_tok[i] <= 'F') ||
6760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                (bdaddr_tok[i] >= 'a' && bdaddr_tok[i] <= 'f')) {
6770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ret = TRUE;
6780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGV("%s: tok %s @ %d is good", __func__, bdaddr_tok, i);
6790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel             } else {
6800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ret = FALSE;
6810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGE("invalid character in tok: %s at ind: %d", bdaddr_tok, i);
6820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                break;
6830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel             }
6840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
6850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
6860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return ret;
6870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
6880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif /*READ_BT_ADDR_FROM_PROP*/
6890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
6900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelint connect_to_local_socket(char* name) {
6910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       socklen_t len; int sk = -1;
6920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
6930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       ALOGE("%s: ACCEPT ", __func__);
6940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       sk  = socket(AF_LOCAL, SOCK_STREAM, 0);
6950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       if (sk < 0) {
6960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           ALOGE("Socket creation failure");
6970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           return -1;
6980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel       }
6990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
7000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if(socket_local_client_connect(sk, name,
7010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
7020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        {
7030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel             ALOGE("failed to connect (%s)", strerror(errno));
7040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel             close(sk);
7050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel             sk = -1;
7060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        } else {
7070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGE("%s: Connection succeeded\n", __func__);
7080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
7090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return sk;
7100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
7110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
7120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelbool is_soc_initialized() {
7130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bool init = false;
7140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char init_value[PROPERTY_VALUE_MAX];
7150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int ret;
7160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
7170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGI("bt-vendor : is_soc_initialized");
7180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
7190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ret = property_get(SOC_INIT_PROPERTY, init_value, NULL);
7200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (ret != 0) {
7210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGI("%s set to %s\n", SOC_INIT_PROPERTY, init_value);
7220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if (!strncasecmp(init_value, "1", sizeof("1"))) {
7230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            init = true;
7240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
7250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
7260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    else {
7270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("%s: Failed to get %s", __FUNCTION__, SOC_INIT_PROPERTY);
7280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
7290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
7300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return init;
7310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
7320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
73341464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel/* flavor of op without locks */
734d659daacec1c7697ad086dee638759c8991ebe45Mark Urbanusstatic int op(bt_vendor_opcode_t opcode, void *param)
7350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
73620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    int retval = BT_STATUS_SUCCESS;
7370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int nCnt = 0;
7380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int nState = -1;
7390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bool is_ant_req = false;
7400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bool is_fm_req = false;
7410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char wipower_status[PROPERTY_VALUE_MAX];
7420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char emb_wp_mode[PROPERTY_VALUE_MAX];
7430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char bt_version[PROPERTY_VALUE_MAX];
744190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel    char lpm_config[PROPERTY_VALUE_MAX];
7450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bool ignore_boot_prop = TRUE;
7460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef READ_BT_ADDR_FROM_PROP
7470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int i = 0;
7480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    static char bd_addr[PROPERTY_VALUE_MAX];
7490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    uint8_t local_bd_addr_from_prop[6];
7500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char* tok;
7510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
7520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bool skip_init = true;
7530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int  opcode_init = opcode;
75420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    ALOGV("++%s opcode %d", __FUNCTION__, opcode);
7550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
7560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    switch(opcode_init)
7570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    {
7580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef FM_OVER_UART
7590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case FM_VND_OP_POWER_CTRL:
7600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            {
7610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              is_fm_req = true;
7620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              if (is_soc_initialized()) {
7630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                  // add any FM specific actions  if needed in future
7640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                  break;
7650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel              }
7660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
7670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
7680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_POWER_CTRL:
7690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            {
77020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                if (!param) {
77120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGE("opcode = %d: param is null", opcode_init);
77220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    break;
77320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                }
7740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                nState = *(int *) param;
7750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGI("bt-vendor : BT_VND_OP_POWER_CTRL: %s",
7760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        (nState == BT_VND_PWR_ON)? "On" : "Off" );
7770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
7785752ddcecf884adefc166873565da60e70f59400Thierry Strudel                switch(q->soc_type)
7790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                {
7800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_DEFAULT:
7810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        if (readTrpState())
7820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        {
7830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           ALOGI("bt-vendor : resetting BT status");
7840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           hw_config(BT_VND_PWR_OFF);
7850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        }
7860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        retval = hw_config(nState);
7870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        if(nState == BT_VND_PWR_ON
7880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           && retval == 0
7890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           && is_hw_ready() == TRUE){
7900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            retval = 0;
7910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        }
7920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        else {
7930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            retval = -1;
7940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        }
7950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
7960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_ROME:
7970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_AR3K:
7980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_CHEROKEE:
7990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        /* BT Chipset Power Control through Device Tree Node */
80020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                        retval = bt_powerup(nState);
8010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    default:
8020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
8030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
8040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
8050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
8060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
80720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        case BT_VND_OP_FW_CFG: {
80820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                /* call hciattach to initalize the stack */
8095752ddcecf884adefc166873565da60e70f59400Thierry Strudel                if (q->soc_type == BT_SOC_ROME) {
81020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    if (is_soc_initialized()) {
81120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                        ALOGI("Bluetooth FW and transport layer are initialized");
8125752ddcecf884adefc166873565da60e70f59400Thierry Strudel                        q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
81320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    } else {
81420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                        ALOGE("bt_vendor_cbacks is null or SoC not initialized");
81520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                        ALOGE("Error : hci, smd initialization Error");
81620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                        retval = -1;
81720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    }
81820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                } else {
81920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGI("Bluetooth FW and transport layer are initialized");
8205752ddcecf884adefc166873565da60e70f59400Thierry Strudel                    q->cb->fwcfg_cb(BT_VND_OP_RESULT_SUCCESS);
8210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
82220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        }
8230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
8240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
8250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_SCO_CFG:
8265752ddcecf884adefc166873565da60e70f59400Thierry Strudel            q->cb->scocfg_cb(BT_VND_OP_RESULT_SUCCESS); //dummy
8270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
8280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef ENABLE_ANT
8290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_ANT_USERIAL_OPEN:
8300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_OPEN");
8310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                is_ant_req = true;
8320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                goto userial_open;
8330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
8340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef FM_OVER_UART
8350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_FM_USERIAL_OPEN:
8360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_OPEN");
8370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                is_fm_req = true;
8380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                goto userial_open;
8390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
8400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudeluserial_open:
8410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_USERIAL_OPEN:
8420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            {
84320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                if (!param) {
84420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGE("opcode = %d: param is null", opcode_init);
84520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    break;
84620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                }
8470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                int (*fd_array)[] = (int (*)[]) param;
8480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                int idx, fd = -1, fd_filter = -1;
8490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGI("bt-vendor : BT_VND_OP_USERIAL_OPEN");
8505752ddcecf884adefc166873565da60e70f59400Thierry Strudel                switch(q->soc_type)
8510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                {
8520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_DEFAULT:
8530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        {
8545752ddcecf884adefc166873565da60e70f59400Thierry Strudel                            if(bt_hci_init_transport(q->fd) != -1){
8550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                int (*fd_array)[] = (int (*) []) param;
8560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
8575752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                    (*fd_array)[CH_CMD] = q->fd[0];
8585752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                    (*fd_array)[CH_EVT] = q->fd[0];
8595752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                    (*fd_array)[CH_ACL_OUT] = q->fd[1];
8605752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                    (*fd_array)[CH_ACL_IN] = q->fd[1];
8610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            }
8620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            else {
8630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                retval = -1;
8640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                break;
8650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            }
8660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            retval = 2;
8670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        }
8680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
8690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_AR3K:
8700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        {
8710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
8720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            if (fd != -1) {
8730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                for (idx=0; idx < CH_MAX; idx++)
8740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    (*fd_array)[idx] = fd;
8750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                     retval = 1;
8760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            }
8770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            else {
8780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                retval = -1;
8790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                break;
8800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            }
8810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
8820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            /* Vendor Specific Process should happened during userial_open process
8830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                After userial_open, rx read thread is running immediately,
8840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                so it will affect VS event read process.
8850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            */
8860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            if(ath3k_init(fd,3000000,115200,NULL,&vnd_userial.termios)<0)
8870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                retval = -1;
8880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        }
8890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
8900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_ROME:
8910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        {
8920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            wait_for_patch_download(is_ant_req);
8930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
8940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            if (!is_soc_initialized()) {
8950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                char* dlnd_inprog = is_ant_req ? "ant" : "bt";
8960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                if (property_set("wc_transport.patch_dnld_inprog", dlnd_inprog) < 0) {
8970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGE("%s: Failed to set dnld_inprog %s", __FUNCTION__, dlnd_inprog);
8980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
8990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
9000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
9010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                if (fd < 0) {
9020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGE("userial_vendor_open returns err");
9030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    retval = -1;
9040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    break;
9050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
9060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
9070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                /* Clock on */
9080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                userial_clock_operation(fd, USERIAL_OP_CLK_ON);
9090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
9100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                if(strcmp(emb_wp_mode, "true") == 0) {
9110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    property_get("ro.bluetooth.wipower", wipower_status, false);
9120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    if(strcmp(wipower_status, "true") == 0) {
9130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        check_embedded_mode(fd);
9140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    } else {
9150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGI("Wipower not enabled");
9160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    }
9170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
9180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                ALOGV("rome_soc_init is started");
9190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                property_set("wc_transport.soc_initialized", "0");
9200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef READ_BT_ADDR_FROM_PROP
9210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                /*Give priority to read BD address from boot property*/
9220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                ignore_boot_prop = FALSE;
9230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                if (property_get(BLUETOOTH_MAC_ADDR_BOOT_PROPERTY, bd_addr, NULL)) {
9240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGV("BD address read from Boot property: %s\n", bd_addr);
9250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    tok =  strtok(bd_addr, ":");
9260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    while (tok != NULL) {
9270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGV("bd add [%d]: %d ", i, strtol(tok, NULL, 16));
9280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        if (i>=6) {
9290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            ALOGE("bd property of invalid length");
9300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            ignore_boot_prop = TRUE;
9310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            break;
9320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        }
93320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                                        if (i == 6 && !ignore_boot_prop) {
93420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                                            ALOGV("Valid BD address read from prop");
9355752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                            memcpy(q->bdaddr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
93620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                                            ignore_boot_prop = FALSE;
93720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                                        } else {
93820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                                            ALOGE("There are not enough tokens in BD addr");
9390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            ignore_boot_prop = TRUE;
9400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            break;
9410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        }
9420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        local_bd_addr_from_prop[5-i] = strtol(tok, NULL, 16);
9430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        tok = strtok(NULL, ":");
9440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        i++;
9450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    }
9460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    if (i == 6 && !ignore_boot_prop) {
9470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGV("Valid BD address read from prop");
9480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        memcpy(vnd_local_bd_addr, local_bd_addr_from_prop, sizeof(vnd_local_bd_addr));
9490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ignore_boot_prop = FALSE;
9500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    } else {
9510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGE("There are not enough tokens in BD addr");
9520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ignore_boot_prop = TRUE;
9530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    }
9540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
9550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                else {
9560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                     ALOGE("BD address boot property not set");
9570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                     ignore_boot_prop = TRUE;
9580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
9590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif //READ_BT_ADDR_FROM_PROP
96048e31bec582e3854b3aaad0ebaaf4ac2ad6a33dbThierry Strudel#ifdef BT_NV_SUPPORT
9610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    /* Always read BD address from NV file */
9625752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                if(ignore_boot_prop && !bt_vendor_nv_read(1, q->bdaddr))
9630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                {
9640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                   /* Since the BD address is configured in boot time We should not be here */
9650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                   ALOGI("Failed to read BD address. Use the one from bluedroid stack/ftm");
9660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
96748e31bec582e3854b3aaad0ebaaf4ac2ad6a33dbThierry Strudel#endif //BT_NV_SUPPORT
9685752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                if(rome_soc_init(fd, (char*)q->bdaddr)<0) {
9690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    retval = -1;
9700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                } else {
9710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGV("rome_soc_init is completed");
9720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    property_set("wc_transport.soc_initialized", "1");
9730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    skip_init = false;
9740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
9750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            }
9760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
9770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                ALOGE("%s: Failed to set property", __FUNCTION__);
9780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            }
9790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
9800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            property_set("wc_transport.clean_up","0");
9810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            if (retval != -1) {
9820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
9830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                retval = start_hci_filter();
9840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                if (retval < 0) {
9850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGE("%s: WCNSS_FILTER wouldn't have started in time\n", __func__);
9860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                } else {
9870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef ENABLE_ANT
9880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    if (is_ant_req) {
9890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGI("%s: connect to ant channel", __func__);
9905752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                        q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
9910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    }
9920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    else
9930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
9940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    {
9950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGI("%s: connect to bt channel", __func__);
9960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
9970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    }
9980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
9990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    if (fd_filter != -1) {
10000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGI("%s: received the socket fd: %d is_ant_req: %d is_fm_req: %d\n",
10010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                                             __func__, fd_filter, is_ant_req,is_fm_req);
10020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        if((strcmp(emb_wp_mode, "true") == 0) && !is_ant_req && !is_fm_req) {
10030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                             if (chipset_ver >= ROME_VER_3_0) {
10040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                                /* get rome supported feature request */
10050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                                ALOGE("%s: %x08 %0x", __FUNCTION__,chipset_ver, ROME_VER_3_0);
10060ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                                rome_get_addon_feature_list(fd_filter);
10070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            }
10080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        }
10090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        if (!skip_init) {
10100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            /*Skip if already sent*/
10110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            enable_controller_log(fd_filter, (is_ant_req || is_fm_req) );
10120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            skip_init = true;
10130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        }
10140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        for (idx=0; idx < CH_MAX; idx++)
10150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            (*fd_array)[idx] = fd_filter;
10160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            retval = 1;
10170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    }
10180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    else {
10190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        if (is_ant_req)
10200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            ALOGE("Unable to connect to ANT Server Socket!!!");
10210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        else
10220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                            ALOGE("Unable to connect to BT Server Socket!!!");
10230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        retval = -1;
10240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    }
10250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
10260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            } else {
10275752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                if (q->soc_type == BT_SOC_ROME)
10280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGE("Failed to initialize ROME Controller!!!");
10290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            }
10300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
10310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            if (fd >= 0) {
10320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                userial_clock_operation(fd, USERIAL_OP_CLK_OFF);
10330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                 /*Close the UART port*/
10340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                 close(fd);
10350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            }
10360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        }
10370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
10380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_CHEROKEE:
10390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        {
10400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            property_get("ro.bluetooth.emb_wp_mode", emb_wp_mode, false);
10410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            retval = start_hci_filter();
10420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            if (retval < 0) {
10430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                ALOGE("WCNSS_FILTER wouldn't have started in time\n");
104469ba81cb05c2c2cdb68de73653458367bb342de0Thierry Strudel                                /*
104569ba81cb05c2c2cdb68de73653458367bb342de0Thierry Strudel                                 Set the following property to -1 so that the SSR cleanup routine
104669ba81cb05c2c2cdb68de73653458367bb342de0Thierry Strudel                                 can reset SOC.
104769ba81cb05c2c2cdb68de73653458367bb342de0Thierry Strudel                                 */
104869ba81cb05c2c2cdb68de73653458367bb342de0Thierry Strudel                                property_set("wc_transport.hci_filter_status", "-1");
10490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            } else {
10500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef ENABLE_ANT
10510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                if (is_ant_req) {
10520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGI("%s: connect to ant channel", __func__);
10535752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                    q->ant_fd = fd_filter = connect_to_local_socket("ant_sock");
10540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
10550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                else
10560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
10570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef FM_OVER_UART
10585752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                if (is_fm_req && (q->soc_type >=BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED)) {
10590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGI("%s: connect to fm channel", __func__);
10605752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                    q->fm_fd = fd_filter = connect_to_local_socket("fm_sock");
10610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
10620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                else
10630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
10640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                {
10650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGI("%s: connect to bt channel", __func__);
10660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    vnd_userial.fd = fd_filter = connect_to_local_socket("bt_sock");
10670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
10680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
10690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                if (fd_filter != -1) {
10700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    ALOGV("%s: received the socket fd: %d \n",
10710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                                             __func__, fd_filter);
10720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
10730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    for (idx=0; idx < CH_MAX; idx++) {
10740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        (*fd_array)[idx] = fd_filter;
10750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    }
10760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    retval = 1;
10770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
10780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                else {
10790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef ENABLE_ANT
10800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    if (is_ant_req)
10810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGE("Unable to connect to ANT Server Socket!!!");
10820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    else
10830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
10840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef FM_OVER_UART
10850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    if (is_fm_req)
10860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGE("Unable to connect to FM Server Socket!!!");
10870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    else
10880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
10890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                        ALOGE("Unable to connect to BT Server Socket!!!");
10900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                    retval = -1;
10910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                                }
10920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            }
10930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        }
10940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
10950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    default:
10965752ddcecf884adefc166873565da60e70f59400Thierry Strudel                        ALOGE("Unknown soc_type: 0x%x", q->soc_type);
10970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
10980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                  }
10990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            } break;
11000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef ENABLE_ANT
11010ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_ANT_USERIAL_CLOSE:
11020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            {
11030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGI("bt-vendor : BT_VND_OP_ANT_USERIAL_CLOSE");
110420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                property_set("wc_transport.clean_up","1");
11055752ddcecf884adefc166873565da60e70f59400Thierry Strudel                if (q->ant_fd != -1) {
110620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGE("closing ant_fd");
11075752ddcecf884adefc166873565da60e70f59400Thierry Strudel                    close(q->ant_fd);
11085752ddcecf884adefc166873565da60e70f59400Thierry Strudel                    q->ant_fd = -1;
11090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
11100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
111120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            break;
11120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
11130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef FM_OVER_UART
11140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_FM_USERIAL_CLOSE:
11150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            {
11160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                ALOGI("bt-vendor : BT_VND_OP_FM_USERIAL_CLOSE");
11170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                property_set("wc_transport.clean_up","1");
11185752ddcecf884adefc166873565da60e70f59400Thierry Strudel                if (q->fm_fd != -1) {
11190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    ALOGE("closing fm_fd");
11205752ddcecf884adefc166873565da60e70f59400Thierry Strudel                    close(q->fm_fd);
11215752ddcecf884adefc166873565da60e70f59400Thierry Strudel                    q->fm_fd = -1;
11220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
11230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                break;
112420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            }
11250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
11260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_USERIAL_CLOSE:
11270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            {
11285752ddcecf884adefc166873565da60e70f59400Thierry Strudel                ALOGI("bt-vendor : BT_VND_OP_USERIAL_CLOSE soc_type: %d", q->soc_type);
11295752ddcecf884adefc166873565da60e70f59400Thierry Strudel                switch(q->soc_type)
11300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                {
11310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_DEFAULT:
11325752ddcecf884adefc166873565da60e70f59400Thierry Strudel                        bt_hci_deinit_transport(q->fd);
11330ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
11340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_ROME:
11350ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_AR3K:
11360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_CHEROKEE:
11370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    {
113820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                        property_set("wc_transport.clean_up","1");
113920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                        userial_vendor_close();
11400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
11410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    }
11420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    default:
11435752ddcecf884adefc166873565da60e70f59400Thierry Strudel                        ALOGE("Unknown soc_type: 0x%x", q->soc_type);
11440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
11450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
11460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
11470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
11480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
11490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_GET_LPM_IDLE_TIMEOUT:
11500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            {
115120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                if (!param) {
115220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGE("opcode = %d: param is null", opcode_init);
115320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    break;
115420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                }
11550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                uint32_t *timeout_ms = (uint32_t *) param;
11560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                *timeout_ms = 1000;
11570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
11580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
11590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
11600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
11610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_LPM_SET_MODE:
11625752ddcecf884adefc166873565da60e70f59400Thierry Strudel            if (q->soc_type == BT_SOC_AR3K) {
116320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                if (!param) {
116420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGE("opcode = %d: param is null", opcode_init);
116520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    break;
116620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                }
11670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                uint8_t *mode = (uint8_t *) param;
11680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
11690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                if (*mode) {
11700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    lpm_set_ar3k(UPIO_LPM_MODE, UPIO_ASSERT, 0);
11710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
11720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                else {
11730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    lpm_set_ar3k(UPIO_LPM_MODE, UPIO_DEASSERT, 0);
11740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
11755752ddcecf884adefc166873565da60e70f59400Thierry Strudel                q->cb->lpm_cb(BT_VND_OP_RESULT_SUCCESS);
117620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            } else {
1177190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                int lpm_result = BT_VND_OP_RESULT_SUCCESS;
1178190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel
1179190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                property_get("persist.service.bdroid.lpmcfg", lpm_config, "all");
1180190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                ALOGI("%s: property_get: persist.service.bdroid.lpmcfg: %s",
1181190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                            __func__, lpm_config);
1182190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel
1183190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                if (!strcmp(lpm_config, "all")) {
1184190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                    // respond with success since we want to hold wake lock through LPM
1185190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                    lpm_result = BT_VND_OP_RESULT_SUCCESS;
1186190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                }
1187190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                else {
1188190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                    lpm_result = BT_VND_OP_RESULT_FAIL;
1189190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel                }
1190190a4be3a00ae97925465dccdf68ecf1c066306dThierry Strudel
11915752ddcecf884adefc166873565da60e70f59400Thierry Strudel                q->cb->lpm_cb(lpm_result);
11920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
11930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
11940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
119520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        case BT_VND_OP_LPM_WAKE_SET_STATE: {
11965752ddcecf884adefc166873565da60e70f59400Thierry Strudel            switch(q->soc_type) {
119720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            case BT_SOC_CHEROKEE:
119820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            case BT_SOC_ROME: {
119920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                if (!param) {
120020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGE("opcode = %d: param is null", opcode_init);
120120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    break;
120220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                }
120320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                uint8_t *state = (uint8_t *) param;
120420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
120520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                            BT_VND_LPM_WAKE_ASSERT : BT_VND_LPM_WAKE_DEASSERT;
120620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
120720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                if (wake_assert == 0)
120820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGV("ASSERT: Waking up BT-Device");
120920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                else if (wake_assert == 1)
121020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGV("DEASSERT: Allowing BT-Device to Sleep");
121120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
121220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel#ifdef QCOM_BT_SIBS_ENABLE
121320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                ALOGI("Invoking HCI H4 callback function");
12145752ddcecf884adefc166873565da60e70f59400Thierry Strudel                q->cb->lpm_set_state_cb(wake_assert);
121520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel#endif
12160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
12170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
121820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            case BT_SOC_AR3K: {
121920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                if (!param) {
122020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    ALOGE("opcode = %d: param is null", opcode_init);
122120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                    break;
12220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
122320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                uint8_t *state = (uint8_t *) param;
122420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                uint8_t wake_assert = (*state == BT_VND_LPM_WAKE_ASSERT) ? \
122520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                                                UPIO_ASSERT : UPIO_DEASSERT;
122620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                lpm_set_ar3k(UPIO_BT_WAKE, wake_assert, 0);
122720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            }
122820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            case BT_SOC_DEFAULT:
122920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                break;
123020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            default:
12315752ddcecf884adefc166873565da60e70f59400Thierry Strudel                ALOGE("Unknown soc_type: 0x%x", q->soc_type);
123220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                break;
123320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            }
123420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        }
123520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            break;
123620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        case BT_VND_OP_EPILOG: {
123720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel#if (HW_NEED_END_WITH_HCI_RESET == FALSE)
12385752ddcecf884adefc166873565da60e70f59400Thierry Strudel            q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
12390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#else
12405752ddcecf884adefc166873565da60e70f59400Thierry Strudel                switch(q->soc_type)
12410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                {
12420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                  case BT_SOC_CHEROKEE:
12430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                  case BT_SOC_ROME:
12440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                       {
12450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           char value[PROPERTY_VALUE_MAX] = {'\0'};
12460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           property_get("wc_transport.hci_filter_status", value, "0");
12470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           if(is_soc_initialized()&& (strcmp(value,"1") == 0))
12480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           {
124920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                              __hw_epilog_process();
12500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           }
12510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           else
12520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           {
12535752ddcecf884adefc166873565da60e70f59400Thierry Strudel                                q->cb->epilog_cb(BT_VND_OP_RESULT_SUCCESS);
12540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                           }
12550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                       }
12560ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                       break;
12570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                  default:
125820f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                       __hw_epilog_process();
12590ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                       break;
12600ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
12610ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
12620ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
12630ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
12640ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_VND_OP_GET_LINESPEED:
12650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            {
12660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                retval = -1;
12670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                if(!is_soc_initialized()) {
12680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                     ALOGE("BT_VND_OP_GET_LINESPEED: error"
12690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                         " - transport driver not initialized!");
12700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                     break;
12710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                }
12720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
12735752ddcecf884adefc166873565da60e70f59400Thierry Strudel                switch(q->soc_type)
12740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                {
12750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_CHEROKEE:
12760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            retval = 3200000;
12770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
12780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    case BT_SOC_ROME:
12790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                            retval = 3000000;
12800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
12810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                    default:
12820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        retval = userial_vendor_get_baud();
12830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                        break;
12840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                 }
12850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                break;
12860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
12870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
12880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
128920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelout:
129020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    ALOGV("--%s", __FUNCTION__);
12910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return retval;
12920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
12930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
129420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelstatic void ssr_cleanup(int reason)
129520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel{
129620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    int pwr_state = BT_VND_PWR_OFF;
12970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int ret;
12980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    unsigned char trig_ssr = 0xEE;
12991414527307ab6aae2c497b3d2122278cb9ca1aa1Frank Barchard#ifndef ENABLE_ANT
13001414527307ab6aae2c497b3d2122278cb9ca1aa1Frank Barchard    (void)reason;  // unused
13011414527307ab6aae2c497b3d2122278cb9ca1aa1Frank Barchard#endif
13020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
130320f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    ALOGI("++%s", __FUNCTION__);
130420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
13055752ddcecf884adefc166873565da60e70f59400Thierry Strudel    pthread_mutex_lock(&q_lock);
13065752ddcecf884adefc166873565da60e70f59400Thierry Strudel    if (!q) {
13075752ddcecf884adefc166873565da60e70f59400Thierry Strudel        ALOGE("ssr_cleanup called with NULL context");
13085752ddcecf884adefc166873565da60e70f59400Thierry Strudel        goto out;
13095752ddcecf884adefc166873565da60e70f59400Thierry Strudel    }
131020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    if (property_set("wc_transport.patch_dnld_inprog", "null") < 0) {
131120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        ALOGE("Failed to set property");
13120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
13130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
13145752ddcecf884adefc166873565da60e70f59400Thierry Strudel    if (q->soc_type >= BT_SOC_ROME && q->soc_type < BT_SOC_RESERVED) {
131520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel#ifdef ENABLE_ANT
131620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        /*Indicate to filter by sending special byte */
13170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if (reason == CMD_TIMEOUT) {
13180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            trig_ssr = 0xEE;
13190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ret = write (vnd_userial.fd, &trig_ssr, 1);
132020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel            ALOGI("Trig_ssr is being sent to BT socket, ret %d err %s",
132120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                        ret, strerror(errno));
13220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
13230ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            if (is_debug_force_special_bytes()) {
132420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                /*
132520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                 * Then we should send special byte to crash SOC in
132620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                 * WCNSS_Filter, so we do not need to power off UART here.
132720f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel                 */
132841464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudel                goto out;
13290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
13300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
133120f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
133220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        /* Close both ANT channel */
1333d659daacec1c7697ad086dee638759c8991ebe45Mark Urbanus        op(BT_VND_OP_ANT_USERIAL_CLOSE, NULL);
13340ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
133520f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel        /* Close both BT channel */
1336d659daacec1c7697ad086dee638759c8991ebe45Mark Urbanus        op(BT_VND_OP_USERIAL_CLOSE, NULL);
13370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
13380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef FM_OVER_UART
1339d659daacec1c7697ad086dee638759c8991ebe45Mark Urbanus        op(BT_VND_OP_FM_USERIAL_CLOSE, NULL);
13400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
13410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        /*CTRL OFF twice to make sure hw
13420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel         * turns off*/
13430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef ENABLE_ANT
1344d659daacec1c7697ad086dee638759c8991ebe45Mark Urbanus        op(BT_VND_OP_POWER_CTRL, &pwr_state);
13450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif
13460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
13470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    /*Generally switching of chip should be enough*/
1348d659daacec1c7697ad086dee638759c8991ebe45Mark Urbanus    op(BT_VND_OP_POWER_CTRL, &pwr_state);
134920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
135041464994bbeb484687aa81ac08b72b8e51d37b11Thierry Strudelout:
13515752ddcecf884adefc166873565da60e70f59400Thierry Strudel    pthread_mutex_unlock(&q_lock);
135220f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    ALOGI("--%s", __FUNCTION__);
13530ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
13540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
13550ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/** Closes the interface */
135620f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudelstatic void cleanup(void)
13570ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel{
13580ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGI("cleanup");
135920f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel
136020f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    pthread_mutex_lock(&q_lock);
13615752ddcecf884adefc166873565da60e70f59400Thierry Strudel    q->cb = NULL;
13625752ddcecf884adefc166873565da60e70f59400Thierry Strudel    free(q);
13635752ddcecf884adefc166873565da60e70f59400Thierry Strudel    q = NULL;
136420f50076d30e7d1c55c2d8206e01534f2df9112bThierry Strudel    pthread_mutex_unlock(&q_lock);
13650ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
13660ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#ifdef WIFI_BT_STATUS_SYNC
13670ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    isInit = 0;
13680ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel#endif /* WIFI_BT_STATUS_SYNC */
13690ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
13700ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
13710ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel/* Check for one of the cients ANT/BT patch download is already in
13720ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel** progress if yes wait till complete
13730ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel*/
13740ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelvoid wait_for_patch_download(bool is_ant_req) {
13750ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGV("%s:", __FUNCTION__);
13760ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
13770ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    while (1) {
13780ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
13790ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
13800ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        if(is_ant_req && !(strcmp(inProgress,"bt"))) {
13810ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           //ANT request, wait for BT to finish
13820ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           usleep(50000);
13830ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
13840ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        else if(!is_ant_req && !(strcmp(inProgress,"ant"))) {
13850ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel          //BT request, wait for ANT to finish
13860ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           usleep(50000);
13870ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
13880ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        else {
13890ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           ALOGI("%s: patch download completed", __FUNCTION__);
13900ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel           break;
13910ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        }
13920ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
13930ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
13940ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
13950ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelbool is_download_progress () {
13960ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char inProgress[PROPERTY_VALUE_MAX] = {'\0'};
13970ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bool retval = false;
13980ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
13990ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ALOGV("%s:", __FUNCTION__);
14000ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
14015752ddcecf884adefc166873565da60e70f59400Thierry Strudel    if ((q->soc_type = get_bt_soc_type()) < 0) {
14020ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGE("%s: Failed to detect BT SOC Type", __FUNCTION__);
14030ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        return -1;
14040ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
14050ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
14065752ddcecf884adefc166873565da60e70f59400Thierry Strudel    switch(q->soc_type)
14070ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    {
14080ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_SOC_ROME:
14090ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ALOGI("%s: ROME case", __func__);
14100ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            property_get("wc_transport.patch_dnld_inprog", inProgress, "null");
14110ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            if(strcmp(inProgress,"null") == 0) {
14120ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                retval = false;
14130ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            } else {
14140ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel                 retval = true;
14150ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            }
14160ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
14170ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_SOC_CHEROKEE:
14180ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            ALOGI("%s: CHEROKEE case", __func__);
14190ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
14200ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        case BT_SOC_DEFAULT:
14210ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
14220ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        default:
14235752ddcecf884adefc166873565da60e70f59400Thierry Strudel            ALOGE("Unknown btSocType: 0x%x", q->soc_type);
14240ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            break;
14250ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
14260ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return retval;
14270ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
14280ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
14290ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelstatic bool is_debug_force_special_bytes() {
14300ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    int ret = 0;
14310ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    char value[PROPERTY_VALUE_MAX] = {'\0'};
14320ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    bool enabled = false;
1433bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel#ifdef ENABLE_DBG_FLAGS
1434bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel    enabled = true;
1435bc37ff26d048752c4ef50c9dd28945aa8bfe6f5aThierry Strudel#endif
14360ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
14370ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    ret = property_get("wc_transport.force_special_byte", value, NULL);
14380ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
14390ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    if (ret) {
14400ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        enabled = (strcmp(value, "false") ==0) ? false : true;
14410ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel        ALOGV("%s: wc_transport.force_special_byte: %s, enabled: %d ",
14420ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel            __func__, value, enabled);
14430ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    }
14440ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
14450ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    return enabled;
14460ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel}
14470ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel
14480ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel// Entry point of DLib
14490ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudelconst bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
14500ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    sizeof(bt_vendor_interface_t),
14510ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    init,
14520ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel    op,
14531414527307ab6aae2c497b3d2122278cb9ca1aa1Frank Barchard    cleanup
14540ebd0bab066cd86d7a19f4646e0686dae885004eThierry Strudel};
1455