kernel中bluetooth的初始化

2024-04-16 07:32
文章标签 初始化 bluetooth kernel

本文主要是介绍kernel中bluetooth的初始化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们大家都知道,Android其实是基于linux之上进行运行的。在Android系统的运行之初,首先是kernel层的一系列的初始化。今天晓东就先和大家来简单分析一下在开机之后,kernel中和bluetooth的初始化相关的内容有哪些。

         我们仍然还是才kernel/net/bluetooth下面的代码开始查看,搜索一下initcall相关的内容也就只有在af_bluetooth.c中看到了这样一句话:

         subsys_initcall(bt_init);

         毫无疑问,我们肯定要从这里开始看了,若是有同学要问晓东为什么会是这里,我就不给您详细解释了,若是您有打破砂锅问到底的精神,晓东推荐你去google或者百度一下这个函数,就会看到一堆讲解linux启动的文章,我想您一定会有所收获的。

         废话不多说了,直接看代码了:

1bt_init的实现。

[cpp]  view plain copy
  1. static int __init bt_init(void)  
  2. {  
  3.     int err;  
  4. /* 
  5. *这会是在kernel中打印的第一个和蓝牙相关的内容,这里的版本是2.16 
  6. */  
  7.     BT_INFO("Core ver %s", VERSION);      
  8. /* 
  9. *新建两个目录,不深入去看了 
  10. *新建一个sys/kernel/debug/bluetooth 
  11. *新建一个sys/class/bluetooth 
  12. *这连个目录可以再adb shell的时间进去看到了 
  13. */  
  14.     err = bt_sysfs_init();  
  15.     /* 
  16.     *向协议族数组中加入PF_BLUETOOTH=31 
  17.     */  
  18.     err = sock_register(&bt_sock_family_ops);  
  19.     BT_INFO("HCI device and connection manager initialized");  
  20.     //hci socket的初始化  
  21.     //注册HCI的proto,还有PROTO_HCI对应的ops  
  22.     //然后注册了一个hci_notifier的监听,后面1.1会详细说明  
  23.     err = hci_sock_init();  
  24.     //l2cap相关的初始化,详细见1.2说明  
  25.     err = l2cap_init();  
  26.     //和L2CAP的注册流程是一样的,只是注册的是sco而已  
  27.     err = sco_init();  
  28. ……  
  29. }  

1.1 hci_sock_init的实现

下面,我们来看一下hci_sock_init函数的实现:

[cpp]  view plain copy
  1. int __init hci_sock_init(void)  
  2. {  
  3.     int err;  
  4. //注册HCI的proto,即加入到proto_list中去  
  5. //proto_list是一个全局的静态链表,无多大用途,仅供查询使用  
  6.     err = proto_register(&hci_sk_proto, 0);  
  7.     //初始化BTPROTO_HCI对应的ops  
  8.     err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);  
  9.     //注册一个hci_notifier的监听吧  
  10.     hci_register_notifier(&hci_sock_nblock);  
  11.     BT_INFO("HCI socket layer initialized");  
  12.     return 0;  
  13. ……  
  14. }  

这里的关键是调用了bt_sock_registerhci_register_notifier函数。下面,我们来着重分析一下这两个函数

1.1.1 bt_sock_register函数的实现

[cpp]  view plain copy
  1. int bt_sock_register(int proto, const struct net_proto_family *ops)  
  2. {  
  3.     int err = 0;  
  4. /* 
  5. *在目前的版本中,共有一下bt相关的proto定义 
  6. *#define BTPROTO_L2CAP  0 
  7. *#define BTPROTO_HCI    1 
  8. *#define BTPROTO_SCO    2 
  9. *#define BTPROTO_RFCOMM 3 
  10. *#define BTPROTO_BNEP   4 
  11. *#define BTPROTO_CMTP   5 
  12. *#define BTPROTO_HIDP   6 
  13. *#define BTPROTO_AVDTP  7 
  14. *需要注意的是,BT_MAX_PROTO的定义和这些proto的定义不是在一个地方 
  15. *所以若是想加入新的proto,一定要注意修改BT_MAX_PROTO的值 
  16. */  
  17.     if (proto < 0 || proto >= BT_MAX_PROTO)  
  18.         return -EINVAL;  
  19. /* 
  20. * bt_proto_lock是一个全局的静态的读写锁 
  21. *主要用于保护bt_proto数组的读写 
  22. */  
  23.     write_lock(&bt_proto_lock);  
  24.     //所有bt相关的proto,都是在一个bt_proto的数组中  
  25.     //找到对应的初始化即可  
  26.     if (bt_proto[proto])  
  27.         err = -EEXIST;  
  28.     else  
  29.         bt_proto[proto] = ops;  
  30.     write_unlock(&bt_proto_lock);  
  31.     return err;  
  32. }  

1.1.2 hci_register_notifier的分析

代码很简答,就是注册了hci_notifiercallbackhci_sock_nblock

[cpp]  view plain copy
  1. int hci_register_notifier(struct notifier_block *nb)  
  2. {  
  3.     return atomic_notifier_chain_register(&hci_notifier, nb);  
  4. }  

1.2 l2cap_init的分析

l2cap相关的初始化,位于l2cap_sock.c

