11.1 Host Controller Interface (HCI)

   


The Host Controller Interface (HCI) forms the interface between the software protocol stack and the Link Manager underneath it, which is implemented in the firmware of a Bluetooth device. Notice that this is a packet-oriented communication between HCI and the Link Manager rather than a device driver. The difference is that HCI does not access the register and the memory locations of a Bluetooth device directly. Instead, it sends command and data packets to the device and receives data packets and event-message packets from this device. This means that the Host Controller Interface offers a uniform interface for accessing the hardware.

11.1.1 Command Packets

There is a uniform packet format for command packets sent by HCI to the Link Manager. All packets are ordered in groups. In the command group (opcode group), we distinguish between individual commands (opcode commands). Each command packet consists of a 10-bit OCF (Opcode Command Field) and a 6-bit OGF (Opcode Group Field). There are the following command groups:

  • Link control commands serve to establish a connection to other Bluetooth devices and to control the connection.

  • Link policy commands serve to change parameters, which are used by the Link Manager to manage connections. For example, such commands can cause connections to switch into the hold mode.

  • Host controller and baseband commands allow you to specify additional parameters for the behavior of the Link Manager (e.g., to filter event messages or to activate the flow control discussed further below).

  • Information parameters offer a pure read access to values of a Bluetooth device, such as the size of the transmit buffer, the version number, and the 48-bit Bluetooth device address.

In addition to these groups, there are the following groups: status parameters, testing commands, Bluetooth logo testing, and vendor-specific debug commands.

The following sections describe how command packets can be sent within the Bluetooth implementation in the Linux kernel.

hci_send_cnd()

net/bluetooth/hci_core.c


This function is used to compose a command packet in the form of an sk_buff out of the passed data, the OCF and OGF values, the length, and a pointer to parameters. The function skb_queue_tail then appends this packet to the end of the command queue of the struct hci_dev of the Bluetooth device.

The structure hci_dev is defined in include/net/bluetooth/hci_core.h. In addition to the command queue, it contains queues for transmit data. In addition to a number of other parameters, it includes four function pointers, to the functions open(), close(), flush(), and send() made available by the Bluetooth device.

Finally, the function hci_send_cmd() invokes the function hci_sched_cmd(), which marks the hdev->cmd_task as ready to be executed. This tasklet was assigned to the device by the function tasklet_init() within the function call hci_register_init() (net/bluetooth/hci_core.c) when the HCI support was initialized. In addition, there is a hdev->rx_task to receive data and another hdev->tx_task to send data. When the tasklet hdev->cmd_task runs, then the function hci_cmd_task() is invoked. This function invokes hci_send_frame().

hci_send_frame()

net/bluetooth/hci_core.c


This function serves as a central transmit function for the HCI. This function serves not only to send command packets, but also to send data packets. It uses the entry int (*send) from the structure hci_dev to invoke the transmit function of the Bluetooth device, to which it passes the skb.

11.1.2 Event Packets

The time it takes to process different HCI commands can be different, Bluetooth implements asynchronous communication. The results of a command are announced to HCI in the form of an event packet. In most cases, this is merely an event of the type Command Complete, which means that the command was successfully completed. A Bluetooth device can receive arbitrary packets by activating the tasklet hci_rx_task when the interrupt triggered by the incoming packet is handled. This tasklet invokes the function hci_rx_task().

hci_rx_task()

net/bluetooth/hci_core.c


This function is used to distinguish an incoming packet further by type. Incoming event packets are further processed by the function hci_event_packet(); accordingly, the functions hci_acldata_packet() and hci_scodata_packet() are invoked for the ACL and SCO data described further below.

Event packets are further distinguished by type of event in the function hci_event_packet(). For example, the type Number of Completed Packets invokes the function hci_num_comp_pkts_evt(). This function evaluates the content of the event packet, which includes the number of packets actually sent per connection by the Bluetooth device. A handle negotiated between the Link Manager and HCI can be used to map the reported number of sent packets to a specific connection (an hci_conn structure). This is done via a hash table in the HCI layer. The counter acl_cnt of struct hci_dev is incremented by one for each acknowledged packet. Feedback on the number of packets sent serves the flow control described in the following section.

11.1.3 Data Packets

