Bluetooth HCI Event的处理

作者:Sam(甄峰) [email protected]

1.当Bluetooth USBdongle插入USB接口时,driver/bluetooth/hci_usb.c中probe程序被调用。probe会调用hci_register_dev()--〉tasklet_init(&hdev->rx_task,hci_rx_task, (unsigned long) hdev);
将hci_rx_task() 连上rx_task->func.

2.同样在Bluetooth USB dongle插入时,hdev->open =hci_usb_open; 当USBDongle被UP时,这个function被调用。它调用hci_usb_intr_rx_submit(),它注册URB完成处理程序,hci_usb_rx_complete。
当有URB出现时, hci_usb_rx_complete ->__recv_frame()->hci_recv_frame()->hci_sched_rx(hdev);->hci_sched_rx()->tasklet_schedule(&hdev->rx_task)
tasklet_schedule():
将这个tasklet放在tasklet_vec链表的头部,并唤醒后台线程ksoftirqd。当后台线程ksoftirqd运行调用__do_softirq时,会执行在中断向量表softirq_vec里中断号TASKLET_SOFTIRQ对应的tasklet_action函数,然后tasklet_action遍历tasklet_vec链表,调用每个tasklet的函数完成软中断操作。
也就是调用hci_rx_task()

也就是:当有URB时,会最终调用到hci_rx_task()

当包类型为 HCI Event时,则调用hci_event_packet()
在hci_event_packet()中,会判断是何种Event.并处理之。

下面以HCI_EV_DISCONN_COMPLETE为例子看Event如何被处理。这个Event表明连接断掉了。reason则表示断掉的原因。

HCI_EV_DISCONN_COMPLETEEvent使用处理程序hci_disconn_complete_evt来处理,下面详细讲解:

1.hci_dev_lock():使用自旋锁得到资源。

2.hci_conn_hash_lookup_handle():从连接队列中找出对应连接。注:当有ACL或SOC连接时,这个连接就会被加入连接链表。

3.这个连接的state改为BT_CLOSED。

4.hci_proto_disconn_ind():调用全局变量hci_proto中的disconn_ind()。

注:在L2cap protocolinsmod时,hci_register_proto()被调用。全局变量hci_proto则被赋值。disconn_ind=l2cap_disconn_ind;

所以当HCI层得到Disconnect时,会通知l2cap层做删除channel等工作。

且因为state改为BT_CLOSED. 所以在l2cap层调用poll(最终调用bt_sock_poll)时会发现POLLHUP被置位。

这样l2cap应用程序就能够知道连接已经断开了。


你可能感兴趣的:(Bluetooth HCI Event的处理)