源代码位于 system/bluetooth/bluedroid/* ,编译完会生成库 libbluedroid.so.
1. init.rc 中的 “service btpwr /wl1271bt_enable /dev/ttyO1”
点击 Setting 里的 bluetooth,打开 bluetooth 后,系统会调用 bt_enable().
a. bt_enable().
int bt_enable() {
LOGV(__FUNCTION__);
int ret = -1;
int hci_sock = -1;
int attempt;
if (set_bluetooth_power(1) < 0) goto out; //这里会调用内核控制BT_EN,GPIO
LOGI("Starting hciattach daemon");
if (property_set("ctl.start", "hciattach") < 0) { //通知 hciattach start
LOGE("Failed to start hciattach");
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
//重试1000次,等待wl1271 BT模块loadfirmware,再做出响应。
for (attempt = 1000; attempt > 0; attempt--) {
hci_sock = create_hci_sock(); //这里用到了socket,看来得看看socket了
if (hci_sock < 0) goto out;
if (!ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID)) { //打开HCI, HCI DEV UP
break;
}
close(hci_sock);
usleep(10000); // 10 ms retry delay
}
if (attempt == 0) {
LOGE("%s: Timeout waiting for HCI device to come up", __FUNCTION__);
goto out;
}
LOGI("Starting bluetoothd deamon");
if (property_set("ctl.start", "bluetoothd") < 0) { //通知 bluetoothd start
LOGE("Failed to start bluetoothd");
goto out;
}
sleep(HCID_START_DELAY_SEC);
ret = 0;
out:
if (hci_sock >= 0) close(hci_sock);
return ret;
}
b. set_bluetooth_power():
static int set_bluetooth_power(int on) {
int sz;
int fd = -1;
int ret = -1;
const char buffer = (on ? '1' : '0');
if (rfkill_id == -1) {
if (init_rfkill()) goto out;
}
fd = open(rfkill_state_path, O_WRONLY); //打开 rfkill_state_path
if (fd < 0) {
LOGE("open(%s) for write failed: %s (%d)", rfkill_state_path,
strerror(errno), errno);
goto out;
}
sz = write(fd, &buffer, 1); //写入 rfkill 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;
}
c. create_hci_sock():
static inline int create_hci_sock() {
int sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); //建立一个socket。
if (sk < 0) {
LOGE("Failed to create bluetooth hci socket: %s (%d)",
strerror(errno), errno);
}
return sk;
}
还有其他一些函数:
d. bt_disable(),这个函数应该是蓝牙睡眠的时候调用的。
int bt_disable() {
LOGV(__FUNCTION__);
int ret = -1;
int hci_sock = -1;
LOGI("Stopping bluetoothd deamon");
if (property_set("ctl.stop", "bluetoothd") < 0) { //通知 bluetoothd stop
LOGE("Error stopping bluetoothd");
goto out;
}
usleep(HCID_STOP_DELAY_USEC);
hci_sock = create_hci_sock(); //建立 hci socket
if (hci_sock < 0) goto out;
ioctl(hci_sock, HCIDEVDOWN, HCI_DEV_ID); //关闭HCI, HCI DEV DOWN
LOGI("Stopping hciattach deamon");
if (property_set("ctl.stop", "hciattach") < 0) {
LOGE("Error stopping hciattach");
goto out;
}
if (set_bluetooth_power(0) < 0) { //关闭蓝牙供电,BT_EN
goto out;
}
ret = 0;
out:
if (hci_sock >= 0) close(hci_sock);
return ret;
}
e. bt_is_enabled():
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(); //check 蓝牙的供电
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; //HCI GET DEV INFO, 获取HCI信息
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;
}
f. check_bluetooth_power()
static int check_bluetooth_power() {
int sz;
int fd = -1;
int ret = -1;
char buffer;
if (rfkill_id == -1) {
if (init_rfkill()) goto out; //init_rfkill
}
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;
}
g. init_rfkill():
static int init_rfkill() {
char path[64];
char buf[16];
int fd;
int sz;
int id;
for (id = 0; ; 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;
break;
}
}
asprintf(&rfkill_state_path, "/sys/class/rfkill/rfkill%d/state", rfkill_id);
return 0;
}
hciattach /system/bin/hciattach -n /dev/ttyO1 texas 3000000