For more information about the HCI specification, see <bluetooth HCI Introduction >
First, we need to understand that the host part of HCI is implemented on Linux.
1. Related Data Structure 1.1 Hci_dev
In Linux, Hci_dev is used to represent an HCI Host (corresponding to a control)
Members |
Role |
Char Name[8] |
Bluetooth name |
__u8 Bus |
HCI bus type, with HCI_USB,HCI_PCCARD,HCI_UART,HCI_PCI, etc. |
__u8 Dev_type |
HCI controller type, with Hci_bredr,hci_amp two kinds |
bdaddr_t bdaddr |
Bluetooth Device address,48 Bits |
__u8 dev_name[248] |
Bluetooth local name, available in user space settings |
unsigned int flags |
The markup for the process, such as pf_starting |
__u16 Pkt_type |
HCI packet types, HCI_DM1,HCI_DM3,HCI_DH1,HCI_HV1, etc. |
__u16 Link_policy |
Link policies, with Hci_lp_rswitch,hci_lp_hold,hci_lp_sniff,hci_lp_park |
__u16 Link_mode |
Link modes, there are hci_lm_accept,hci_lm_master,hci_lm_auth, etc. |
struct workqueue_struct* Workqueue |
Work queue, initialized in Hci_register_dev, to control the following (deferred) Work queue tasks |
struct WORK_STRUCT power_on Rx_work Cmd_work Tx_work |
Work queue task, corresponding kernel line subtree hci_power_on Hci_rx_work Hci_cmd_work Hci_tx_work |
struct Delayed_work Power_off Discov_off Service_cache |
Delay Work Queue task, corresponding kernel line subtree Hci_power_off Hci_discov_off Service_cache_off |
struct Sk_buff_head Rx_q Raw_q Cmd_q |
Data Packet List Raw_q/cmd_q for storing packets to be sent Rx_q for storing packets to be received |
2. Initialization
The initialization of the HCI section is done by the function hci_sock_init ().
Hci_sock_init (), Proto_register (), Bt_sock_register (), Bt_procfs_init ()
Proto_register adding the HCI protocol to a prot_list (for/proc/net/protocols)
Bt_sock_register Register the agreement with Pf_bluetooth to add BTPROTO_HCI to the Bt_proto array
Simultaneous registration of the HCI socket creation function hci_sock_create ()
Bt_procfs_init adding the HCI section to the proc file system
3. HCI sockets
An HCI socket creation function was registered in initialization hci_sock_create ()
Note: BTPROTO_HCI supports only sock_raw types of sockets
Hci_sock_create () is primarily called when the user creates a Sock_raw socket of the BTPROTO_HCI type
Includes some general initialization such as allocating memory, initializing HCI socket-related data
The most important thing is to define the HCI socket operation set Hci_sock_ops
When binding an HCI socket, there are three channels Raw/monitor/control (Raw is the default channel)
MONITOR: Used to notify user of device events, such as Hci_dev_up/hci_dev_suspend, with Hci_notify () to complete
4. Send data
In Linux, five types of HCI packets are defined
Command/acldata/scodata/event/vendor
Data send function hci_sock_sendmsg () defined in Hci_sock_ops
Different processing depending on the channel to which the HCI socket is bound
1) MONITOR: Do not do the processing
2) CONTROL: by Mgmt_control () to handle
3) RAW: Put to raw_q/cmd_q based on the HCI packet type, then dispatch the work queue
Call Hci_tx_work/hci_cmd_work for processing
The contents of the Hci_tx_work function are as follows
Static voidHci_tx_work (structWork_struct *Work ) { structHci_dev *hdev = container_of (Work,structHci_dev, tx_work); structSk_buff *SKB; bt_dbg ("%s ACL%d SCO%d le%d", Hdev->name, hdev->acl_cnt, Hdev->SCO_CNT, hdev->le_cnt); /*Schedule queues and send stuff to HCI driver*/Hci_sched_acl (Hdev); Hci_sched_sco (Hdev); Hci_sched_esco (Hdev); Hci_sched_le (Hdev); /*Send Next Queued Raw (unknown type) packet*/ while(SKB = Skb_dequeue (&hdev->RAW_Q))) Hci_send_frame (SKB);}
Sending different types of packets to the drive section (the Hci_send_frame function calls Hci_dev->send)
5. Receiving data
After the drive space receives data from the controller, call Hci_recv_frame ()
Hci_recv_frame () puts the packet into the queue rx_q and then schedules the work queue Rx_work
Thus triggering the rx_work corresponding processing function hci_rx_work ()
-------------------------------------------------------------------------
If the socket is in promiscuous mode (PROMISC, an HCI socket of raw type)
Call Hci_send_to_sock (), and then call SOCK_QUEUE_RCV_SKB ()
SOCK_QUEUE_RCV_SKB () adds the packet to the tail of the queue Sk_receive_queue
# # # # and then the middle doesn't know what to send, then call the following procedure ... # # # # # # # #
Hci_sock_recvmsg () –> hci_sock_cmsg () –> put_cmsg () sent to the original socket
-------------------------------------------------------------------------
Hci_rx_work () will be processed differently depending on the type of frame
1) Hci_event_pkt:hci_event_packet () Handles events from controller
2) Hci_acldata_pkt:hci_acldata_packet () handles ACL types of packets
3) Hci_scodata_pkt:hci_scodata_packet () Processing of SCO-type packets
Hci_acldata_packet and Hci_scodata_packet will send packets to the upper layer protocol.
6. IOCTL
The HCI_SOCK_IOCTL function handles IOCTL events, mainly including three classes
1) Set device status such as Hcidevup/hcidevdown/hcidevreset/hcidevrestat
2) Obtaining device information such as Hcigetdevlist/hcigetdevinfo/hcigetconnlist/hcigetconninfo/hcigetauthinfo
3) Set controler such as Hcisetscan/hcisetauth/hcisetencrypt, Issue command to controller and wait for response
Hci_dev_cmd ()->hci_request ()->hci_xxx_req ()
It is important to note that hcidevup, by calling Hci_dev_open to turn on the Bluetooth device (call Hci_dev->open)
7. Drive section
The code for the driver section is located in Drivers/bluetooth
The general Bluetooth driver initialization process is
Xxx_init () –> xxx_probe () –> Hci_alloc_dev () –> initialize HCI_DEV structure –> Hci_register_dev ()
Among them, the initialization of HCI_DEV structure part mainly includes: type (bus), Operation set (OPEN,CLOSE,FLUSH,SEND,IOCTL)
Typically, the driver customizes a device-related structure and initializes the hardware-related data.
However, the struct has a member variable that is a HCI_DEV structure body
Data receive function is usually done by interrupts, in Bluetooth HCI is transmitted on the UART/USB and so on, so the way to interrupt is also dependent on other modules
The registration of a receive function is usually performed explicitly or implicitly in the Xxx_probe or open function
Xxx_receive () –> hci_recv_frame () –> place data frames into Hci_dev->rx_q list –> in the dispatch work queue Rx_work
In addition to Hci_recv_frame, there are two BT protocol stack data reception functions hci_recv_fragment and Hci_recv_stream_fragment
7. API7.1 provides the underlying API
Hci_alloc_dev/hci_free_dev
Hci_register_dev/hci_unregister_dev
Hci_suspend_dev/hci_resume_dev
Hci_recv_frame/hci_recv_fragment/hci_recv_stream_fragment
7.2 APIs for the upper layer
Bt_sock_register/bt_sock_unregister
Hci_register_cb/hci_unregister_cb
Reference:
<linux Workqueue Working principle >
<bluetooth UART Interface Driver Initialization analysis >