我们大家都知道,Android其实是基于linux之上进行运行的。在Android系统的运行之初,首先是kernel层的一系列的初始化。今天晓东就先和大家来简单分析一下在开机之后,kernel中和bluetooth的初始化相关的内容有哪些。
我们仍然还是才kernel/net/bluetooth下面的代码开始查看,搜索一下initcall相关的内容也就只有在af_bluetooth.c中看到了这样一句话:
subsys_initcall(bt_init);
毫无疑问,我们肯定要从这里开始看了,若是有同学要问晓东为什么会是这里,我就不给您详细解释了,若是您有打破砂锅问到底的精神,晓东推荐你去google或者百度一下这个函数,就会看到一堆讲解linux启动的文章,我想您一定会有所收获的。
废话不多说了,直接看代码了:
1、bt_init的实现。
static int __init bt_init(void) { int err; /* *这会是在kernel中打印的第一个和蓝牙相关的内容,这里的版本是2.16 */ BT_INFO("Core ver %s", VERSION); /* *新建两个目录,不深入去看了 *新建一个sys/kernel/debug/bluetooth *新建一个sys/class/bluetooth *这连个目录可以再adb shell的时间进去看到了 */ err = bt_sysfs_init(); /* *向协议族数组中加入PF_BLUETOOTH=31 */ err = sock_register(&bt_sock_family_ops); BT_INFO("HCI device and connection manager initialized"); //hci socket的初始化 //注册HCI的proto,还有PROTO_HCI对应的ops //然后注册了一个hci_notifier的监听,后面1.1会详细说明 err = hci_sock_init(); //l2cap相关的初始化,详细见1.2说明 err = l2cap_init(); //和L2CAP的注册流程是一样的,只是注册的是sco而已 err = sco_init(); …… }
1.1 hci_sock_init的实现
下面,我们来看一下hci_sock_init函数的实现:
int __init hci_sock_init(void) { int err; //注册HCI的proto,即加入到proto_list中去 //proto_list是一个全局的静态链表,无多大用途,仅供查询使用 err = proto_register(&hci_sk_proto, 0); //初始化BTPROTO_HCI对应的ops err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); //注册一个hci_notifier的监听吧 hci_register_notifier(&hci_sock_nblock); BT_INFO("HCI socket layer initialized"); return 0; …… }
这里的关键是调用了bt_sock_register和hci_register_notifier函数。下面,我们来着重分析一下这两个函数
1.1.1 bt_sock_register函数的实现
int bt_sock_register(int proto, const struct net_proto_family *ops) { int err = 0; /* *在目前的版本中,共有一下bt相关的proto定义 *#define BTPROTO_L2CAP 0 *#define BTPROTO_HCI 1 *#define BTPROTO_SCO 2 *#define BTPROTO_RFCOMM 3 *#define BTPROTO_BNEP 4 *#define BTPROTO_CMTP 5 *#define BTPROTO_HIDP 6 *#define BTPROTO_AVDTP 7 *需要注意的是,BT_MAX_PROTO的定义和这些proto的定义不是在一个地方 *所以若是想加入新的proto,一定要注意修改BT_MAX_PROTO的值 */ if (proto < 0 || proto >= BT_MAX_PROTO) return -EINVAL; /* * bt_proto_lock是一个全局的静态的读写锁 *主要用于保护bt_proto数组的读写 */ write_lock(&bt_proto_lock); //所有bt相关的proto,都是在一个bt_proto的数组中 //找到对应的初始化即可 if (bt_proto[proto]) err = -EEXIST; else bt_proto[proto] = ops; write_unlock(&bt_proto_lock); return err; }
1.1.2 hci_register_notifier的分析
代码很简答,就是注册了hci_notifier的callback为hci_sock_nblock
int hci_register_notifier(struct notifier_block *nb) { return atomic_notifier_chain_register(&hci_notifier, nb); }
1.2 l2cap_init的分析
l2cap相关的初始化,位于l2cap_sock.c中
int __init l2cap_init(void) { int err; //l2cap相关的初始化,见1.2.1 err = l2cap_init_sockets(); if (err < 0) return err; //hci的proto //0--L2CAP //1—SCO //详见1.2.2 err = hci_register_proto(&l2cap_hci_proto); if (err < 0) { BT_ERR("L2CAP protocol registration failed"); bt_sock_unregister(BTPROTO_L2CAP); goto error; } //就是建sys/kernel/debug/bluetooth/l2cap if (bt_debugfs) { l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, NULL, &l2cap_debugfs_fops); if (!l2cap_debugfs) BT_ERR("Failed to create L2CAP debug file"); } …… }
1.2.1 l2cap_init_sockets
这个函数和hci_sock_init的内容就差不多了
int __init l2cap_init_sockets(void) { int err; //把l2cap加入到proto_list中去 err = proto_register(&l2cap_proto, 0); if (err < 0) return err; //再加入BTPROTO_L2CAP到bt_proto中 err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); if (err < 0) goto error; …… }
1.2.2 hci_register_proto
我们知道l2cap和sco其实并不是和hci层平齐的,他们都是位于hci之上的,所以,这里会继续在hci之上初始化l2cap和sco相关的内容。
int hci_register_proto(struct hci_proto *hp) { int err = 0; BT_DBG("%p name %s id %d", hp, hp->name, hp->id); //其实只有0和1,分别为L2CAP和SCO if (hp->id >= HCI_MAX_PROTO) return -EINVAL; //hci_task_lock是一个全局锁 write_lock_bh(&hci_task_lock); //hci_proto对应的id初始化 //这也是一个全局变量 if (!hci_proto[hp->id]) hci_proto[hp->id] = hp; else err = -EEXIST; write_unlock_bh(&hci_task_lock); return err; }
至此bt_init函数的分析就结束了,我们来总结一下,他主要做了以下几个工作:
1) 新建了几个debug的文件夹/文件:
sys/kernel/debug/bluetooth
sys/class/bluetooth
sys/kernel/debug/bluetooth/l2cap
sys/kernel/debug/bluetooth/sco
2) 向协议族数组中加入了PF_BLUETOOTH=31的协议
3) 向proto_list中加入了HCI,L2CAP,SCO
4) 向bt_proto数组中加入了BTPROTO_L2CAP,BTPROTO_HCI, BTPROTO_SCO
5) 向hci_proto数组中加入了L2CAP和SCO
6) 向hci_notifier注册了一个callback:hci_sock_nblock