Added custom bluedroid
Change-Id: Iaf072ca3912f3b141b93d8b0e2d75b3ec5e5c1cf
This commit is contained in:
parent
a5bfeb9314
commit
896c792e87
306
bluedroid/bluetooth.c
Normal file
306
bluedroid/bluetooth.c
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "bluedroid"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/hci_lib.h>
|
||||
|
||||
#include <bluedroid/bluetooth.h>
|
||||
|
||||
#ifndef HCI_DEV_ID
|
||||
#define HCI_DEV_ID 0
|
||||
#endif
|
||||
|
||||
#define HCID_START_DELAY_SEC 3
|
||||
#define HCID_STOP_DELAY_USEC 500000
|
||||
|
||||
#define MIN(x,y) (((x)<(y))?(x):(y))
|
||||
|
||||
|
||||
static int rfkill_id = -1;
|
||||
static char *rfkill_state_path = NULL;
|
||||
|
||||
|
||||
static int init_rfkill(int id) {
|
||||
char path[64];
|
||||
char buf[16];
|
||||
int fd;
|
||||
int sz;
|
||||
int rfkill_id;
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
LOGW("open(%s) failed: %s (%d)\n", path, strerror(errno), errno);
|
||||
return -1;
|
||||
}
|
||||
sz = read(fd, &buf, sizeof(buf));
|
||||
close(fd);
|
||||
if (sz >= 9 && memcmp(buf, "bluetooth", 9) == 0) {
|
||||
rfkill_id = id;
|
||||
if (rfkill_state_path)
|
||||
free(rfkill_state_path);
|
||||
asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
|
||||
} else {
|
||||
LOGW("/sys/class/rfkill/rfkill%d/state is not owned by bluetooth, ignoring", id);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_bluetooth_power() {
|
||||
int sz;
|
||||
int fd = -1;
|
||||
int ret = -1;
|
||||
char buffer;
|
||||
|
||||
if (init_rfkill(0)) goto out;
|
||||
|
||||
fd = open(rfkill_state_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
LOGE("open(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
sz = read(fd, &buffer, 1);
|
||||
if (sz != 1) {
|
||||
LOGE("read(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (buffer) {
|
||||
case '1':
|
||||
ret = 1;
|
||||
break;
|
||||
case '0':
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if (fd >= 0) close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_bluetooth_power(int on) {
|
||||
int sz;
|
||||
int fd = -1;
|
||||
int ret = -1;
|
||||
const char buffer = (on ? '1' : '0');
|
||||
|
||||
if (init_rfkill(0)) goto out;
|
||||
|
||||
fd = open(rfkill_state_path, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
LOGE("open(%s) for write failed: %s (%d)", rfkill_state_path,
|
||||
strerror(errno), errno);
|
||||
goto out;
|
||||
}
|
||||
sz = write(fd, &buffer, 1);
|
||||
if (sz < 0) {
|
||||
LOGE("write(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (fd >= 0) close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* sleep on means allow sleep */
|
||||
static int set_bluetooth_sleep(int on) {
|
||||
int sz;
|
||||
int fd = -1;
|
||||
int ret = -1;
|
||||
const char buffer = (on ? '1' : '0');
|
||||
|
||||
if (init_rfkill(1)) goto out;
|
||||
|
||||
fd = open(rfkill_state_path, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
LOGE("open(%s) for write failed: %s (%d)", rfkill_state_path,
|
||||
strerror(errno), errno);
|
||||
goto out;
|
||||
}
|
||||
sz = write(fd, &buffer, 1);
|
||||
if (sz < 0) {
|
||||
LOGE("write(%s) failed: %s (%d)", rfkill_state_path, strerror(errno),
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (fd >= 0) close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int create_hci_sock() {
|
||||
int sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
|
||||
if (sk < 0) {
|
||||
LOGE("Failed to create bluetooth hci socket: %s (%d)",
|
||||
strerror(errno), errno);
|
||||
}
|
||||
return sk;
|
||||
}
|
||||
|
||||
int bt_enable() {
|
||||
LOGV(__FUNCTION__);
|
||||
|
||||
int ret = -1;
|
||||
int hci_sock = -1;
|
||||
int attempt;
|
||||
|
||||
if (set_bluetooth_power(1) < 0) goto out;
|
||||
|
||||
LOGI("Starting hciattach daemon");
|
||||
if (property_set("ctl.start", "hciattach") < 0) {
|
||||
LOGE("Failed to start hciattach");
|
||||
set_bluetooth_power(0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Try for 10 seconds, this can only succeed once hciattach has sent the
|
||||
// firmware and then turned on hci device via HCIUARTSETPROTO ioctl
|
||||
for (attempt = 1000; attempt > 0; attempt--) {
|
||||
hci_sock = create_hci_sock();
|
||||
if (hci_sock < 0) goto out;
|
||||
|
||||
if (!ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID)) {
|
||||
break;
|
||||
}
|
||||
close(hci_sock);
|
||||
usleep(10000); // 10 ms retry delay
|
||||
}
|
||||
if (attempt == 0) {
|
||||
LOGE("%s: Timeout waiting for HCI device to come up", __FUNCTION__);
|
||||
set_bluetooth_power(0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
LOGI("Starting bluetoothd deamon");
|
||||
if (property_set("ctl.start", "bluetoothd") < 0) {
|
||||
LOGE("Failed to start bluetoothd");
|
||||
set_bluetooth_power(0);
|
||||
goto out;
|
||||
}
|
||||
sleep(HCID_START_DELAY_SEC);
|
||||
|
||||
if (set_bluetooth_sleep(0) < 0) goto out;
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (hci_sock >= 0) close(hci_sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bt_disable() {
|
||||
LOGV(__FUNCTION__);
|
||||
|
||||
int ret = -1;
|
||||
int hci_sock = -1;
|
||||
|
||||
if (set_bluetooth_sleep(1) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
LOGI("Stopping bluetoothd deamon");
|
||||
if (property_set("ctl.stop", "bluetoothd") < 0) {
|
||||
LOGE("Error stopping bluetoothd");
|
||||
goto out;
|
||||
}
|
||||
usleep(HCID_STOP_DELAY_USEC);
|
||||
|
||||
hci_sock = create_hci_sock();
|
||||
if (hci_sock < 0) goto out;
|
||||
ioctl(hci_sock, HCIDEVDOWN, HCI_DEV_ID);
|
||||
|
||||
LOGI("Stopping hciattach deamon");
|
||||
if (property_set("ctl.stop", "hciattach") < 0) {
|
||||
LOGE("Error stopping hciattach");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (set_bluetooth_power(0) < 0) {
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
if (hci_sock >= 0) close(hci_sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bt_is_enabled() {
|
||||
LOGV(__FUNCTION__);
|
||||
|
||||
int hci_sock = -1;
|
||||
int ret = -1;
|
||||
struct hci_dev_info dev_info;
|
||||
|
||||
|
||||
// Check power first
|
||||
ret = check_bluetooth_power();
|
||||
if (ret == -1 || ret == 0) goto out;
|
||||
|
||||
ret = -1;
|
||||
|
||||
// Power is on, now check if the HCI interface is up
|
||||
hci_sock = create_hci_sock();
|
||||
if (hci_sock < 0) goto out;
|
||||
|
||||
dev_info.dev_id = HCI_DEV_ID;
|
||||
if (ioctl(hci_sock, HCIGETDEVINFO, (void *)&dev_info) < 0) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hci_test_bit(HCI_UP, &dev_info.flags);
|
||||
|
||||
out:
|
||||
if (hci_sock >= 0) close(hci_sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ba2str(const bdaddr_t *ba, char *str) {
|
||||
return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
|
||||
ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
|
||||
}
|
||||
|
||||
int str2ba(const char *str, bdaddr_t *ba) {
|
||||
int i;
|
||||
for (i = 5; i >= 0; i--) {
|
||||
ba->b[i] = (uint8_t) strtoul(str, &str, 16);
|
||||
str++;
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user