11.2 L2CAP

   


The Logical Link Control and Adaptation Protocol (L2CAP) handles tasks on the data-link layer in the Bluetooth protocol stack. It establishes ACL connections for the next lower layer, but does not transport pure audio data, which primarily is transported over SCO connections. In particular, the L2CAP protocol is responsible for multiplexing data streams from higher layers to an ACL connection, because there must always be at most one ACL connection at a time between two Bluetooth devices. Other important tasks include the segmenting and reassembling of data packets to be able to send and receive the much larger packets of the higher-layer protocols despite the small packet sizes of the baseband layer. L2CAP supports packet sizes of up to 64 Kbytes.

To multiplex several data streams, L2CAP uses the abstraction of the channel. Each channel is allocated to one specific protocol. There are connection-oriented channels for point-to-point communication and connectionless channels used for group communication. A simple signaling method is used to establish an L2CAP connection. The L2CAP protocol can also be accessed directly from the user space over a socket. This is normally a socket from the PF_BLUETOOTH socket family with protocol identifier BTPROTO_L2CAP.

Now, when HCI receives an ACL packet, then it is passed to the receive function l2cap_recv_frame(). If the channel identifier in the packet header is 0x0001, then it is a signaling packet. Subsequently, the function l2cap_sig_channel() is invoked; otherwise, the function l2cap_data_channel() is invoked.

12cap_sig_channel()

net/bluetooth/12cap_core.c


The type of signaling packet is recognized within this function and, depending on the type, an appropriate handling function is invoked:

 switch (cmd.code) {        case L2CAP_CONN_REQ:              err = l2cap_connect_req(conn, &cmd, data);              break;        case L2CAP_CONN_RSP:              err = l2cap_connect_rsp(conn, &cmd, data);              break;        case L2CAP_CONF_REQ:              err = l2cap_config_req(conn, &cmd, data);              break;        case L2CAP_CONF_RSP:              err = l2cap_config_rsp(conn, &cmd, data);              break;        case L2CAP_DISCONN_REQ:              err = l2cap_disconnect_req(conn, &cmd, data);              break;        case L2CAP_DISCONN_RSP:              err = l2cap_disconnect_rsp(conn, &cmd, data);              break; 

The following section uses the example of an incoming connection request from a remote communication partner in the Bluetooth network to describe how the L2CAP protocol implementation works.

11.2.1 Connection Establishment Phase

When a request to establish a connection arrives from a remote communication partner, then the signaling code L2CAP_CONN_REQ is detected, and the function l2cap_connect_req() is invoked.

12cap_connect_req()

net/bluetooth/12cap_core.c


This function first checks on whether there is a waiting socket for this connection request that matches exactly the source address of the Bluetooth device from which the connection request originates and which concurrently matches the PSM field. The PSM (Protocol/Service Multiplexer) field specifies the desired higher protocol (e.g., RFCOMM).

Such a socket has to have been previously created by an application with the command listen and the function l2cap_sock_listen(), and it has to be in blocking wait state after the function accept() was invoked. This wait state is implemented in the function l2cap_sock_accept(), which uses the function l2cap_accept_dequeue() to wait until the state sk->state switches from BT_LISTEN to BT_CONNECTED.

The function l2cap_get_sock_listen(), which searches all sockets listening to the L2CAP protocol, checks for a socket waiting for an incoming connection request. Subsequently, it ensures that there is not already a connection with the source address of the requesting Bluetooth device. Next, the pertinent sock structure is initialized. The state sk->state in BT_CONFIG and the new channel with the function l2cap_chan_add() are added to the list of channels, conn->chan_list. Subsequently, the function l2cap_send_rsp(), which, in turn, accesses the function hci_send_acl() supplied by HCI, returns a L2CAP_CONN_RSP message to acknowledge the connection request.

11.2.2 Configuration Phase

If there are no errors, then the next step walks through the configuration phase, before the connection can be used for data transmission. First, both ends send a configuration request (signaling code L2CAP_CONF_REQ). The configuration phase can be completed successfully only if the configuration request of the other end has been acknowledged and a positive acknowledgement of its own configuration request was made.

The end that received the connection request waits for a configuration request after successful completion of the connection establishment phase. When the connection request arrives, the function l2cap_sig_channel() invokes the function l2cap_config_req().

12cap_config_req()

net/bluetooth/12cap.core.c


This function first uses l2cap_parse_conf_req() to evaluate the configuration options of the peer and store them in the protinfo structure of the sock structure. However, the QoS option is currently not evaluated. Next, the function l2cap_build_conf_rsp() is invoked. This function uses l2cap_conf_output() to discover whether the peer's configuration options (currently only the MTU) can be accepted. The function l2cap_send_rsp() is used to return a response. Subsequently, the function l2cap_send_req() uses the function l2cap_build_conf_req() to create and send a configuration request to the other end. Currently, only the MTU is considered.

12cap_config_rsq()

net\bluetooth/12cap.core.c


This function handles the peer's response to the configuration request. If the peer sends a nonempty response, then the current implementation disconnects immediately. Otherwise, the configuration phase can be abandoned. The field sk->state is set to BT_CONNECTED and, starting with the function call l2cap_chan_ready() (net/bluetooth/l2cap_core.c), the function pointer sk->state_change() is used to invoke the function sock_def_wakeup() (both in net/core/sock.c), which eventually marks the process waiting at the socket as an executable process.

11.2.3 Data Transmission Phase

This section describes the data transmission.

12cap_data_channel()

net/bluetooth/12cap.core.c


The function l2cap_data_channel() is invoked when data packets are received. The first step is to check for whether a connection is present in the list of channels, conn->chan_list, for the SCID (Source Connection IDentification). This check is done by the function l2cap_get_chan_by_scid(). After further checks, the data packet is put into the receive queue, and the function data_ready() of the sock structure is invoked, which then informs the application that new data is ready.

Looking at things from the BSD socket interface, data is received at the socket interface over the socket call recvmsg, which is mapped to the function l2cap_sock_recvmsg(). In this respect, there are no major differences from the implementations of other protocols that also use the function skb_recv_datagram() (net/core/datagram.c). This function causes a blocking or nonblocking wait for data in the input queue sk->receive_queue.

When sending, the socket call sendmsg() invokes the function l2cap_sock_sendmsg(), which uses the function l2cap_chan_send() to prepare a packet and then uses hci_send_acl() to send it.


       


    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