2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define LOG_TAG "bluedroid"
22 #include <sys/ioctl.h>
23 #include <sys/socket.h>
24 #include <sys/types.h>
27 #include <cutils/log.h>
28 #include <cutils/properties.h>
30 #include <bluetooth/bluetooth.h>
31 #include <bluetooth/hci.h>
32 #include <bluetooth/hci_lib.h>
34 #include <bluedroid/bluetooth.h>
40 #define HCID_STOP_DELAY_USEC 500000
42 #define MIN(x,y) (((x)<(y))?(x):(y))
45 static const char *sysrfkill = "/sys/class/rfkill";
46 static char rfkill_state_path[64] = "";
49 static int init_rfkill() {
55 DIR *sysdir = opendir(sysrfkill);
58 LOGE("opendir failed: %s (%d)\n", strerror(errno), errno);
62 while ((entry = readdir(sysdir))) {
63 if (entry->d_name[0] == '.')
65 snprintf(path, sizeof(path), "%s/%s/type", sysrfkill, entry->d_name);
66 fd = open(path, O_RDONLY);
68 LOGW("open(%s) failed: %s (%d)\n", path, strerror(errno), errno);
71 sz = read(fd, &buf, sizeof(buf));
73 if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) {
74 snprintf(rfkill_state_path, sizeof(rfkill_state_path),
75 "%s/%s/state", sysrfkill, entry->d_name);
81 return rfkill_state_path[0] ? 0 : -1;
84 static int check_bluetooth_power() {
90 if (rfkill_state_path[0] == '\0') {
91 if (init_rfkill()) goto out;
94 fd = open(rfkill_state_path, O_RDONLY);
96 LOGE("open(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
100 sz = read(fd, &buffer, 1);
102 LOGE("read(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
117 if (fd >= 0) close(fd);
121 static int set_bluetooth_power(int on) {
125 const char buffer = (on ? '1' : '0');
127 if (rfkill_state_path[0] == '\0') {
128 if (init_rfkill()) goto out;
131 fd = open(rfkill_state_path, O_WRONLY);
133 LOGE("open(%s) for write failed: %s (%d)", rfkill_state_path,
134 strerror(errno), errno);
137 sz = write(fd, &buffer, 1);
139 LOGE("write(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
146 if (fd >= 0) close(fd);
150 static inline int create_hci_sock() {
151 int sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
153 LOGE("Failed to create bluetooth hci socket: %s (%d)",
154 strerror(errno), errno);
166 if (set_bluetooth_power(1) < 0) goto out;
168 LOGI("Starting hciattach daemon");
169 if (property_set("ctl.start", "hciattach") < 0) {
170 LOGE("Failed to start hciattach");
171 set_bluetooth_power(0);
175 // Try for 10 seconds, this can only succeed once hciattach has sent the
176 // firmware and then turned on hci device via HCIUARTSETPROTO ioctl
177 for (attempt = 1000; attempt > 0; attempt--) {
178 hci_sock = create_hci_sock();
179 if (hci_sock < 0) goto out;
181 if (!ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID)) {
185 usleep(10000); // 10 ms retry delay
188 LOGE("%s: Timeout waiting for HCI device to come up", __FUNCTION__);
189 set_bluetooth_power(0);
193 LOGI("Starting bluetoothd deamon");
194 if (property_set("ctl.start", "bluetoothd") < 0) {
195 LOGE("Failed to start bluetoothd");
196 set_bluetooth_power(0);
203 if (hci_sock >= 0) close(hci_sock);
213 LOGI("Stopping bluetoothd deamon");
214 if (property_set("ctl.stop", "bluetoothd") < 0) {
215 LOGE("Error stopping bluetoothd");
218 usleep(HCID_STOP_DELAY_USEC);
220 hci_sock = create_hci_sock();
221 if (hci_sock < 0) goto out;
222 ioctl(hci_sock, HCIDEVDOWN, HCI_DEV_ID);
224 LOGI("Stopping hciattach deamon");
225 if (property_set("ctl.stop", "hciattach") < 0) {
226 LOGE("Error stopping hciattach");
230 if (set_bluetooth_power(0) < 0) {
236 rfkill_state_path[0] = '\0';
238 if (hci_sock >= 0) close(hci_sock);
242 int bt_is_enabled() {
247 struct hci_dev_info dev_info;
251 ret = check_bluetooth_power();
252 if (ret == -1 || ret == 0) goto out;
256 // Power is on, now check if the HCI interface is up
257 hci_sock = create_hci_sock();
258 if (hci_sock < 0) goto out;
260 dev_info.dev_id = HCI_DEV_ID;
261 if (ioctl(hci_sock, HCIGETDEVINFO, (void *)&dev_info) < 0) {
266 ret = hci_test_bit(HCI_UP, &dev_info.flags);
269 if (hci_sock >= 0) close(hci_sock);
273 int ba2str(const bdaddr_t *ba, char *str) {
274 return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
275 ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
278 int str2ba(const char *str, bdaddr_t *ba) {
280 for (i = 5; i >= 0; i--) {
281 ba->b[i] = (uint8_t) strtoul(str, &str, 16);