We distinguish between asynchronous connectionless (ACL) and synchronous connection-oriented (SCO) data packets. Both data types are sent when the tasklet hdev->tx_task becomes active, and then the function hci_sched_acl() (net/bluetooth/hci_core.c) is executed. If flow control for ACL data runs between HCI and the Link Manager, then we first have to check on whether ACL data may be sent.

Flow control is used to prevent the transmit buffer of the Bluetooth device from overflowing. This can happen, for example, when an application sends data faster than the Bluetooth device can transport it further for instance, because the communication partner is temporarily not reachable. The initial size of the output buffer can be polled from HCI. The current size of the output buffer can be derived from event packets of the type Number of Completed Packets, described above. HCI assumes that the free output buffer becomes smaller with each packet it passes to the Link Manager. The actual current size can be learned only upon receipt of a new event packet.

Flow control in the Bluetooth protocol stack of the Linux kernel is handled by the function hci_sched_acl(). In turn, this function invokes the function hci_low_acl_sent():

hci_low_acl_sent()

net/bluetooth/hci_core.c


First, this function finds out the total number, num, of all connections known to the specified network device. For each connection (represented by the structure hci_conn), the field acl_sent includes the number of ACL data packets sent over this connection. This field is incremented during a transmission, but decremented by the number of acknowledged packets over this connection when the described event packet Number of Completed Packets is received. In addition, the function hci_low_acl_sent() identifies the connection with the smallest number of ACL packets sent, which has to be smaller than 0xffff. If none of the existing connections meets these conditions, then the function's return value is set to null. If there is such a connection, then the total number of acknowledged packets (acl_cnt entry in struct hci_dev) is divided by the number (num) of connections. The result is returned by the parameter quote, and the identified connection is the return value of the function. The number of acknowledged packets forms the transmit credit, which is distributed over all ready-to-send connections.

hci_sched_acl()

net/bluetooth/hci_core.c


Using the quote calculated by the function hci_low_acl_sent(), this function tries to send ACL data packets over the specified connection (by using the function hci_send_frame()). ACL data packets may be sent as long as the queue is not empty, as long as the number of ACL packets to be formed from one skb does not exceed the transmit credit of the Bluetooth device, and as long as quote is not yet null. Both quote and the transmit credit stored in the hci_dev structure are decremented by one for each packet sent. At the same time, the number of packets sent over this connection is incremented.

hci_sched_sco()

net/bluetooth/hci_core.c


Only the transmit credit for SCO packets, included in the field sco_cnt of struct hci_dev, is considered in the case of SCO data packets. There is no distribution over several connections for SCO connections. SCO data packets are simply sent until the transmit credit is used up.

11.1.4 Accessing the Host Controller Interface

The functionality of the Host Controller Interface (HCI) in Linux is available in different ways. Figure 11-1 shows that HCI can be accessed directly from the user space over a socket. This is normally a socket of the PF_BLUETOOTH socket family with protocol identifier BTPROTO_HCI und type SOCK_RAW. These sockets are created in the file net/bluetooth/hci_sock.c. The socket interface is used to supply the usual BSD socket functions. An application can use these functions to send and receive data directly over HCI from and to the network.

Alternatively, an application can use ioctl() calls to access the Bluetooth device (e.g., to open, close, or reset the device).

For higher protocol layers to be implemented in the Linux kernel, HCI functions are available over the macro EXPORT_SYMBOL. For example, the L2CAP protocol described in the next section accesses these functions, including functions to register and deregister the HCI device (hci_register_dev() and hci_unregister_dev()) and interfaces to higher protocols. For example, the functions hci_register_proto() and hci_unregister_proto() serve to register the higher-layer protocol (e.g., L2CAP) that supplies a receive function or other functions to the HCI. The function hci_register_notifier() is used by the higher-layer protocol to register itself with the notifier chain of the device. (See Chapter 5.) The function hci_connect(), which sends a command packet from HCI to the Link Manager (net/bluetooth/hci_core.c), is used to establish a connection. The counterpart of this function is the function hci_disconnect(). The functions hci_send_acl(), hci_send_sco(), and hci_send_raw() are used to transmit, and the function hci_recv_frame() is used to receive.


       


    Linux Network Architecture
    Linux Network Architecture
    ISBN: 131777203
    EAN: N/A
    Year: 2004
    Pages: 187

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net