以hci_ldisc.c为例,梳理内核中线路规程的注册流程
我们的N_HCI的注册过程如下:
bluetooth/hci_ldisc.c
module_init(hci_uart_init);
tty_register_ldisc(N_HCI, &hci_uart_ldisc) //hci_uart_ldisc包含N_HCI线路规程的一系列回调
drivers/tty/tty_ldisc.c
int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
tty_ldiscs[disc] = new_ldisc;  //将线路规程操作,保存到全局数组

new_ldisc->num = disc;
     new_ldisc->refcount = 0;

这样,用户就可以通过调用IOCTL的TIOSETD命令,来设置该规程
以hciattach为例:
hciattach进程的启动
以a20 4.1 realtek为例:
init.sun6i.rc:
# 3. realtek rtl8723as bt hciattach
service hciattach /system/bin/logwrapper /system/bin/hciattach -n -s 115200 /dev/ttyS1 rtk_h5 1500000
   user root
   group bluetooth net_bt_admin
   disabled
   oneshot
hciattach的代码位于:
external/bluetooth/bluez/tools/hciattach.c
external/bluetooth/bluez/tools/hciattach_rtk.c
hciattach.c
main
首先,解析参数,这个参数决定了用那一套uart接口。
{ "rtk_h5",     0x0000, 0x0000, HCI_UART_3WIRE, 115200, 1500000, FLOW_CTL,0, NULL, realtek_init, realtek_post},
n = init_uart(dev, u, send_break, raw); // 初始化uart dev=/dev/ttyS1 u为rtk_h5这套参数,
int fd = open(dev, O_RDWR | O_NOCTTY); //打开串口
u->init(fd, u, &ti);//调用回调初始化函数
rtk_init_h5(fd, ti); //做下载firmware的准备工作
rtk_config(fd, proto, speed, ti); //下载蓝牙firmware
set_speed(fd, &ti, u->init_speed);//设置初始波特率 115200
int i = N_HCI;
ioctl(fd, TIOCSETD, &i);//设置tty为N_HCI线路规程
ioctl(fd, HCIUARTSETPROTO, u->proto); //设置为HCI_UART_3WIRE
u->post(fd, u, &ti);//调用回调函数post,//设置高速模式
内核对TIOSETD的处理
在drivers/tty/tty_io.c种,处理TIOSETD
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) //tty设备的IOCTL回调处理函数
return tiocsetd(tty, p);  //设置线路规程
return tty_set_ldisc(tty, ldisc); //tty = N_HCI
drivers/tty/tty_ldisc.c
int tty_set_ldisc(struct tty_struct *tty, int ldisc)
struct tty_ldisc *new_ldisc = tty_ldisc_get(ldisc); //讲N_HCI转换为tty_ldisc的数据结构,其中包含ops回调,其实就是通过N_HCI作为索引在一个tty_ldisc数组中取出相应的item,这个tty_ldisc数组,就是hci_uart_ldisc,上面讲了,是通过通过int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)注册。
work = tty_ldisc_halt(tty);//终止原来线路规
tty_ldisc_assign(tty, new_ldisc);
tty_set_termios_ldisc(tty, ldisc); //设置新的线路规程
tty_ldisc_open(tty, new_ldisc); //调用hci_uart_ldisc的open回调,做一些清空buffer等初始化工作
tty->ops->set_ldisc(tty); //调用hci_uart_ldisc设置到tty_struct中去
对HCIUARTSETPROTO的处理
现在,刚刚的串口设备已经使用了新的线路规程,它将处理HCIUARTSETPROTO命令,但是在/drivers/tty/tty_io.c中,如果发现该CMD处理不了,就调用对应线路规程的ops中的ioctl来处理:
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
ld->ops->ioctl(tty, file, cmd, arg); //调用到hci_uart_ldisc中的hci_uart_tty_ioctl函数
hci_ldisc.c
hci_uart_tty_ioctl
hci_uart_set_proto(hu, arg);//arg = HCI_UART_3WIRE
struct hci_uart_proto *p = hci_uart_get_proto(id);//获取hci协议,里面包含一系列open等回调。
其实这里,就是根据id作为索引,获取hci_uart_proto数组的一个item,这些item,通过hci_uart_register_proto来注册填充。
p->open(hu); //调用对应open接口,将对应的proto回调保存到hci_uart结构中
hci_uart_register_dev(hu);//注册该hci设备
struct hci_dev *hdev; 构造一个hci_dev结构,填入hci_uart相关回调。
hci_register_dev(hdev);//注册设备
//首先遍历当前所有hci设备,这些设备都保存到一个全局数组hci_dev_list,获取hci设备的后缀id
sprintf(hdev->name, "hci%d", id);//保存名字
hci_register_sysfs(hdev);//在sys文件系统中,注册一个设备节点。
hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,

RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, hdev);

rfkill_register(hdev->rfkill);//注册rfkill节点
到目前为止,hci0已经注册好了,android层的bluez可以通过AF_BLUETOOTH访问,获取HCI信息了。

