2、enableNative的分析
enable Native是真正的蓝牙使能的函数,蓝牙打开的一系列操作都是通过他来真正实现的。可以认为,这个函数蓝牙使能的主干,其余几个方面都可以认为是旁枝末节而已,因此,无论如何,我们必须了解到这个函数真正的精髓所在。
先来看jni层究竟是如何实现这个函数的:
static jint enableNative(JNIEnv *env, jobject object) {
#ifdef HAVE_BLUETOOTH
LOGV("%s", __FUNCTION__);
//可以看到其实很简单,就是调用bt_enable函数
return bt_enable();
#endif
return -1;
}
bt_enable是libbluedroid.so这个动态库中的一个函数,所以,很容易就可以找到对应的源码:system/bluetooth/bluedroid/bluetooth.c
int bt_enable() {
……
//这里是通过rfkill来设置蓝牙芯片的电压,也就是通常所说的上电
//这里是通过向对应的rfkill的state文件置1,各家的方案都有各家的做法,但实现的接口是统一的
if (set_bluetooth_power(1) < 0) goto out;
//启动hciattach service,这个是在init.rc中定义的service,在前面的文章中我已经有说明过。
//hciattach的作用是用来初始化蓝牙芯片,他包含了串口的波特率的初始化,fw的download等一系列的操作,各家的方案又会有所差异,所以,我就不详细分析了,大家知道这个是做些什么操作的即可
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
//这里其实有一个小的bug,注释是10s的尝试时间,事实上每次等待的时间是100ms,总共时间就已经到100s了,不过也无伤大雅了。
//这里就是通过ioctl去进行hcidev的up,我们可以理解只有hciattach把芯片全部初始化完成,这里才能够成功up,否则就会出错,我们就需要去不停的进行尝试。
//你肯定会有疑问,hciattach那边是如何控制这边的出错的啊?其实很简单,在hciattach初始化要结束的时候才会去创建hcidev,若是连hcidev都没有,up必然会出错了,呵呵,具体的细节下面再详细分析了
//hciattach对hcidev的影响见2.1
//hcidev up的详细分析见2.2
for (attempt = 1000; attempt > 0; attempt--) {
//创建socket,没什么好说的
hci_sock = create_hci_sock();
if (hci_sock < 0) goto out;
//通过ioctl来进行up
ret = ioctl(hci_sock, HCIDEVUP, HCI_DEV_ID);
LOGI("bt_enable: ret: %d, errno: %d", ret, errno);
if (!ret) {
break;
} else if (errno == EALREADY) {
LOGW("Bluetoothd already started, unexpectedly!");
break;
}
close(hci_sock);
usleep(100000); // 100 ms retry delay
}
if (attempt == 0) {
LOGE("%s: Timeout waiting for HCI device to come up, error- %d, ",