• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 #define LOG_TAG "bluedroid"
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <stdlib.h>
22 #include <sys/ioctl.h>
23 #include <sys/socket.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 
27 #include <cutils/log.h>
28 #include <cutils/properties.h>
29 
30 #include <bluetooth/bluetooth.h>
31 #include <bluetooth/hci.h>
32 #include <bluetooth/hci_lib.h>
33 
34 #include <bluedroid/bluetooth.h>
35 
36 #ifndef HCI_DEV_ID
37 #define HCI_DEV_ID 0
38 #endif
39 
40 #define HCID_STOP_DELAY_USEC 500000
41 
42 #define MIN(x,y) (((x)<(y))?(x):(y))
43 
44 
45 static int rfkill_id = -1;
46 static char *rfkill_state_path = NULL;
47 
48 #ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
init_rfkill()49 static int init_rfkill() {
50     char path[64];
51     char buf[16];
52     int fd;
53     int sz;
54     int id;
55     for (id = 0; ; id++) {
56         snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
57         fd = open(path, O_RDONLY);
58         if (fd < 0) {
59             ALOGW("open(%s) failed: %s (%d)\n", path, strerror(errno), errno);
60             return -1;
61         }
62         sz = read(fd, &buf, sizeof(buf));
63         close(fd);
64         if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) {
65             rfkill_id = id;
66             break;
67         }
68     }
69 
70     asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
71     return 0;
72 }
73 
check_bluetooth_power()74 static int check_bluetooth_power() {
75     int sz;
76     int fd = -1;
77     int ret = -1;
78     char buffer;
79 
80     if (rfkill_id == -1) {
81         if (init_rfkill()) goto out;
82     }
83 
84     fd = open(rfkill_state_path, O_RDONLY);
85     if (fd < 0) {
86         ALOGE("open(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
87              errno);
88         goto out;
89     }
90     sz = read(fd, &buffer, 1);
91     if (sz != 1) {
92         ALOGE("read(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
93              errno);
94         goto out;
95     }
96 
97     switch (buffer) {
98     case '1':
99         ret = 1;
100         break;
101     case '0':
102         ret = 0;
103         break;
104     }
105 
106 out:
107     if (fd >= 0) close(fd);
108     return ret;
109 }
110 
set_bluetooth_power(int on)111 static int set_bluetooth_power(int on) {
112     int sz;
113     int fd = -1;
114     int ret = -1;
115     const char buffer = (on ? '1' : '0');
116 
117     if (rfkill_id == -1) {
118         if (init_rfkill()) goto out;
119     }
120 
121     fd = open(rfkill_state_path, O_WRONLY);
122     if (fd < 0) {
123         ALOGE("open(%s) for write failed: %s (%d)", rfkill_state_path,
124              strerror(errno), errno);
125         goto out;
126     }
127     sz = write(fd, &buffer, 1);
128     if (sz < 0) {
129         ALOGE("write(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
130              errno);
131         goto out;
132     }
133     ret = 0;
134 
135 out:
136     if (fd >= 0) close(fd);
137     return ret;
138 }
139 #endif
140 
create_hci_sock()141 static inline int create_hci_sock() {
142     int sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
143     if (sk < 0) {
144         ALOGE("Failed to create bluetooth hci socket: %s (%d)",
145              strerror(errno), errno);
146     }
147     return sk;
148 }
149 
bt_enable()150 int bt_enable() {
151     ALOGV(__FUNCTION__);
152 
153     int ret = -1;
154     int hci_sock = -1;
155     int attempt;
156 
157 #ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
158     if (set_bluetooth_power(1) < 0) goto out;
159 #endif
160 
161 #ifndef BLUETOOTH_HCIATTACH_USING_PROPERTY
162     ALOGI("Starting hciattach daemon");
163     if (property_set("ctl.start", "hciattach") < 0)
164 #else
165     ALOGI("Enable hci tranport");
166     if (property_set("bluetooth.hciattach", "true") < 0)
167 #endif
168     {
169         ALOGE("Failed to start hciattach");
170 #ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
171         set_bluetooth_power(0);
172 #endif
173         goto out;
174     }
175 
176     // Try for 10 seconds, this can only succeed once hciattach has sent the
177     // firmware and then turned on hci device via HCIUARTSETPROTO ioctl
178     for (attempt = 100; attempt > 0;  attempt--) {
179         hci_sock = create_hci_sock();
180         if (hci_sock < 0) goto out;
181 
182         ret = ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID);
183 
184         if (!ret) {
185             break;
186         } else if (errno == EALREADY) {
187             ALOGW("Bluetoothd already started, unexpectedly!");
188             break;
189         }
190 
191         ALOGI("%s: ioctl(%d, HCIDEVUP, HCI_DEV_ID) failed: %s (%d)",
192               __FUNCTION__, hci_sock, strerror(errno), errno);
193 
194         close(hci_sock);
195         usleep(100 * 1000);  // 100 ms retry delay
196     }
197     if (attempt == 0) {
198         ALOGE("%s: Timeout waiting for HCI device to come up, error- %d, ",
199             __FUNCTION__, ret);
200         if (property_set("ctl.stop", "hciattach") < 0) {
201             ALOGE("Error stopping hciattach");
202         }
203 #ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
204         set_bluetooth_power(0);
205 #endif
206         goto out;
207     }
208 
209     ALOGI("Starting bluetoothd deamon");
210     if (property_set("ctl.start", "bluetoothd") < 0) {
211         ALOGE("Failed to start bluetoothd");
212 #ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
213         set_bluetooth_power(0);
214 #endif
215         goto out;
216     }
217 
218     ret = 0;
219 
220 out:
221     if (hci_sock >= 0) close(hci_sock);
222     return ret;
223 }
224 
bt_disable()225 int bt_disable() {
226     ALOGV(__FUNCTION__);
227 
228     int ret = -1;
229     int hci_sock = -1;
230 
231     ALOGI("Stopping bluetoothd deamon");
232     if (property_set("ctl.stop", "bluetoothd") < 0) {
233         ALOGE("Error stopping bluetoothd");
234         goto out;
235     }
236     usleep(HCID_STOP_DELAY_USEC);
237 
238     hci_sock = create_hci_sock();
239     if (hci_sock < 0) goto out;
240     ioctl(hci_sock, HCIDEVDOWN, HCI_DEV_ID);
241 
242 #ifndef BLUETOOTH_HCIATTACH_USING_PROPERTY
243     ALOGI("Stopping hciattach deamon");
244     if (property_set("ctl.stop", "hciattach") < 0)
245 #else
246     ALOGI("Disable hci tranport");
247     if (property_set("bluetooth.hciattach", "false") < 0)
248 #endif
249     {
250         ALOGE("Error stopping hciattach");
251         goto out;
252     }
253 
254 #ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
255     if (set_bluetooth_power(0) < 0) {
256         goto out;
257     }
258 #endif
259     ret = 0;
260 
261 out:
262     if (hci_sock >= 0) close(hci_sock);
263     return ret;
264 }
265 
bt_is_enabled()266 int bt_is_enabled() {
267     ALOGV(__FUNCTION__);
268 
269     int hci_sock = -1;
270     int ret = -1;
271     struct hci_dev_info dev_info;
272 
273 
274 #ifndef BLUETOOTH_DOES_NOT_USE_RFKILL
275     // Check power first
276     ret = check_bluetooth_power();
277     if (ret == -1 || ret == 0) goto out;
278 #endif
279 
280     ret = -1;
281 
282     // Power is on, now check if the HCI interface is up
283     hci_sock = create_hci_sock();
284     if (hci_sock < 0) goto out;
285 
286     dev_info.dev_id = HCI_DEV_ID;
287     if (ioctl(hci_sock, HCIGETDEVINFO, (void *)&dev_info) < 0) {
288         ret = 0;
289         goto out;
290     }
291 
292     if (dev_info.flags & (1 << (HCI_UP & 31))) {
293         ret = 1;
294     } else {
295         ret = 0;
296     }
297 
298 out:
299     if (hci_sock >= 0) close(hci_sock);
300     return ret;
301 }
302 
ba2str(const bdaddr_t * ba,char * str)303 int ba2str(const bdaddr_t *ba, char *str) {
304     return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
305                 ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
306 }
307 
str2ba(const char * str,bdaddr_t * ba)308 int str2ba(const char *str, bdaddr_t *ba) {
309     int i;
310     for (i = 5; i >= 0; i--) {
311         ba->b[i] = (uint8_t) strtoul(str, (char **) &str, 16);
312         str++;
313     }
314     return 0;
315 }
316