Mistake on this page? Email us
Modules
Attribute Profile (ATT)

Modules

 ATT API
 
 ATT Server API
 
 ATT Client API
 

Detailed Description

Introduction

diagram_att.png
Figure 1. BLE Stack: ATT

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.

ATT Server

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.

diagram_atts.png
Figure 2. Services, characteristics, and attributes stored in an attribute server

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.

diagram_atts_database.png
Figure 3. ATTS attribute database data structures

Attribute UUID

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:

/* A 16-bit UUID value 0x0016 */
uint8 uuid16[] = {0x16, 0x00};
/* A 128-bit UUID value 00001234-0000-1000-8000-00805F9B34FB */
uint8 uuid128[] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
0x00, 0x10, 0x00, 0x00, 0x34, 0x12, 0x00, 0x00};

Attribute Value

The attribute value is stored as a byte array. If the attribute is an integer, the value is stored in little endian format.

Attribute Handle

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.

Client Characteristic Configuration

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:

  1. The server must maintain the value of the CCCD separately for each client.
  2. If the server and client are bonded, the value of the CCCD is persistent across connections.
  3. If the server and client are not bonded, the value of the CCCD is reset to zero when the client connects.

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.

diagram_atts_cccd.png
Figure 4. CCCD data structures defined by the application

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.

Dynamic Attribute Interface Operation

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.

Note
Service discovery generally takes place shortly after a connection opens. Therefore, this interface should generally be used before a connection opens.

Use of the dynamic attribute subsystem is optional.

ATT Client

See ATT Client API for Interface.

Client Discovery 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.

diagram_attc_discovery.png
Figure 5. Client discovery data structures defined by the application

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.

GATT Discovery Procedures

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 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

Usage Scenarios

This section describes typical scenarios that use the API.

Server Operations

Figure 6 shows an example server operation.

operation_att_server.png
Figure 6. Server Operations

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.

Client Operations

Figure 7 shows some example client operations.

operation_att_client.png
Figure 7. Client Operations
  1. First, a connection is established with an attribute protocol server on a peer device.
    1. The application initiates a request by calling AttcReadByGroupTypeReq() with the continuing parameter set to TRUE.
    2. The client sends an attribute protocol read by group type request, receives a response, and executes the ATT callback with event ATTC_READ_BY_GROUP_TYPE_RSP. Because the read by group type procedure is not complete, the client automatically sends another read by group type request packet to continue the procedure.
    3. When the procedure is complete, the ATT callback is executed with event ATTC_READ_BY_GROUP_TYPE_RSP and the continuing parameter set to FALSE.
  2. Next the application sends another request by calling AttcReadByTypeReq().
    1. The stack sends a read by type request packet, receives a response, and executes the ATT callback with event ATTC_READ_BY_TYPE_RSP.
    2. In this example, the procedure is complete in the first packet transaction and the continuing parameter is set to FALSE.
  3. Finally, the application writes an attribute by calling AttcWriteCmd().
    1. The stack sends a write command packet. This packet does not have a corresponding response packet.
    2. When the stack has sent the packet, it executes the ATT callback with event ATTC_WRITE_CMD_RSP.

Client Prepare and Execute Write

Figure 8 shows an example prepare and execute write procedure.

operation_att_client_prepexecwrite.png
Figure 8. Client Prepare and Execute Write
  1. The application calls AttcPrepareWriteReq() to write an attribute value.
  2. The stack sends prepare write request packets until all the data has been sent to the peer device.
  3. The ATT callback is executed with event ATTC_PREPARE_WRITE_RSP each time a response packet is received.
  4. When callback event parameter continuing is set to FALSE, the procedure is complete.
  5. Next the application calls AttcExecuteWriteReq() to execute the write procedure in the peer device's attribute server.
  6. The stack sends and executes the write request packet.
  7. When it receives a response, it executes the ATT callback with event ATTC_EXECUTE_WRITE_RSP.

Client Discovery and Configuration

Figure 9 shows and example of discovery and configuration using the ATT client discovery API.

operation_att_client_discconfig.png
Figure 9. Client Discovery and Configuration Procedures
  1. First, service discovery is initiated by calling AttcDiscService() with the UUID of the service to be discovered.
  2. The ATT callback is executed with event ATTC_FIND_BY_TYPE_VALUE_RSP containing discovery results.
  3. The callback message is passed to function AttcDiscServiceCmpl(), which returns ATT_SUCCESS indicating that service discovery completed successfully.
  4. Then the application proceeds with characteristic discovery by calling AttcDiscCharStart().
  5. The ATT callback is executed with event ATTC_READ_BY_TYPE_RSP containing characteristic discovery results.
  6. The callback message is passed to function AttcDiscCharCmpl(), which returns ATT_CONTINUING indicating that characteristic discovery is continuing. This procedure repeats until AttcDiscCharCmpl() returns ATT_SUCCESS indicating that characteristic discovery completed successfully.
  7. Then the application proceeds with characteristic configuration by calling AttcDiscConfigStart(). A characteristic read or write is performed according to the contents of the configuration characteristic list, and the ATT callback is executed.
  8. The callback message is passed to function AttcDiscConfigCmpl(), which returns ATT_CONTINUING indicating that configuration is not complete. The procedure repeats until AttcDiscConfigCmpl() returns ATT_SUCCESS.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.