![]() |
Cordio Stack and Cordio Profiles
r2p3-02rel0
|
Content | |
ATT API | |
ATT Server API | |
ATT Client API | |
The ATT subsystem implements the attribute protocol and generic attribute profile. It contains two independent subsystems:
An ATT layer below ATTC and ATTS implements routing of received attribute protocol messages to either ATTC or ATTS.
For full generic ATT Interface, see ATT API.
This API controls the operation of the attribute protocol server (ATTS). For server interface, see ATT Server API.
An attribute server provides access to an attribute database stored within the server. According to the Bluetooth specification, attributes are collected into groups of characteristics, which are further collected into a service. A service is a collection of characteristics designed to accomplish a particular function, such as an alert service or a sensor service.
Figure 2 shows how services, characteristics, and attributes are organized according to the Bluetooth specification. An attribute database typically contains one or more services. Each service contains a set of characteristics, which is made up of one or more attributes. The type of attribute is uniquely identified by a UUID and an instance of an attribute in a server is uniquely identified by a handle. An attribute typically contains data that can be read or written by the attribute client on a peer device.
In the ATTS implementation, the attribute database consists of a linked list of one or more group structures. Each attribute group structure points to an array of attribute structures. Each attribute structure contains the UUID, data, and other information for the attribute. The data structures in the ATTS database implementation are illustrated in Figure 3.
The group structure contains a pointer to the attribute array, the handle range of the attributes it references, and other data. A database implementation typically uses one group structure per service, although this is not a requirement. A group can contain multiple services, or a service can be implemented with multiple groups.
An attribute UUID is either 16 bits or 128 bits in length. The UUID value is stored as a byte array in little endian format. For example:
The attribute value is stored as a byte array. If the attribute is an integer, the value is stored in little endian format.
The attribute protocol uses handles to uniquely identify attributes. To save memory, the attribute server does not store a handle for each attribute. Rather, it uses the starting handle value in each group to derive the handle of a particular attribute in the group. The start handle is the handle of the attribute at index zero of the group’s attribute array. The handle of each subsequent attribute is simply the start handle plus the attributes index in the array.
The Client Characteristic Configuration Descriptor (abbreviated as CCC or CCCD) enables or disables indications or notifications of the characteristic value associated with the descriptor.
The Bluetooth specification has certain requirements for CCCDs:
The functions in this interface simplify and centralize the management of CCCDs. However, if a server application does not use notifications or indications, or does not support bonding, then these functions do not need to be used.
An application using this interface is responsible for defining certain data structures, as shown below in Figure 4.
The data structures consist of bonded device CCCD tables, a CCCD settings table, a connection storage buffer, and a CCCD index enumeration. The Bonded device CCCD tables maintain persistent storage of the CCCD values for each bonded device. The CCCD settings table contains the CCCD attribute handle, security settings, and permitted CCCD values. The connection storage buffer holds separate CCCD values for all simultaneous connections. All tables are indexed by the CCCD index enumeration that defines the position in the table associated with each CCCD.
The dynamic attribute subsystem provides a mechanism through which an application can add services, characteristics, and attributes at runtime. The dynamic attribute subsystem is an alternative to AttsAddGroup which generally utilizes constant arrays that cannot change at runtime. The dynamic attribute subsystem maintains its attribute database in a volatile heap. The dynamic attribute interface provides functions for adding groups of attributes to this heap.
See ATT Client API for Interface.
The ATTC API contains a utility interface that simplifies common GATT client service and characteristic discovery procedures. It also contains interfaces that simplify the configuration of a service, for example reading or writing a set of characteristics or attributes after discovery is complete.
An application using this interface is responsible for defining certain data structures, as shown below in Figure 5.
The client discovery API uses a discovery control block that contains data used for the discovery and configuration procedure. The control block points to a discovery characteristic list, a configuration characteristic list, and a handle list.
The discovery characteristic list is a list of characteristics and descriptors that are to be discovered. Each item in the list contains the UUID of the characteristic or descriptor and its settings. As characteristics and descriptors are discovered, the handle list is populated with their respective handles.
The configuration characteristic list contains a list of characteristics and descriptors to read or write. Each item in the list contains the value (if it is to be written) and the handle index of the characteristic or descriptor in the handle list.
The Generic attribute profile (GATT) of the Bluetooth core specification defines how attribute protocol operations are used to perform GATT procedures. The table below demonstrates how the ATTC API performs GATT discovery procedures.
GATT Procedure | ATTC API |
---|---|
Discover All Primary Services | AttcReadByGroupTypeReq() startHandle=0x0001 endHandle=0xFFFF uuidLen = 2 pUuid= pointer to ATT_UUID_PRIMARY_SERVICE continuing=TRUE |
Discover Primary Services by Service UUID | AttcFindByTypeValueReq() startHandle = 0x0001 endHandle = 0xFFFF uuid16 = ATT_UUID_PRIMARY_SERVICE valueLen = 2 or 16 pValue = pointer to service UUID continuing = TRUE |
Find Included Services | AttcReadByTypeReq() startHandle = service start handle endHandle = service end handle uuidLen = 2 pUuid = pointer to ATT_UUID_INCLUDE |
Discover All Characteristics of a Service | AttcReadByTypeReq() startHandle = service start handle endHandle = service end handle uuidLen = 2 pUuid= pointer to ATT_UUID_CHARACTERISTIC continuing = TRUE |
Discover Characteristics by UUID | AttcReadByTypeReq() startHandle = service start handle endHandle = service end handle uuidLen = 2 pUuid= pointer to ATT_UUID_CHARACTERISTIC continuing = TRUE |
Discover All Characteristic Descriptors | AttcFindInfoReq() startHandle = characteristic value handle + 1 endHandle = characteristic end handle continuing = TRUE |
This section describes typical scenarios that use the API.
Figure 6 shows an example server operation.
First, a connection is established with an attribute protocol client on a peer device. The peer device sends an attribute protocol read request. In this example, the read request is handled internally by the stack and no interaction is required from the application.
Next, the peer device sends a write request. In this example, the attribute being written is configured to execute a write callback function. The callback executes and the application performs whatever operation is necessary for the attribute. On return of the callback the stack sends a write response packet.
Next, the application sends a handle value notification to the peer device by calling AttsHandleValueInd(). The stack sends a handle value indication packet.
When the stack receives a handle value confirmation packet from the peer, it executes the application's ATT callback with event ATTS_HANDLE_VALUE_CNF.
Figure 7 shows some example client operations.
Figure 8 shows an example prepare and execute write procedure.
Figure 9 shows and example of discovery and configuration using the ATT client discovery API.