内核中line discipline的注册流程以及BT hciattach进程的启动相关推荐

  1. Spring中Bean定义的注册流程

    目录 一.前言 二.Bean定义的注册流程 1.注册流程 2.SpringApplication组件 2.1.run()核心逻辑

  2. 五、linux总线中设备和驱动注册流程详解

    一.注册流程图( 建议大家先看这张图3分钟. ) 由上图可以看出,linux中,有各种总线(bus),其中的平台总线(platform)是我们字符设备和驱动注册的地方.通过platform_devic ...

  3. linux内核定时器死机,浅析linux内核中timer定时器的生成和sofirq软中断调用流程

    浅析linux内核中timer定时器的生成和sofirq软中断调用流程 mod_timer添加的定时器timer在内核的软中断中发生调用,__run_timers会spin_lock_irq(& ...

  4. linux加密框架 crypto 通用算法注册接口__crypto_register_alg注册流程

    函数介绍 __crypto_register_alg函数实现向加密框架注册算法(包括静态算法和动态算法)的功能,输入参数为算法说明alg,注册成功时返回算法注册用的算法幼虫larval,注册失败时返回 ...

  5. 你真的懂Linux内核中的阻塞和异步通知机制吗?(花了五天整理,墙裂推荐!)

    工科生一枚,热衷于底层技术开发,有强烈的好奇心,感兴趣内容包括单片机,嵌入式Linux,Uboot等,欢迎学习交流! 爱好跑步,打篮球,睡觉. 欢迎加我QQ1500836631(备注CSDN),一起学 ...

  6. 5GC注册流程(详解)

    首先附上三篇好文,如果这三篇全部看完并记忆,那么本文可略过 5GC注册过程(这个相当于23502协议中注册流程的原文翻译) 5G中携带SUCI的初始注册流程(这个是博主自理的初始注册,流程简单明了) ...

  7. Android系统启动流程--init进程的启动流程

    这可能是个系列文章,用来总结和梳理Android系统的启动过程,以加深对Android系统相对全面的感知和理解(基于Android11).  1.启动电源,设备上电 引导芯片代码从预定义的地方(固化在 ...

  8. 一文讲解Linux内核中根文件系统挂载流程

    根文件系统的概念 根文件系统是控制权从linux内核转移到用户空间的一个桥梁.linux内核就类似于一个黑匣子,只向用户提供各种功能的接口,但是功能的具体实现不可见,用户程序通过对这些功能接口的不同整 ...

  9. 内核中的UDP socket流程(2)——API “sys_socket”

    内核中的UDP socket流程(2)--API "sys_socket" 作者:gfree.wind@gmail.com 原文:http://blog.chinaunix.net ...

最新文章

  1. AI 技术升级,这一新方法遏制在线语言骚扰
  2. 12JavaScript中的内置对象
  3. c中gets函数使用可能导致缓冲区溢出
  4. ThreadLocal的设计与实现
  5. redis java 性能_Redis 性能优化
  6. C 冒泡排序及其非常非常非常简单的优化
  7. IplImage* cvmat* mat 释放
  8. java 快速io_java 最快的input (ACM) Java高效IO
  9. 后台管理系统、商品管理、商品发布、商品回收、订单管理、退款管理、运营管理、商城设置、导航分类、营销管理、优惠券套餐、数据统计、活跃用户、数据埋点、财务管理、对账单、财务数据、账户资产、电商后台
  10. jms 教程_JMS教程–什么是JMS
  11. cmd窗口命令行上移下移_微软新版命令行界面:Windows Termina...
  12. c++ 编译代码时Link失败,无法关闭目标文件
  13. An error occurred.Faithfully yours, nginx
  14. java使用java.lang.Math类,生成100个0-99之间的随机整数,并找出它们中间的最大值和最小值,并统计大于50的整数的个数。打印3次运行结果,看是否相同。
  15. Word中如何快速删除页眉下的横线?教你一招,轻松解决!
  16. face++实现人脸识别及人脸相似度对比
  17. java qt gui_工控编程,Qt 学习之路
  18. 生活 RH阴性血 AB型
  19. 北京积分落户积分计算方法
  20. 多级放大电路超详细分析

热门文章

  1. Bypass 360主机卫士SQL注入防御(附tamper脚本)
  2. python3安装遇到 zipimport.ZipImportError: can't decompress data; zlib not available
  3. 从小白程序员到大厂高级技术专家我看过哪些书籍?
  4. 华云数据受邀出席2021年江苏省网络安全发展大会
  5. 站长号平台关于必须绑定手机才能发帖的相关说明
  6. android 翻转imageview,如何在Android中翻转ImageView?
  7. java se 6是什么意思_Java SE 6中与JRE 1.6与JDK 1.6 - 什么做这些是什么意思?
  8. Android方向传感器实践——自己动手做指南针
  9. win10可以联网,但显示无法连接到Internet
  10. 2021湖湘杯 Hideit Writeup