Learning BLE from Scratch: Discovering Services and Characteristics

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 listLearning BLE from Scratch: Discovering Services and CharacteristicsPacket Structure:Learning BLE from Scratch: Discovering Services and CharacteristicsLearning BLE from Scratch: Discovering Services and CharacteristicsLet’s take a look at an actual data packetLearning BLE from Scratch: Discovering Services and CharacteristicsThe address followed by the request is the packet headerLearning BLE from Scratch: Discovering Services and CharacteristicsLearning BLE from Scratch: Discovering Services and Characteristics

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.

Learning BLE from Scratch: Discovering Services and Characteristics

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

Learning BLE from Scratch: Discovering Services and CharacteristicsYou 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).

Learning BLE from Scratch: Discovering Services and Characteristics

We have no more data here

RFU:Reserved

Length: our data has a payload length of 11 bytes

Learning BLE from Scratch: Discovering Services and Characteristics

Channel Identifier CID=0x0004 indicates that the remaining data belongs to ATT, i.e., the Attribute Protocol.

Learning BLE from Scratch: Discovering Services and Characteristics

Learning BLE from Scratch: Discovering Services and CharacteristicsThe data structure at the ATT layer is as followsLearning BLE from Scratch: Discovering Services and Characteristics

AttributePDU

0x10 opcode corresponds to reading attributes by group

Learning BLE from Scratch: Discovering Services and CharacteristicsOpcodeLearning BLE from Scratch: Discovering Services and CharacteristicsRead 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

Learning BLE from Scratch: Discovering Services and Characteristics

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

Learning BLE from Scratch: Discovering Services and Characteristics

Attribute query response

Learning BLE from Scratch: Discovering Services and Characteristics

Group type read request response

Learning BLE from Scratch: Discovering Services and CharacteristicsOpcode 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 queryLearning BLE from Scratch: Discovering Services and CharacteristicsQuery againLearning BLE from Scratch: Discovering Services and CharacteristicsThe 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 packetLearning BLE from Scratch: Discovering Services and CharacteristicsLearning BLE from Scratch: Discovering Services and CharacteristicsRead the attribute at 0x000bRemember we mentioned earlier that each line of data is an attributeLearning BLE from Scratch: Discovering Services and CharacteristicsComposition of attributesFor services, what is read is the type of the service (UUID)Then the slave gives a response, returning the service’s UUIDLearning BLE from Scratch: Discovering Services and CharacteristicsThen, 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.Learning BLE from Scratch: Discovering Services and CharacteristicsLearning BLE from Scratch: Discovering Services and CharacteristicsLearning BLE from Scratch: Discovering Services and CharacteristicsRead 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:Learning BLE from Scratch: Discovering Services and CharacteristicsCharacteristic 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.Learning BLE from Scratch: Discovering Services and CharacteristicsCharacteristic attributes:Indicate the operations that the client can perform on the characteristic. Common attribute values include:Learning BLE from Scratch: Discovering Services and CharacteristicsThe 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 parametersLearning BLE from Scratch: Discovering Services and CharacteristicsLearning BLE from Scratch: Discovering Services and Characteristics

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

Learning BLE from Scratch: Discovering Services and Characteristics

  • 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 declarationsLearning BLE from Scratch: Discovering Services and CharacteristicsAgain retrieving characteristic declarationsLearning BLE from Scratch: Discovering Services and CharacteristicsCharacteristic 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 handlesLearning BLE from Scratch: Discovering Services and CharacteristicsRetrieve characteristic valuesBy obtaining characteristic declarations, the following information is knownLearning BLE from Scratch: Discovering Services and CharacteristicsUsing opcode 0x0A to read the attribute values of 0x0003 and 0x0006, obtaining the device name and appearance. Using handle 0x0007 to obtain connection parameters.Learning BLE from Scratch: Discovering Services and CharacteristicsConnection 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 onceLearning BLE from Scratch: Discovering Services and CharacteristicsThe slave continuously returns the characteristic list in multiple packetsLearning BLE from Scratch: Discovering Services and CharacteristicsThe 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 contentLearning BLE from Scratch: Discovering Services and CharacteristicsThis 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.

Leave a Comment