[cpp]  view plain copy
  1. int __init l2cap_init(void)  
  2. {  
  3.     int err;  
  4.     //l2cap相关的初始化,见1.2.1  
  5.     err = l2cap_init_sockets();  
  6.     if (err < 0)  
  7.         return err;  
  8.     //hci的proto  
  9.     //0--L2CAP  
  10.     //1—SCO  
  11. //详见1.2.2  
  12.     err = hci_register_proto(&l2cap_hci_proto);  
  13.     if (err < 0) {  
  14.         BT_ERR("L2CAP protocol registration failed");  
  15.         bt_sock_unregister(BTPROTO_L2CAP);  
  16.         goto error;  
  17.     }  
  18.     //就是建sys/kernel/debug/bluetooth/l2cap  
  19.     if (bt_debugfs) {  
  20.         l2cap_debugfs = debugfs_create_file("l2cap", 0444,  
  21.                     bt_debugfs, NULL, &l2cap_debugfs_fops);  
  22.         if (!l2cap_debugfs)  
  23.             BT_ERR("Failed to create L2CAP debug file");  
  24.     }  
  25. ……  
  26. }  

1.2.1 l2cap_init_sockets

这个函数和hci_sock_init的内容就差不多了

[cpp]  view plain copy
  1. int __init l2cap_init_sockets(void)  
  2. {  
  3.     int err;  
  4.     //把l2cap加入到proto_list中去  
  5.     err = proto_register(&l2cap_proto, 0);  
  6.     if (err < 0)  
  7.         return err;  
  8.     //再加入BTPROTO_L2CAP到bt_proto中  
  9.     err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);  
  10.     if (err < 0)  
  11.         goto error;  
  12. ……  
  13. }  

1.2.2 hci_register_proto

我们知道l2capsco其实并不是和hci层平齐的,他们都是位于hci之上的,所以,这里会继续在hci之上初始化l2capsco相关的内容。

[cpp]  view plain copy
  1. int hci_register_proto(struct hci_proto *hp)  
  2. {  
  3.     int err = 0;  
  4.     BT_DBG("%p name %s id %d", hp, hp->name, hp->id);  
  5.     //其实只有0和1,分别为L2CAP和SCO  
  6.     if (hp->id >= HCI_MAX_PROTO)  
  7.         return -EINVAL;  
  8. //hci_task_lock是一个全局锁  
  9.     write_lock_bh(&hci_task_lock);  
  10.     //hci_proto对应的id初始化  
  11.     //这也是一个全局变量  
  12.     if (!hci_proto[hp->id])  
  13.         hci_proto[hp->id] = hp;  
  14.     else  
  15.         err = -EEXIST;  
  16.     write_unlock_bh(&hci_task_lock);  
  17.     return err;  
  18. }  

至此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_L2CAPBTPROTO_HCI, BTPROTO_SCO

5)  向hci_proto数组中加入了L2CAPSCO

6)  向hci_notifier注册了一个callbackhci_sock_nblock

 

这篇关于kernel中bluetooth的初始化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/908161

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给

笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel

kernel起始与ENTRY(stext),和uboot一样,都是从汇编阶段开始的,因为对于kernel而言,还没进行栈的维护,所以无法使用c语言。_HEAD定义了后面代码属于段名为.head .text的段。         内核起始部分代码被解压代码调用,前面关于uboot的文章中有提到过(eg:zImage)。uboot启动是无条件的,只要代码的位置对,上电就工作,kern

欧拉系统 kernel 升级、降级

系统版本  cat  /etc/os-release  NAME="openEuler"VERSION="22.03 (LTS-SP1)"ID="openEuler"VERSION_ID="22.03"PRETTY_NAME="openEuler 22.03 (LTS-SP1)"ANSI_COLOR="0;31" 系统初始 kernel 版本 5.10.0-136.12.0.

[Linux Kernel Block Layer第一篇] block layer架构设计

目录 1. single queue架构 2. multi-queue架构(blk-mq)  3. 问题 随着SSD快速存储设备的发展,内核社区越发发现,存储的性能瓶颈从硬件存储设备转移到了内核block layer,主要因为当时的内核block layer是single hw queue的架构,导致cpu锁竞争问题严重,本文先提纲挈领的介绍内核block layer的架构演进,然

Kernel 中MakeFile 使用if条件编译

有时需要通过if  else来选择编译哪个驱动,单纯的obj-$(CONFIG_)就不是很方便,下面提供两种参考案例: 案例一: 来源:drivers/char/tpm/Makefileifdef CONFIG_ACPItpm-y += tpm_eventlog.o tpm_acpi.oelseifdef CONFIG_TCG_IBMVTPMtpm-y += tpm_eventlog.o

Web Bluetooth 与点对点连接

前言 需求需要实现手持终端设备与 web 网页的点对点数据传输,不希望有服务器参与,想到了 web 的 USB 与 Bluetooth API,对 Web Bluetooth API 进行了研究。 蓝牙 GATT 基础知识 GATT(通用属性配置文件,蓝牙低功耗(BLE)中定义的一种规范)定义了如何在蓝牙低功耗设备之间进行数据的传输和交互。它规定了蓝牙设备之间的数据格式、通信协议以及数据的组

@postconstruct初始化的操作

从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解(Annotion);@PostConstruct和@PreDestroy。这两个注解被用来修饰一个非静态的void()方法 。写法有如下两种方式: @PostConstruct Public void someMethod() {}

spring和tomcat初始化的类和注解

1.InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法。 spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用 实