The HCI part of Linux bluetooth kernel analysis

Source: Internet
Author: User

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-&GT;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 >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.