zoukankan      html  css  js  c++  java
  • linux蓝牙驱动代码阅读笔记

    linux蓝牙驱动代码阅读笔记

    转载时请注明出处和作者联系方式
    作者联系方式:李先静 <xianjimli at hotmail dot com>

    昨天看了一下介绍蓝牙协议文档,今天索性对照看了看kernel里的代码(bluez),这里记点笔记,还是继承了老毛病,只关注整体流程而忽略细节,先了解个大概,等真正需要时再仔细分析。

    net/hci_core.c

    HCI在主机端的驱动主要是为上层提供一个统一的接口,让上层协议不依赖于具体硬件的实现。HCI在硬件中的固件与HCI在主机端的驱动通信方式有多种,比如像UART、USB和PC Card等等。hci_core.c相当于一个框架,用于把各种具体通信方式胶合起来,并提供一些公共函数的实现。

    hci_cmd_task是负责发送CMD的任务,它从hdev->cmd_q队列中取CMD,然后调用hci_send_frame把CMD发送出去,hci_send_frame又会调用实际的HCI驱动的send函数发送数据。

    hci_rx_task是负责接收数据的任务,它从hdev->rx_q队列中取数据,然后根据数据的类型调用上层函数处理。数据包有三种类型:
    1. HCI_EVENT_PKT: 用于处理一些通信事件,比如连接建立,连接断开,认证和加密等事件,这些事件控制协议状态的改变。
    2. HCI_ACLDATA_PKT: 异步非连接的数据包,通过hci_acldata_packet提交给上层的L2CAP协议处理(hci_proto[HCI_PROTO_L2CAP])。
    3. HCI_SCODATA_PKT: 同步面向连接的数据包,通过hci_scodata_packet提供给上层的SCO协议处理(hci_proto[HCI_PROTO_SCO])。

    hci_tx_task 是负责发送数据的任务,发送所有connection中的ACL和SCO数据,以及hdev->raw_q中的数据包。

    HCI为上层提供的接口主要有:
    1. hci_send_sco:发送SCO数据包,把要发送的数据包放入connection的发送队列中,然后调度发送任务去发送。
    2. hci_send_acl:发送ACL数据包,把要发送的数据包放入connection的发送队列中,然后调度发送任务去发送。
    3. hci_send_cmd:发送命令数据,把要发送的数据包放入hdev->cmd_q队列中,然后调度命令发送任务去发送。
    4. hci_register_proto/hci_unregister_proto:注册/注销上层协议,HCI会把接收到的数据转发给这些上层协议。
    5. hci_register_dev/hci_unregister_dev: 注册/注销设备,HCI会把要发送的数据通过这些设备发送出去。
    6. 其它一些公共函数。

    net/hci_conn.c
    提供了一些连接管理,论证和加密的函数。

    net/hci_event.c
    事件处理函数,负责状态机的维护,这些事件通常会使连接从一个状态转换另一个状态。
    1. hci_si_event:用于发送事件。
    2. hci_event_packet:用于处理底层上报的事件,从hci_rx_task处调用过来。

    net/hci_sock.c
    给上层提供一个socket接口,应用程序可以通过socket的方式来访问HCI。
    1. hci_sock_init:中注册了BTPROTO_HCI类型family。
    2. hci_sock_create:创建sock的函数,它的sock的ops指向hci_sock_ops。
    3. hci_sock_setsockopt/hci_sock_getsockopt:设置/获取sock的一些选项。
    4. hci_sock_sendmsg:发送消息,根据消息的类型把消息放到适当的队列中。
    5. hci_sock_recvmsg:接收消息,从接收队列中取消息。
    6. hci_sock_recvmsg:ioctl函数。

    net/hci_sysfs.c
    提供一些sysfs文件系统接口。

    net/l2cap.c
    L2CAP是HCI之上的协议,提供诸如QoS,分组,多路复用,分段和组装之类的功能。

    通过bt_sock_register为上层提供一个sock接口:
    1. l2cap_sock_create:创建sock的函数,它的sock的ops指向l2cap_sock_ops。
    2. l2cap_sock_setsockopt/l2cap_sock_getsockopt设置/获取sock的一些选项。
    3. l2cap_sock_sendmsg:发送消息,通过HCI提供hci_send_acl函数把消息传递给下层的设备。
    4. bt_sock_recvmsg:接收消息,从接收队列中取消息。

    通过hci_register_proto向其下的HCI注册协议:
    1. l2cap_connect_ind:处理连接请求。
    2. l2cap_connect_cfm:确认连接。
    3. l2cap_disconn:处理断开请求。
    4. l2cap_auth_cfm:认证确认。
    5. l2cap_encrypt_cfm:加密确认。
    6. l2cap_recv_acldata:处理来自HCI的数据。

    net/sco.c
    SCO也是运行在HCI之上的协议,它是面向连接的可靠的传输方式,主要用于声音数据传输。

    通过bt_sock_register为上层提供一个sock接口:
    1. sco_sock_create:创建sock的函数,它的sock的ops指向sco_sock_ops。
    2. sco_sock_setsockopt/sco_sock_getsockopt设置/获取sock的一些选项。
    3. sco_sock_sendmsg:发送消息,通过HCI提供sco_send_frame函数把消息传递给下层的设备。
    4. bt_sock_recvmsg:接收消息,从接收队列中取消息。

    通过hci_register_proto向其下的HCI注册协议:
    1. sco_connect_ind:处理连接请求。
    2. sco_connect_cfm:确认连接。
    3. sco_disconn_ind:处理断开请求。
    4. sco_recv_scodata: 处理来自HCI数据。

    rfcomm/*
    rfcomm是基于l2CAP之上的协议,它在蓝牙协议之上封装传统的RS232串口。

    drivers/bluetooth
    前面我们介绍的都是HCI及其上层的协议,HCI下层的实现就是HCI驱动程序,这些驱动程序用于与蓝牙硬件通信,通信的方式常见的有USB,UART和PC card等几种。这里我们看看USB的方式:

    drivers/bluetooth/hci_usb.c
    1. hci_usb_probe: 调用hci_register_dev向前面说的hci_core注册HCI设备。
    2. hci_usb_send_frame:用于提供给HCI去发送数据包。它把数据包放到传输队列__transmit_q(husb, bt_cb(skb)->pkt_type)之中,然后调用hci_usb_tx_process去传输数据。
    3. hci_usb_tx_process:根据数据的类型去调用hci_usb_send_ctrl /hci_usb_send_isoc /hci_usb_send_bulk把数据通过USB发送给硬件。

    ~~end~~
     
  • 相关阅读:
    Codeforces 787D. Legacy 线段树优化建图+最短路
    Codeforces 1051E. Vasya and Big Integers
    BZOJ3261 最大异或和
    BZOJ3531 SDOI2014 旅行
    洛谷P2468 SDOI 2010 粟粟的书架
    2018 ICPC 焦作网络赛 E.Jiu Yuan Wants to Eat
    HDU6280 From Tree to Graph
    HDU5985 Lucky Coins 概率dp
    (HDU)1334 -- Perfect Cubes (完美立方)
    (HDU)1330 -- Deck (覆盖物)
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167663.html
Copyright © 2011-2022 走看看