- HAL层(system/bluetooth/bluedroid/bluetooth.c,
function: bt_enable(), property_set("ctl.start", "hciattach"))
- |
- | 给电之后,启动注册在init.rc里面的hciattach daemon
- |
- bluez(external/bluetooth/bluez/tools/hciattach.c)
- |
- | 打开制定的tty设备,然后做一些通用的设置,并且通过ioctl发送两个命令
- | TIOCSETD和HCIUARTSETPROTO
- | 去将设备注册到hci设备中(h4和bcsp,走的是ldisc机制)
- |
- kernel hci层(net/bluetooth/hci_socket.c,hci_core.c)
- |
- | 收到HCIDEVUP指令通过hci_dev_open打开设备,调用hdev->open(hci_uart_open,
- | hci_uart_register_dev时候指定的方法),并且通过__hci_request调用hci_init_req
- | 去调用一系列的hci_send_cmd发送各种命令,主要是读各种配置以及设置一些基本参数
- | __hci_request设置了睡眠,它是一个阻塞函数
- |
- kernel hci层(net/bluetooth/hci_core.c),hci_send_cmd
- |
- | 调用tasklet_schedule(&hdev->cmd_task)唤起cmd_task,cmd_task在执行
- | HCIUARTSETPROTO命令时已经设置好了的
- |
- kernel hci层(net/bluetooth/hci_core.c),hci_cmd_task
- |
- | 调用hci_send_frame将命令发送给硬件。hci_send_frame见后面的数据发送流程
- | 数据收到后会通过中断调起数据接收流程,具体流程也见后面。然后进行一系列的处理
- | (hci_rx_task->hci_event_packet)最后调起hci_req_complete,用wake_up_interruptible
| 唤醒前面__hci_request设置的睡眠
一共有3个ioctl命令,TIOCSETD和HCIUARTSETPROTO在hciattach.c里面,通过open命令调用
drivers/tty/tty_io.c以及对应的ioctl,具体见下面描述。
HCIDEVUP在bluetooth.c里面,通过socket(AF_BLUETOOTH, SOCK_RAW,
BTPROTO_HCI)发出,BTPROTO_HCI对应的hci_socket.c的ioctl处理。af_bluetooth.c在初始化的时候就
注册了三种proto的socket:hci,l2cap和sco.
TIOCSETD处理流程
- tty core(drivers/tty/tty_io.c,function: tty_ioctl调用tiocsetd,传入的参数是hci对应的
discipline id,N_HCI)
- |
- tty ldisc(drivers/tty/tty_ldisc.c,tty_set_ldisc: 1)根据id找ops,ops是在子ldisc初始化时注册到
tty_ldisc.c里面的一个tty_ldisc_ops数组 2) alloc一个ldisc,将前面找到的op设给这个ldisc
3) 通过tty_ldisc_assign将这个ldisc设给tty结构体.
从此,以后对应的函数都是调用子ldisc里面的tty_ldisc_ops函数来处理)
- |
- hci uart(drivers/bluetooth/hci_ldisc.c)
HCIUARTSETPROTO处理流程
- tty core(drivers/tty/tty_io.c,function: tty_ioctl调用ld = tty_ldisc_ref_wait(tty);
ld->ops->ioctl())
- |
- |
- hci uart(drivers/bluetooth/hci_ldisc.c,通过init函数注册到tty_ldisc中的,
对应的id是N_HCI.函数hci_uart_tty_ioctl调用hci_uart_set_proto)
- |
- | 调用在h4_init或者bcsp_init里面注册的设备的open命令,具体调用哪个open
- | 取决于hciattach.c里面uart数组对应的定义。
- | open完了之后通过hci_uart_register_dev alloc一个hci_dev
- |
- hci core(net/bluetooth/hci_core.c,function:hci_register_dev,这里面做的事情比较多,初始化了
3个tasklet(发送,接收以及命令),注册hci设备对应的sysfs,以及注册了该hci设备对应的rfkill,到这一步,
底层的蓝牙虚拟设备hci0就可以通过hciconfig命令看到了
由上面可以看到,一个子uart模块在初始化的时候,应该干这么几件事:
- 1)通过tty_register_ldisc(id, &tty_ldisc_op)将ops写到tty_ldisc的数组里面,并且子ldisc要实现这么一个hci_uart_proto的数组
- 2)通过xxx_uart_register_proto(&hci_uart_proto)写到子ldisc的hci_uart_proto数组里面
一旦hci_register_dev完成,也就是hci层加进来以后,HAL层所有的操作都将通过hci-->proto-->ldisc-->tty这么一个流程。
阅读(7188) | 评论(0) | 转发(4) |