17342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project/*
27342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
37342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project *
47342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
57342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project * you may not use this file except in compliance with the License.
67342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project * You may obtain a copy of the License at
77342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project *
87342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
97342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project *
107342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
117342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
127342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project * See the License for the specific language governing permissions and
147342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project * limitations under the License.
157342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project */
167342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
177342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#define LOG_TAG "bluedroid"
187342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
197342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <errno.h>
207342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <fcntl.h>
216e6506eb74c918e761f9ba08a6c71897334747c1Glenn Kasten#include <stdlib.h>
227342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <sys/ioctl.h>
237342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <sys/socket.h>
247342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <sys/types.h>
257342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <sys/stat.h>
267342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
277342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <cutils/log.h>
287342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <cutils/properties.h>
297342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
307342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <bluetooth/bluetooth.h>
317342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <bluetooth/hci.h>
327342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <bluetooth/hci_lib.h>
337342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
347342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#include <bluedroid/bluetooth.h>
357342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
367342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#ifndef HCI_DEV_ID
377342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#define HCI_DEV_ID 0
387342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#endif
397342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
407342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#define HCID_STOP_DELAY_USEC 500000
417342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
427342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project#define MIN(x,y) (((x)<(y))?(x):(y))
437342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
447342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
457342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic int rfkill_id = -1;
467342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic char *rfkill_state_path = NULL;
477342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
483a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
497342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic int init_rfkill() {
507342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    char path[64];
517342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    char buf[16];
527342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int fd;
537342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int sz;
547342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int id;
557342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    for (id = 0; ; id++) {
567342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
577342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        fd = open(path, O_RDONLY);
587342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        if (fd < 0) {
599f71f85140223aa110f29440cfb87de2d760761aSteve Block            ALOGW("open(%s) failed: %s (%d)\n", path, strerror(errno), errno);
607342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project            return -1;
617342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        }
627342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        sz = read(fd, &buf, sizeof(buf));
637342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        close(fd);
647342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) {
657342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project            rfkill_id = id;
667342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project            break;
677342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        }
687342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
697342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
707342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
717342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    return 0;
727342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project}
737342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
747342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic int check_bluetooth_power() {
757342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int sz;
767342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int fd = -1;
777342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int ret = -1;
787342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    char buffer;
797342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
807342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (rfkill_id == -1) {
817342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        if (init_rfkill()) goto out;
827342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
837342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
847342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    fd = open(rfkill_state_path, O_RDONLY);
857342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (fd < 0) {
869657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("open(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
877342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project             errno);
887342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
897342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
907342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    sz = read(fd, &buffer, 1);
917342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (sz != 1) {
929657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("read(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
937342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project             errno);
947342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
957342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
967342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
977342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    switch (buffer) {
987342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    case '1':
997342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        ret = 1;
1007342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        break;
1017342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    case '0':
1027342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        ret = 0;
1037342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        break;
1047342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
1057342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1067342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectout:
1077342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (fd >= 0) close(fd);
1087342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    return ret;
1097342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project}
1107342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1117342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic int set_bluetooth_power(int on) {
1127342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int sz;
1137342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int fd = -1;
1147342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int ret = -1;
1157342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    const char buffer = (on ? '1' : '0');
1167342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1177342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (rfkill_id == -1) {
1187342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        if (init_rfkill()) goto out;
1197342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
1207342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1217342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    fd = open(rfkill_state_path, O_WRONLY);
1227342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (fd < 0) {
1239657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("open(%s) for write failed: %s (%d)", rfkill_state_path,
1247342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project             strerror(errno), errno);
1257342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
1267342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
1277342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    sz = write(fd, &buffer, 1);
1287342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (sz < 0) {
1299657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("write(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
1307342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project             errno);
1317342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
1327342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
1337342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    ret = 0;
1347342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1357342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectout:
1367342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (fd >= 0) close(fd);
1377342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    return ret;
1387342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project}
1393a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#endif
1407342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1417342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectstatic inline int create_hci_sock() {
1427342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
1437342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (sk < 0) {
1449657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("Failed to create bluetooth hci socket: %s (%d)",
1457342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project             strerror(errno), errno);
1467342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
1477342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    return sk;
1487342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project}
1497342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1507342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectint bt_enable() {
151c7be2810d52c07f8cff574c93166a02f3c14d878Steve Block    ALOGV(__FUNCTION__);
1527342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1537342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int ret = -1;
1547342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int hci_sock = -1;
1557342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int attempt;
1567342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1573a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
1587342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (set_bluetooth_power(1) < 0) goto out;
1593a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#endif
1607342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1613a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#ifndef BLUETOOTH_HCIATTACH_USING_PROPERTY
16264661e48d99f432299e40bde2d11b26944a71dd4Steve Block    ALOGI("Starting hciattach daemon");
1633a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim    if (property_set("ctl.start", "hciattach") < 0)
1643a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#else
1653a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim    ALOGI("Enable hci tranport");
1663a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim    if (property_set("bluetooth.hciattach", "true") < 0)
1673a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#endif
1683a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim    {
1699657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("Failed to start hciattach");
1703a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
171dad064dc614b7c582a011f0addbff2a9eb68c195Jaikumar Ganesh        set_bluetooth_power(0);
1723a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#endif
1737342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
1747342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
1757342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
1767342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    // Try for 10 seconds, this can only succeed once hciattach has sent the
1777342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    // firmware and then turned on hci device via HCIUARTSETPROTO ioctl
178bf6696874d1b57ffddc7848450b20e926ad5d0a4Elliott Hughes    for (attempt = 100; attempt > 0;  attempt--) {
1797342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        hci_sock = create_hci_sock();
1807342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        if (hci_sock < 0) goto out;
1817342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
18204a1a722bda65ea26fc449a613085909056c1fa2Jaikumar Ganesh        ret = ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID);
18362432dd0bb4d59f640bde9309f86eef2fd984f18Matthew Xie
18404a1a722bda65ea26fc449a613085909056c1fa2Jaikumar Ganesh        if (!ret) {
1857342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project            break;
18662432dd0bb4d59f640bde9309f86eef2fd984f18Matthew Xie        } else if (errno == EALREADY) {
1879f71f85140223aa110f29440cfb87de2d760761aSteve Block            ALOGW("Bluetoothd already started, unexpectedly!");
18862432dd0bb4d59f640bde9309f86eef2fd984f18Matthew Xie            break;
1897342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        }
19062432dd0bb4d59f640bde9309f86eef2fd984f18Matthew Xie
191bf6696874d1b57ffddc7848450b20e926ad5d0a4Elliott Hughes        ALOGI("%s: ioctl(%d, HCIDEVUP, HCI_DEV_ID) failed: %s (%d)",
192bf6696874d1b57ffddc7848450b20e926ad5d0a4Elliott Hughes              __FUNCTION__, hci_sock, strerror(errno), errno);
193bf6696874d1b57ffddc7848450b20e926ad5d0a4Elliott Hughes
1947342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        close(hci_sock);
195bf6696874d1b57ffddc7848450b20e926ad5d0a4Elliott Hughes        usleep(100 * 1000);  // 100 ms retry delay
1967342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
1977342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (attempt == 0) {
1989657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("%s: Timeout waiting for HCI device to come up, error- %d, ",
19904a1a722bda65ea26fc449a613085909056c1fa2Jaikumar Ganesh            __FUNCTION__, ret);
200cd60add87bf628e96d3a91dc96d4bf945a0ccb17jhtop.kim        if (property_set("ctl.stop", "hciattach") < 0) {
2019657b13bd143660e9285e9bec379eec12c866110Steve Block            ALOGE("Error stopping hciattach");
202cd60add87bf628e96d3a91dc96d4bf945a0ccb17jhtop.kim        }
2033a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
204dad064dc614b7c582a011f0addbff2a9eb68c195Jaikumar Ganesh        set_bluetooth_power(0);
2053a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#endif
2067342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
2077342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
2087342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
20964661e48d99f432299e40bde2d11b26944a71dd4Steve Block    ALOGI("Starting bluetoothd deamon");
21012f7feb45d8bfcf8514143103ac30bc4efee26f6Jaikumar Ganesh    if (property_set("ctl.start", "bluetoothd") < 0) {
2119657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("Failed to start bluetoothd");
2123a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
213dad064dc614b7c582a011f0addbff2a9eb68c195Jaikumar Ganesh        set_bluetooth_power(0);
2143a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#endif
2157342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
2167342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
2177342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2187342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    ret = 0;
2197342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2207342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectout:
2217342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (hci_sock >= 0) close(hci_sock);
2227342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    return ret;
2237342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project}
2247342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2257342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectint bt_disable() {
226c7be2810d52c07f8cff574c93166a02f3c14d878Steve Block    ALOGV(__FUNCTION__);
2277342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2287342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int ret = -1;
2297342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int hci_sock = -1;
2307342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
23164661e48d99f432299e40bde2d11b26944a71dd4Steve Block    ALOGI("Stopping bluetoothd deamon");
23212f7feb45d8bfcf8514143103ac30bc4efee26f6Jaikumar Ganesh    if (property_set("ctl.stop", "bluetoothd") < 0) {
2339657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("Error stopping bluetoothd");
2347342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
2357342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
2367342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    usleep(HCID_STOP_DELAY_USEC);
2377342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2387342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    hci_sock = create_hci_sock();
2397342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (hci_sock < 0) goto out;
2407342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    ioctl(hci_sock, HCIDEVDOWN, HCI_DEV_ID);
2417342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2423a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#ifndef BLUETOOTH_HCIATTACH_USING_PROPERTY
24364661e48d99f432299e40bde2d11b26944a71dd4Steve Block    ALOGI("Stopping hciattach deamon");
2443a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim    if (property_set("ctl.stop", "hciattach") < 0)
2453a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#else
2463a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim    ALOGI("Disable hci tranport");
2473a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim    if (property_set("bluetooth.hciattach", "false") < 0)
2483a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#endif
2493a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim    {
2509657b13bd143660e9285e9bec379eec12c866110Steve Block        ALOGE("Error stopping hciattach");
2517342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
2527342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
2537342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2543a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
2557342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (set_bluetooth_power(0) < 0) {
2567342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
2577342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
2583a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#endif
2597342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    ret = 0;
2607342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2617342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectout:
2627342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (hci_sock >= 0) close(hci_sock);
2637342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    return ret;
2647342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project}
2657342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2667342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectint bt_is_enabled() {
267c7be2810d52c07f8cff574c93166a02f3c14d878Steve Block    ALOGV(__FUNCTION__);
2687342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2697342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int hci_sock = -1;
2707342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    int ret = -1;
2717342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    struct hci_dev_info dev_info;
2727342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2737342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2743a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
2757342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    // Check power first
2767342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    ret = check_bluetooth_power();
2777342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (ret == -1 || ret == 0) goto out;
2783a293d2850d4530054cdcc78a4a747d6c4f0fff1jeonghoon.lim#endif
2797342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2807342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    ret = -1;
2817342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2827342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    // Power is on, now check if the HCI interface is up
2837342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    hci_sock = create_hci_sock();
2847342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (hci_sock < 0) goto out;
2857342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2867342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    dev_info.dev_id = HCI_DEV_ID;
2877342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (ioctl(hci_sock, HCIGETDEVINFO, (void *)&dev_info) < 0) {
2887342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        ret = 0;
2897342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project        goto out;
2907342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    }
2917342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2921890bf01833f6cab431f014af7a20fcbed3a4e13Jaikumar Ganesh    if (dev_info.flags & (1 << (HCI_UP & 31))) {
2931890bf01833f6cab431f014af7a20fcbed3a4e13Jaikumar Ganesh        ret = 1;
2941890bf01833f6cab431f014af7a20fcbed3a4e13Jaikumar Ganesh    } else {
2951890bf01833f6cab431f014af7a20fcbed3a4e13Jaikumar Ganesh        ret = 0;
2961890bf01833f6cab431f014af7a20fcbed3a4e13Jaikumar Ganesh    }
2977342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project
2987342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Projectout:
2997342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    if (hci_sock >= 0) close(hci_sock);
3007342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project    return ret;
3017342a3e6a751116a193ff27d69b87eda478a5016The Android Open Source Project}
302a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly
303a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pellyint ba2str(const bdaddr_t *ba, char *str) {
304a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly    return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
305a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly                ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
306a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly}
307a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly
308a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pellyint str2ba(const char *str, bdaddr_t *ba) {
309a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly    int i;
310a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly    for (i = 5; i >= 0; i--) {
3116e6506eb74c918e761f9ba08a6c71897334747c1Glenn Kasten        ba->b[i] = (uint8_t) strtoul(str, (char **) &str, 16);
312a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly        str++;
313a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly    }
314a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly    return 0;
315a15c33f9aaf27f75a7f6fa02a539b54caace4d35Nick Pelly}
316