Through previous studies, we learned that BLE devices act as servers, storing some data, while clients achieve corresponding functions by reading, writing, and configuring this data.
Previously, we learned about broadcasting and connections; today, let’s take a look at what happens after a connection is established.Discovery of Services and CharacteristicsAfter a device establishes a connection, it first retrieves the service listPacket Structure:
Let’s take a look at an actual data packet
The address followed by the request is the packet header
LLID:This data bit indicates the logical link to which the packet belongs,and whether the valid data portion contains a link layer data packet or a link layer control packet. Among them::
00 indicates reserved.
01indicates a link layer dataPDU,andL2CAP messages are fragmented oremptyPDU.
10 indicates a link layer dataPDU,andL2CAP message is the start or an unfragmented completeI2CAP message. (Currently, our data is this packet header)
11indicates a link layer control packet.
Empty packet’s LLID
NESN:The receiver informs the sender of the expected next data packet’s SN through NESN.After successfully receiving a data packet, the receiver flips NESN.
-
The sender determines whether to retransmit based on the received NESN:
-
If
<span>NESN == current sent SN</span>
: indicates the receiver has correctly received it, send the next new data packet. -
If
<span>NESN != current sent SN</span>
: indicates the receiver has not received it, retransmit.
SN:Data packet sequence number: used to identify the order of the current data packet, ensuring the receiver can detect lost or duplicate packets.
Each time a new non-empty data packet (containing payload) is sent, the SN flips. If the same data packet is retransmitted, the SN remains unchanged. The receiver compares the current SN with the last received SN to determine whether the packet is new data or retransmission.
So the data we captured is as follows
You can use Wireshark to observe these two fields to troubleshoot packet loss or retransmission issues.
MD:(More Data) Flag indicates whether the current device has more data to transmit, set <span>MD=1</span>
, indicating there is more data to follow. The host continues to listen after receiving it (does not terminate the connection event).
We have no more data here
RFU:Reserved
Length: our data has a payload length of 11 bytes
Channel Identifier CID=0x0004 indicates that the remaining data belongs to ATT, i.e., the Attribute Protocol.
The data structure at the ATT layer is as follows
AttributePDU
0x10 opcode corresponds to reading attributes by group
Opcode
Read attributes by group
Group type read requests are used to obtain attribute values where the attribute type is known, but the handle is unknown, defined by the upper layer specification. Common attribute types include:
Primary Service:UUID: 0x2800
Secondary Service:UUID: 0x2801
Query handles start from 0x0001 to 0xffff for the0x2800 service, representing a query for all primary services
The corresponding data was returned from the device
Attribute query response
Group type read request response
Opcode 0x11: Attribute query response Start handle 0x0001, end handle 0x0009, belongs to GAP service (UUID=0x1800) Start handle 0x000a, end handle 0x000a, belongs to GATT service (UUID=0x1801)Then the host sends another group query
Query again
The second query responseHandles from 0x000b to 0xffff belong to a custom primary service; in this example, we have a custom service for controlling an LED light.Then, the host sends a request for the attribute data packet
Read the attribute at 0x000bRemember we mentioned earlier that each line of data is an attribute
Composition of attributesFor services, what is read is the type of the service (UUID)Then the slave gives a response, returning the service’s UUID
Then, the host sends another 0x08 opcode: read by type request.To obtain attribute values where the attribute type is known but the handle is unknown within the handle range.
Read by type request0x2803: Characteristic Declaration.This data requests to read characteristic declarations within the range of 0x0001~0x0009.The slave returns the data as follows:
Characteristic declaration responsePreviously, we mentioned that a characteristic contains three attributes: characteristic declaration, characteristic value, and characteristic descriptor.Characteristic declaration: The attribute type (UUID) of the characteristic declaration is 0x2803, which indicates that this is a characteristic declaration, the start of the entire characteristic.
Characteristic attributes:Indicate the operations that the client can perform on the characteristic. Common attribute values include:
The attribute handle of the characteristic value and the UUID of the characteristic value refer to the attribute handle and UUID in the next line.The slave returns three characteristic declarations: device name, appearance, and preferred connection parameters
-
BLE 4.x has a default ATT MTU of 23 bytes, after deducting the header, the actual transmittable characteristic declaration data is limited.Each characteristic declaration occupies 7 bytes (Handle 2 + Properties 1 + Value Handle 2 + UUID 2), thus a single packet can return at most:
-
BLE 5.0+ supports extended MTU (e.g., 247 bytes), allowing more characteristics to be returned at once.
Then, the host retrieves the remaining characteristic declarationsAgain retrieving characteristic declarations
Characteristic declaration responseCentral Address Resolution is a feature in the Bluetooth specification that allows devices to resolve random private addresses during a connection. When a device supports this feature, it can recognize previously paired devices even if they use random addresses.The peer retrieves characteristic declarations to know which characteristics are protected and their corresponding handles
Retrieve characteristic valuesBy obtaining characteristic declarations, the following information is known
Using opcode 0x0A to read the attribute values of 0x0003 and 0x0006, obtaining the device name and appearance. Using handle 0x0007 to obtain connection parameters.
Connection parameters include the minimum and maximum connection intervals.In addition to step-by-step queries, the host also used opcode 0x04: Information Lookup, to obtain the entire characteristic list at once
The slave continuously returns the characteristic list in multiple packets
The host also sent a query with a starting handle less than the ending handle, receiving an erroneous response. It is unclear why the host would do this; perhaps to ensure that no information is missed?In any case, after a series of operations, we finally obtained the following interface content
This concludes the tasks performed by the GAP layer, ATT layer, and L2CAP layer.The above communication process is implemented by the protocol stack’s GAP layer, ATT layer, and L2CAP layer on the slave side, so there is no need to worry too much about implementation issues; you just need to prepare the corresponding data.