btmon获取hci数据流程
btmon获取hci数据流程
背景
最近在看蓝牙相关的驱动代码,追到hci接收数据处理函数hci_rx_work()
(net/bluetooth/hci_core.c
),
瞄到下面一段代码:
...
while ((skb = skb_dequeue(&hdev->rx_q))) {
/* Send copy to monitor */
hci_send_to_monitor(hdev, skb);
...
}
在hci发送数据的处理函数hci_send_frame()
中也有类似的代码片段:
...
/* Time stamp */
__net_timestamp(skb);
/* Send copy to monitor */
hci_send_to_monitor(hdev, skb);
if (atomic_read(&hdev->promisc)) {
/* Send copy to the sockets */
hci_send_to_sock(hdev, skb);
}
...
突然有了个联想:这个hci_send_to_monitor()
莫不是给上层的btmon
准备的?
继续追代码,hci_send_to_monitor()
函数具体实现如下:
...
/* Put header before the data */
hdr = skb_push(skb_copy, HCI_MON_HDR_SIZE);
hdr->opcode = opcode;
hdr->index = cpu_to_le16(hdev->id);
hdr->len = cpu_to_le16(skb->len);
hci_send_to_channel(HCI_CHANNEL_MONITOR, skb_copy,
HCI_SOCK_TRUSTED, NULL);
...
数据最后是发给HCI_CHANNEL_MONITOR
通道的,
带着好奇,去翻了下bluez的源码,在monitor
目录,即btmon的代码里,control_tracing()
函数中就打开了HCI_CHANNEL_MONITOR
通道:
...
if (open_channel(HCI_CHANNEL_MONITOR) < 0) {
if (!hcidump_fallback)
return -1;
if (hcidump_tracing() < 0)
return -1;
return 0;
}
...
至此,btmon
整个获取hci数据的流程就通了,以接收数据为例:
- 核内(蓝牙驱动):
具体的HCI接口(H4,usb,sdio等)驱动获取数据 ->hci_recv_frame() -- 所有的HCI接口的驱动基本上都会调用这里来,比如H4,usb,sdio都会 -> hci_rx_work() -- 接收工作队列 -> hci_send_to_monitor() -- Send frame to monitor socket -> hci_send_to_channel(HCI_CHANNEL_MONITOR, ...)
- 核外(bluez btmon):
main() -> control_tracing() -> open_channel(HCI_CHANNEL_MONITOR) -- 打开 HCI_CHANNEL_MONITOR 通道 -> open_socket -- 打开socket -> data_callback() -- 数据处理回调
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 DD'Notes!
评论