docs: Migrate ESP32 Bluetooth Architecture PDF content to ESP-IDF

This commit is contained in:
luweike
2025-03-17 11:07:40 +08:00
parent 4f3e64331b
commit d4fc63553d
29 changed files with 1278 additions and 118 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
docs/_static/profile-dependencies.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

View File

@@ -17,6 +17,8 @@ if os.environ.get('IDF_PATH') is None:
raise RuntimeError('IDF_PATH should be set, run export.sh before building docs')
BT_DOCS = [
'api-guides/bt-architecture/index.rst',
'api-guides/bt-architecture/overview.rst',
'api-reference/bluetooth/esp_bt_defs.rst',
'api-reference/bluetooth/esp_bt_device.rst',
'api-reference/bluetooth/esp_bt_main.rst',
@@ -36,6 +38,7 @@ BLE_DOCS = [
'api-guides/ble/get-started/ble-device-discovery.rst',
'api-guides/ble/get-started/ble-connection.rst',
'api-guides/ble/get-started/ble-data-exchange.rst',
'api-guides/ble/smp.rst',
'api-reference/bluetooth/bt_le.rst',
'api-reference/bluetooth/esp_gap_ble.rst',
'api-reference/bluetooth/esp_gatt_defs.rst',
@@ -58,6 +61,7 @@ BLE_MESH_DOCS = [
CLASSIC_BT_DOCS = [
'api-guides/classic-bt/index.rst',
'api-guides/classic-bt/overview.rst',
'api-guides/classic-bt/profiles-protocols.rst',
'api-reference/bluetooth/classic_bt.rst',
'api-reference/bluetooth/esp_a2dp.rst',
'api-reference/bluetooth/esp_avrc.rst',

View File

@@ -21,7 +21,7 @@ Basic Concepts
Initiating a Connection
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*With the introduction of extended advertising features in Bluetooth LE 5.0, there are slight differences in the connection establishment process between Legacy ADV and Extended ADV. Below, we take the Legacy ADV connection establishment process as an example.*
*With the introduction of extended advertising features in Bluetooth Core Specification 5.0, there are slight differences in the connection establishment process between Legacy ADV and Extended ADV. Below, we take the Legacy ADV connection establishment process as an example.*
When a scanner receives an advertising packet on a specific advertising channel, if the advertiser is connectable, the scanner can send a connection request on the same advertising channel. The advertiser can set a *Filter Accept List* to filter out untrusted devices or accept connection requests from any scanner. Afterward, the advertiser becomes the peripheral device, and the scanner becomes the central device, allowing for bidirectional communication over the data channel.
@@ -101,7 +101,7 @@ The structure of the Data Channel Packet is similar to that of the :ref:`Adverti
* - 2
- Payload
- 0-27 / 0-251
- Before Bluetooth LE 4.2, the maximum payload was 27 bytes; Bluetooth LE 4.2 introduced Data Length Extension (DLE), allowing a maximum payload of 251 bytes.
- Before Bluetooth Core Specification 4.2, the maximum payload was 27 bytes; Bluetooth Core Specification 4.2 introduced Data Length Extension (DLE), allowing a maximum payload of 251 bytes.
* - 3
- Message Integrity Check, MIC
- 4
@@ -124,9 +124,9 @@ The payload of the data PDU can be further divided into:
- ATT Header + ATT Data
- 0-23 / 0-247
The default MTU value is 23 bytes, which matches the maximum ATT data byte size that can be carried in a single data PDU before Bluetooth LE 4.2.
The default MTU value is 23 bytes, which matches the maximum ATT data byte size that can be carried in a single data PDU before Bluetooth Core Specification 4.2.
MTU can be set to larger values, such as 140 bytes. Before Bluetooth LE 4.2, with a maximum of 23 bytes carrying ATT data in the payload, a complete ATT data packet would need to be split across multiple data PDUs. After Bluetooth LE 4.2, a single data PDU can carry up to 247 bytes of ATT data, so an MTU of 140 bytes can still be accommodated in a single data PDU.
MTU can be set to larger values, such as 140 bytes. Before Bluetooth Core Specification 4.2, with a maximum of 23 bytes carrying ATT data in the payload, a complete ATT data packet would need to be split across multiple data PDUs. After Bluetooth Core Specification 4.2, a single data PDU can carry up to 247 bytes of ATT data, so an MTU of 140 bytes can still be accommodated in a single data PDU.
Hands-On Practice

View File

@@ -41,7 +41,7 @@ Bluetooth Channels
Similar to Bluetooth Classic, the Bluetooth SIG has adopted Adaptive Frequency Hopping (AFH) in Bluetooth LE to address data collision issues. This technology can assess the congestion of RF channels and avoid crowded channels through frequency hopping to improve communication quality. However, unlike Bluetooth Classic, Bluetooth LE uses the 2.4 GHz ISM band divided into 40 RF channels, each with a 2 MHz bandwidth, ranging from 2402 MHz to 2480 MHz, while Bluetooth Classic uses 79 RF channels, each with a 1 MHz bandwidth.
In the Bluetooth LE 4.2 standard, RF channels are categorized into two types, as follows:
In Bluetooth Core Specification 4.2, RF channels are categorized into two types, as follows:
.. list-table::
:align: center
@@ -67,7 +67,7 @@ During advertising, the advertiser will send advertising packets on the three ad
Extended Advertising Features
##################################
In the Bluetooth LE 4.2 standard, advertising packets are limited to a maximum of 31 bytes, which restricts the functionality of advertising. To enhance the capability of advertising, Bluetooth 5.0 introduced the Extended Advertising feature. This feature divides advertising packets into:
In Bluetooth Core Specification 4.2, advertising packets are limited to a maximum of 31 bytes, which restricts the functionality of advertising. To enhance the capability of advertising, Bluetooth 5.0 introduced the Extended Advertising feature. This feature divides advertising packets into:
.. list-table::
:align: center
@@ -124,7 +124,7 @@ What information is included in the advertising packet?
Advertising Packet Structure
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For the third question, regarding the information contained in the advertising packet, the Bluetooth LE 4.2 standard defines the format of the advertising packet, as shown in the diagram below:
For the third question, regarding the information contained in the advertising packet, Bluetooth Core Specification 4.2 defines the format of the advertising packet, as shown in the diagram below:
.. _adv_packet_structure:
@@ -134,7 +134,7 @@ For the third question, regarding the information contained in the advertising p
:scale: 35%
:alt: Advertising Packet Structure
Bluetooth LE 4.2 Advertising Packet Structure
Advertising Packet Structure in Bluetooth Core Specification 4.2
Lets break it down step by step. The outer layer of an advertising packet contains four parts, which are:
@@ -336,7 +336,7 @@ For devices using random private addresses to communicate with trusted devices,
* - Non-resolvable Random Private Address
- Completely random and rarely used, as it cannot be resolved and is only meant to prevent tracking
Let's look at the **advertising data**. The format of an advertising data structure is defined as follows:
Let's look at the advertising data. The format of an advertising data structure is defined as follows:
.. list-table::
:align: center
@@ -361,6 +361,148 @@ Let's look at the **advertising data**. The format of an advertising data struct
-
Advertising Process
^^^^^^^^^^^^^^^^^^^^^
Advertising With a Public Address
####################################
When using a public address for advertising, set the ``own_addr_type`` of ``esp_ble_adv_params_t`` to ``BLE_ADDR_TYPE_PUBLIC``. The advertising process flowchart is as follows (*click to enlarge*):
.. seqdiag::
:caption: Advertising With a Public Address
:align: center
:scale: 200%
seqdiag adv-public-addr {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 14;
"Input\n[Advertiser]";
"API\n[Advertiser]";
"LLM\n[Advertiser]";
"LLM\n[Scanner]";
"API\n[Scanner]";
"Output\n[Scanner]";
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_set_device_name"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_config_adv_data"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends config adv data HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns set adv data event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_data_set_complete_evt"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_start_advertising to start advertising; sets the own_addr_type parameter to ble_addr_type_public"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends start adv HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns start adv event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_start_complete_evt"];
"LLM\n[Scanner]" -> "API\n[Scanner]";
"API\n[Scanner]" -> "Output\n[Scanner]" [label="esp_gap_ble_scan_result_evt"];
}
Advertising With a Resolvable Random Private Address
##########################################################
When using a resolvable random private address for advertising, the underlying protocol stack updates the advertising address when the resolvable random private address times out. The default timeout is set to 15 minutes. The timeout duration for the resolvable random private address can be configured using the ``BT_BLE_RPA_TIMEOUT`` option in menuconfig. Set the ``own_addr_type`` of ``esp_ble_adv_params_t`` to ``BLE_ADDR_TYPE_RPA_PUBLIC`` or ``BLE_ADDR_TYPE_RPA_RANDOM``. The advertising process flowchart is as follows (*click to enlarge*):
.. seqdiag::
:caption: Advertising With a Resolvable Random Private Address
:align: center
:scale: 200%
seqdiag adv-resolvable-addr {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 14;
"Input\n[Advertiser]";
"API\n[Advertiser]";
"LLM\n[Advertiser]";
"LLM\n[Scanner]";
"API\n[Scanner]";
"Output\n[Scanner]";
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_set_device_name"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_config_local_privacy"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_config_adv_data"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends config adv data HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns set adv data event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_data_set_complete_evt"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_start_advertising to start advertising; sets the own_addr_type parameter to ble_addr_type_rpa_public or ble_addr_type_rpa_random"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends start adv HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns start adv event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_start_complete_evt"];
"LLM\n[Scanner]" -> "API\n[Scanner]";
"API\n[Scanner]" -> "Output\n[Scanner]" [label="esp_gap_ble_scan_result_evt"];
}
.. note::
When advertising with a resolvable random private address, advertising should start only after the ``esp_ble_gap_config_local_privacy`` event returns. Set ``own_addr_type`` to ``BLE_ADDR_TYPE_RPA_PUBLIC`` or ``BLE_ADDR_TYPE_RPA_RANDOM``.
To use ``BLE_ADDR_TYPE_RPA_RANDOM``, a random static address must be set through the ``esp_ble_gap_set_rand_addr`` API. This step is not required for ``BLE_ADDR_TYPE_RPA_PUBLIC``.
``BLE_ADDR_TYPE_RPA_PUBLIC`` operates as follows: The controller generates a Resolvable Random Private Address (RPA) based on the local Identity Resolving Key (IRK) from the resolving list. If no matching entry is found in the resolving list, the public address is used.
For ``BLE_ADDR_TYPE_RPA_RANDOM``, If no matching entry is found in the resolving list, a random static address is used.
Advertising with a Random Static Address
###########################################
Similar to advertising with a resolvable random private address, advertising with a random static address requires setting the ``own_addr_type`` of ``esp_ble_adv_params_t`` to ``BLE_ADDR_TYPE_RANDOM``. The advertising process flowchart is as follows (*click to enlarge*):
.. seqdiag::
:caption: Advertising With a Random Static Address
:align: center
:scale: 200%
seqdiag adv-random-addr {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 14;
"Input\n[Advertiser]";
"API\n[Advertiser]";
"LLM\n[Advertiser]";
"LLM\n[Scanner]";
"API\n[Scanner]";
"Output\n[Scanner]";
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_set_device_name"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_set_rand_addr"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends set rand address HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns set rand address event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_set_static_rand_addr_evt"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends config adv data HCI command to LL layer"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_config_adv_data"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="return set adv data event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="calls\n esp_gap_ble_adv_data_set_complete_evt"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_start_advertising to start advertising; sets the own_addr_type parameter to ble_addr_type_random"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends start adv HCI command to LL layer"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns start adv event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_start_complete_evt"];
"LLM\n[Scanner]" -> "API\n[Scanner]";
"API\n[Scanner]" -> "Output\n[Scanner]" [label="esp_gap_ble_scan_result_evt"];
}
Basic Concepts of Scanning
^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -370,8 +512,7 @@ Similar to the advertising process, scanning also raises three questions:
2. When to scan and for how long? (When?)
3. What to do during scanning? (What?)
For Bluetooth LE 4.2 devices, the advertiser only sends data on the advertising channels, which are channels 37-39. For Bluetooth LE 5.0 devices, if the advertiser has enabled extended advertising, it sends `ADV_EXT_IND` on the primary advertising channels and `AUX_ADV_IND` on the secondary advertising channels.
Thus, for Bluetooth LE 4.2 devices, scanners only need to receive advertising data on advertising channels. For Bluetooth LE 5.0 devices, scanners must first receive the `ADV_EXT_IND` on the primary advertising channels and, if it indicates a secondary channel, move to the corresponding secondary channel to receive the `AUX_ADV_IND`.
For Bluetooth LE 4.2 devices, the advertiser only sends data on the advertising channels, which are channels 37-39. For Bluetooth LE 5.0 devices, if the advertiser has enabled extended advertising, it sends `ADV_EXT_IND` on the primary advertising channels and `AUX_ADV_IND` on the secondary advertising channels. Thus, for Bluetooth LE 4.2 devices, scanners only need to receive advertising data on advertising channels. For Bluetooth LE 5.0 devices, scanners must first receive the `ADV_EXT_IND` on the primary advertising channels and, if it indicates a secondary channel, move to the corresponding secondary channel to receive the `AUX_ADV_IND`.
Scan Window and Scan Interval

View File

@@ -26,6 +26,15 @@ Get Started
get-started/ble-connection
get-started/ble-data-exchange
***************
Security
***************
.. toctree::
:maxdepth: 2
smp
**********
Profile
**********

View File

@@ -17,7 +17,7 @@ This document provides an architecture overview of the Bluetooth Low Energy (Blu
{IDF_TARGET_NAME} supports Bluetooth 5.0 (LE) and is certified for Bluetooth LE 5.3.
The Bluetooth LE stack in ESP-IDF is a layered architecture that enables Bluetooth functionality on {IDF_TARGET_NAME} chip series. The table below shows its architecture.
The Bluetooth LE stack in ESP-IDF is a layered architecture that enables Bluetooth functionality on {IDF_TARGET_NAME} chip series. The figure below shows its architecture.
.. only:: esp32 or esp32s3 or esp32c3 or esp32c6 or esp32c5 or esp32c61

View File

@@ -0,0 +1,163 @@
SMP
=============
:link_to_translation:`zh_CN:[中文]`
The Security Manager Protocol (SMP) is implemented within Bluetooth Low Energy's GAP module. SMP is responsible for generating encryption and identity keys, defining a protocol for pairing and key distribution, and ensuring secure communication between devices in the protocol stack. This process requires an established connection at the data link layer and compliance with specific security standards.
The GAP SMP allows two devices to encrypt their communication at the data link layer by setting appropriate security levels, as specified in the SMP chapter of the Bluetooth Core Specification. Before detailing the implementation of GAP SMP, the following key concepts should be clarified:
- **Pairing:** The process in which two devices establish a connection with a defined security level.
- **Bonding:** The process in which at least one device sends security-related information (such as Long-Term Key (LTK), Connection Signature Resolving Key (CSRK), or Identity Resolving Key (IRK)) for future connections. If bonding occurs, key distribution follows pairing. However, bonding is not required for pairing. During pairing, devices exchange characteristics to determine if they support bonding. If neither device supports bonding, no security information is stored.
- **Authentication:** This process verifies the identity of a connected device, ensuring that it is not a third-party attacker. A de-authentication link does not automatically indicate that the connection is insecure. When both devices confirm the security attributes of the link encryption key, they are considered authenticated.
During pairing, the Short-Term Key (STK) authentication generates a keyword. For devices with input/output and Out-of-Band (OOB) functions, all generated and exchanged keys possess Man-in-the-Middle (MITM) protection attributes. In this case, larger PINs or OOB keys enhance security. Conversely, if the Just Works method is employed, the generated and exchanged keys lack MITM protection.
- **Authorization:** The process of granting permission to perform certain operations at the application layer. Some applications require explicit authorization before use. If permission is not granted, the operation fails.
Bluetooth LE Encryption
--------------------------
Encryption in Bluetooth LE can be achieved in two ways:
- **Initial Encryption (No Bonding):** If two Bluetooth LE devices have not bonded, encryption occurs during the pairing process. The decision to bond or not depends on the pairing configuration.
- **Reconnection Encryption (Bonding):** If two devices have bonded, encryption is initiated using previously exchanged keys. In this case, one device triggers encryption by reusing stored keys from the bonding process.
The flowchart below illustrates how a master device initiates an encryption request in Just Works mode (*click to enlarge*):
.. seqdiag::
:caption: The Flowchart of Encryption in Just Works Mode
:align: center
:scale: 200%
seqdiag just-works-encrypt {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 14;
"Input\n[Master]";
"API\n[Master]";
"SMP\n[Master]";
"SMP\n[Slave]";
"API\n[Slave]";
"Output\n[Slave]";
"Input\n[Master]" -> "API\n[Master]" [label="esp_ble_set_encryption"];
"API\n[Master]" -> "SMP\n[Master]";
"SMP\n[Master]" -> "SMP\n[Slave]" [label="smp_pair_req"];
"SMP\n[Slave]" -> "API\n[Slave]";
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_sec_req_evt"];
"API\n[Slave]" <- "Output\n[Slave]" [label="esp_ble_gap_security_rsp"];
"SMP\n[Slave]" <- "API\n[Slave]";
"SMP\n[Master]" <- "SMP\n[Slave]" [label="smp_pair_rsq"];
"SMP\n[Master]" -> "SMP\n[Slave]" [label="[ENCRYPT]", color=blue];
"SMP\n[Master]" <- "SMP\n[Slave]" [label="[ENCRYPT]", color=blue];
"API\n[Master]" <- "SMP\n[Master]";
"SMP\n[Slave]" -> "API\n[Slave]";
"Input\n[Master]" <- "API\n[Master]" [label="esp_gap_ble_auth_cmpl_evt"];
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_auth_cmpl_evt"];
}
The flowchart below illustrates how a master device initiates an encryption request in Passkey Entry mode (*click to enlarge*):
.. seqdiag::
:caption: The Flowchart of Encryption in Passkey Entry Mode
:align: center
:scale: 200%
seqdiag passkey-entry-encrypt {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 14;
"Input\n[Master]";
"API\n[Master]";
"SMP\n[Master]";
"SMP\n[Slave]";
"API\n[Slave]";
"Output\n[Slave]";
"Input\n[Master]" -> "API\n[Master]" [label="esp_ble_set_encryption"];
"API\n[Master]" -> "SMP\n[Master]";
"SMP\n[Master]" -> "SMP\n[Slave]" [label="smp_pair_req"];
"SMP\n[Slave]" -> "API\n[Slave]";
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_sec_req_evt"];
"API\n[Slave]" <- "Output\n[Slave]" [label="esp_ble_gap_security_rsp"];
"SMP\n[Slave]" <- "API\n[Slave]";
"SMP\n[Master]" <- "SMP\n[Slave]" [label="smp_pair_rsq"];
"Input\n[Master]" <- "API\n[Master]" [label="esp_gap_ble_passkey_notify_evt displays the passkey to the user, the peer device should enter this key and send it to the SMP stack"];
"API\n[Slave]" <- "Output\n[Slave]" [label="esp_ble_passkey_reply send the passkey to the SMP stack which is displayed in the peer device"];
"SMP\n[Master]" -> "SMP\n[Slave]" [label="[ENCRYPT]", color=blue];
"SMP\n[Master]" <- "SMP\n[Slave]" [label="[ENCRYPT]", color=blue];
"API\n[Master]" <- "SMP\n[Master]";
"SMP\n[Slave]" -> "API\n[Slave]";
"Input\n[Master]" <- "API\n[Master]" [label="esp_gap_ble_auth_cmpl_evt"];
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_auth_cmpl_evt"];
}
Bluetooth LE Bonding
----------------------
Bonding between two Bluetooth LE devices is achieved via a GAP API call. According to the Bluetooth Core Specification, the purpose of bonding is to enable two Bluetooth LE devices, once encrypted by SMP, to use the same keys for link encryption when reconnecting. This process simplifies reconnection. During pairing, the devices exchange encryption keys and store them for long-term use.
The bonding process is illustrated in the following flowchart (*click to enlarge*):
.. seqdiag::
:caption: The Flowchart of Bluetooth LE Bonding Process
:align: center
:scale: 200%
seqdiag ble_bonding {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 14;
"Input\n[Master]";
"API\n[Master]";
"SMP\n[Master]";
"LLC\n[Master]";
"LLC\n[Slave]";
"SMP\n[Slave]";
"API\n[Slave]";
"Output\n[Slave]";
"Input\n[Master]" -> "API\n[Master]" [label="esp_ble_set_encryption"];
"API\n[Master]" -> "SMP\n[Master]" [label="continues if bonding is completed with the peer device"];
"SMP\n[Master]" -> "LLC\n[Master]" [label="llc_start_enc_cmd"];
"LLC\n[Master]" -> "LLC\n[Slave]";
"LLC\n[Slave]" -> "SMP\n[Slave]" [label="llc_ltk_req_evt"];
"LLC\n[Slave]" <- "SMP\n[Slave]" [label="llc_ltk_req_reply_cmd"];
"LLC\n[Master]" -> "LLC\n[Slave]" [label="[ENCRYPT]", color=blue];
"LLC\n[Master]" <- "LLC\n[Slave]" [label="[ENCRYPT]", color=blue];
"SMP\n[Master]" <- "LLC\n[Master]" [label="llc_enc_change_evt"];
"LLC\n[Slave]" -> "SMP\n[Slave]" [label="llc_enc_change_evt"];
"API\n[Master]" <- "SMP\n[Master]";
"SMP\n[Slave]" -> "API\n[Slave]";
"Input\n[Master]" <- "API\n[Master]" [label="esp_gap_ble_auth_cmpl_evt"];
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_auth_cmpl_evt"];
}
.. note::
Bonding must be initiated by the master device after a connection has been established.
Implementation of SMP
----------------------------
The Bluetooth LE SMP calls encryption APIs in Bluetooth LE GAP, registers the Bluetooth LE GAP callbacks, and obtains the current encryption status through the return values of events.

View File

@@ -0,0 +1,11 @@
##################################
Bluetooth\ :sup:`®` Architecture
##################################
:link_to_translation:`zh_CN:[中文]`
.. toctree::
:maxdepth: 2
overview

View File

@@ -0,0 +1,174 @@
Overview
=============
:link_to_translation:`zh_CN:[中文]`
Bluetooth\ :sup:`®` wireless technology is a short-range communication standard known for its reliability, low power consumption, and cost efficiency. It is categorized into two primary types:
- **Bluetooth Classic:** Optimized for continuous, high-throughput data streaming, suitable for applications like audio transmission.
- **Bluetooth Low Energy (Bluetooth LE):** Designed for low-power, intermittent data transmission, ideal for devices such as sensors and wearables.
.. only:: esp32
{IDF_TARGET_NAME} supports dual-mode Bluetooth, enabling both Bluetooth Classic and Bluetooth LE functionalities.
Bluetooth Protocol Stack
=============================
The Bluetooth protocol stack is a layered communication architecture that defines how Bluetooth devices discover each other, establish connections, exchange data, and ensure secure and reliable communication. As shown in Figure :ref:`bluetooth-core-system-architecture`, The stack consists of two main parts: the Controller Stack and the Host Stack, which communicate via the HCI (Host Controller Interface).
.. _bluetooth-core-system-architecture:
.. figure:: ../../../_static/bluetooth-core-system-architecture.png
:align: center
:width: 80%
:alt: Bluetooth Core System Architecture
Bluetooth Core System Architecture (Source: Bluetooth Core Specification)
**Controller Stack**
The Controller Stack manages hardware-level operations and low-level link control. It includes:
- **PHY (Physical Layer):** Handles transmission and reception of Bluetooth signals in the 2.4 GHz ISM band.
- **Baseband:** Manages low-level timing and control functions, including frequency hopping, packet formatting, and error correction.
- **Link Controller:** Handles state machine operations for device connection and disconnection, flow control, and retransmissions.
- **Link Manager:** Manages link setup, authentication, encryption, and power control.
- **Device Manager:** Oversees device states, handles paging and inquiry processes, and manages stored link keys for security.
**Host Stack**
The Host Stack implements high-level protocols for application interaction. It includes:
- **L2CAP (Logical Link Control and Adaptation Protocol):** Handles data segmentation, reassembly, and multiplexing.
- **SMP (Security Manager Protocol):** Manages authentication, encryption, and secure pairing.
- **GAP (Generic Access Profile):** Manages device discovery, connection establishment, and defines roles and modes for Bluetooth devices.
- **ATT/GATT (Attribute Protocol/Generic Attribute Profile):** Implements attribute-based data exchange through services and characteristics, primarily in Bluetooth LE.
- **SDP (Service Discovery Protocol):** Allows devices to advertise and explore available services, mainly used in Bluetooth Classic.
.. only:: esp32
The Bluetooth Host and Controller can be implemented on the same device or on separate devices. {IDF_TARGET_NAME} supports both approaches. Figure :ref:`bt-host-controller-structure` illustrates typical application structures.
.. _bt-host-controller-structure:
.. figure:: ../../../_static/bt-host-controller-structure.png
:align: center
:width: 70%
:alt: {IDF_TARGET_NAME} Bluetooth Host and Controller Structure
{IDF_TARGET_NAME} Bluetooth Host and Controller Structure
- **Scenario 1 (Default ESP-IDF setting)**
Bluedroid is used as the Bluetooth Host, and VHCI (software-implemented virtual HCI) facilitates communication between the Host and Controller. Both the Bluedroid and Controller run on the same device (i.e., the {IDF_TARGET_NAME} chip), eliminating the need for an external Host device.
- **Scenario 2 (Controller-Only Mode)**
The {IDF_TARGET_NAME} operates exclusively as a Bluetooth Controller. An external Host device (such as a Linux PC with BlueZ or an Android device with Bluedroid) manages Bluetooth operations.
- **Scenario 3 (Testing/Certification)**
Similar to Scenario 2, but used for Bluetooth Qualification Body (BQB) controller testing or certification. The {IDF_TARGET_NAME} chip is connected to test tools via UART.
Bluetooth Operating Environment
===================================
The ESP-IDF Bluetooth implementation operates within a FreeRTOS environment, where Bluetooth tasks are assigned based on function and priority. Controller tasks have the highest priority due to their real-time requirements, except for certain inter-process communication (IPC) tasks that coordinate operations between CPU cores.
.. only:: esp32
On {IDF_TARGET_NAME}, which operates on a dual-core FreeRTOS system, Controller tasks have the highest priority, second only to IPC tasks that manage communication between the two CPU cores. The default Bluetooth Host, Bluedroid, consists of three tasks: BTC, BTU, and HCI.
Bluedroid
==============
ESP-Bluedroid is a modified version of Androids Bluedroid stack, supporting both Bluetooth Classic and Bluetooth LE. It consists of two layers:
- **Bluetooth Upper Layer (BTU):** Implements core protocols (L2CAP, GATT, SMP, etc.).
- **Bluetooth Transport Controller Layer (BTC):** Provides application-level APIs and manages profiles.
**Use Case:** Recommended for applications requiring both Bluetooth Classic and Bluetooth LE.
OS Adaptation
-----------------
Bluedroid integrates with FreeRTOS by adapting system-related functions:
- **Timer (Alarm):** FreeRTOS Timer has been packaged as an Alarm, and is used to start the timer which triggers certain tasks.
- **Task (Thread):** FreeRTOS Task replaces POSIX Thread, and uses FreeRTOS Queue to trigger tasks (i.e., wake up).
- **Future Await/Ready (Semaphore):** ``xSemaphoreTake`` is packaged as ``future_await``, and ``xSemaphoreGive`` as ``future_ready``. These functions must not be called within the same task context.
- **Allocator (malloc/free):** ``malloc/free`` in the standard library is packaged as the ``Allocator`` function that reserves (mallocs) or frees memory.
Bluedroid Directory Structure
---------------------------------
The ESP-IDF directory *component/bt/host/bluedroid* contains the following sub-folders:
.. code-block:: text
├── api
├── bta
├── btc
├── common/include/common
├── config
├── device
├── external/sbc
├── hci
├── main
├── stack
└── Kconfig.in
The detailed description of each sub-folder can be found in the table below:
.. list-table:: Description of *component/bt/host/bluedroid* in ESP-IDF
:header-rows: 1
:widths: 20 80
* - **Sub-folder**
- **Description**
* - *api*
- The API directory, which includes all the APIs (except for those that are related to the Controller).
* - *bta*
- The Bluetooth adaptation layer, which is suitable for the interface of some bottom layer protocols in the host.
* - *btc*
- The Bluetooth control layer, which controls the upper-layer protocols (including profiles) and miscellaneous items in the host.
* - *common*
- Common header file for the protocol stack.
* - *config*
- Configure some parameters for the protocol stack.
* - *device*
- Related to the device control of the Controller, e.g., the basic set of HCI CMD controller processes.
* - *external*
- Codes that are not directly related to the Bluetooth, but are still usable, e.g., the SBC codec software programs.
* - *hci*
- HCI layer protocols.
* - *main*
- Main program (mainly to start or halt the process).
* - *stack*
- The bottom layer protocol stacks in the Host (GAP/ ATT/ GATT/ SDP/ SMP, etc.).
* - *Kconfig.in*
- Menuconfig files.

View File

@@ -4,10 +4,9 @@ Bluetooth\ :sup:`®` Classic
:link_to_translation:`zh_CN:[中文]`
*********
Overview
*********
.. toctree::
:maxdepth: 2
overview
profiles-protocols

View File

@@ -1,4 +1,4 @@
Introduction
Overview
=============
:link_to_translation:`zh_CN:[中文]`
@@ -9,7 +9,7 @@ This document provides an architecture overview of the Bluetooth Classic stack i
{IDF_TARGET_NAME} supports Dual-Mode Bluetooth 4.2.
The Bluetooth Classic stack in ESP-IDF is a layered architecture that enables Bluetooth functionality on {IDF_TARGET_NAME} chip series. The table below shows its architecture.
The Bluetooth Classic stack in ESP-IDF is a layered architecture that enables Bluetooth functionality on {IDF_TARGET_NAME} chip series. The figure below shows its architecture.
.. only:: esp32
@@ -20,29 +20,6 @@ The Bluetooth Classic stack in ESP-IDF is a layered architecture that enables Bl
{IDF_TARGET_NAME} Bluetooth Classic Stack Architecture
The table below shows whether the Bluetooth Classic Controller are supported in a specific chip series.
.. list-table::
:width: 100%
:widths: auto
:header-rows: 1
* - Chip Series
- Controller
* - ESP32
- Y
* - ESP32-S2
- \
* - ESP32-S3
- \
* - ESP32-C2
- \
* - ESP32-C3
- \-
* - ESP32-C6
- \-
* - ESP32-H2
- \-
The following sections briefly describe each layer and provide quick links to the related documents and application examples.

View File

@@ -0,0 +1,103 @@
Profiles and Protocols
========================
:link_to_translation:`zh_CN:[中文]`
Protocols define message formats and procedures to accomplish specific functions, e.g., data transportation, link control, security service, and service information exchange. Bluetooth profiles, on the other hand, define the functions and features required of each layer in the Bluetooth system, from PHY to L2CAP, and any other protocols outside the core specification.
Below are the supported Bluetooth Classic protocols and profiles in ESP-Bluedroid:
- Protocols: L2CAP, SDP, AVDTP, AVCTP, RFCOMM
- Profiles: GAP, A2DP, AVRCP, SPP, HFP
The protocol model is depicted in Figure :ref:`bluetooth-protocol-model`.
.. _bluetooth-protocol-model:
.. figure:: ../../../_static/bluetooth-protocol-model.png
:align: center
:width: 60%
:alt: Bluetooth Protocol Model
Bluetooth Protocol Model
In Figure :ref:`bluetooth-protocol-model`, L2CAP and SDP are necessary in a minimal Host Stack for Bluetooth Classic. AVDTP, AV/C, and AVCTP are outside the core specification and are used by specific profiles.
L2CAP
--------
The Bluetooth Logical Link Control and Adaptation Protocol (L2CAP) is an OSI layer 2 protocol that supports higher-level protocol multiplexing, packet segmentation, and reassembly, as well as the delivery of service information quality. L2CAP makes it possible for different applications to share an ACL-U logical link. Applications and service protocols interface with L2CAP, using a channel-oriented interface, to create connections to equivalent entities on other devices.
L2CAP channels operate in one of the six modes selected through the L2CAP channel configuration procedure. The operation modes are distinguished from the QoS that they can provide, and are utilized in different application conditions. These modes are:
- Basic L2CAP Mode
- Flow Control Mode
- Retransmission Mode
- Enhanced Retransmission Mode
- Streaming Mode
- LE Credit-Based Flow Control Mode
For ACL-U logical links, the supported operation modes are the Basic L2CAP Mode, Enhanced Retransmission Mode and Streaming Mode. For other features, the L2CAP Signaling channel is the supported fixed channel, while the Frame Check Sequence (FCS) is also a supported option.
SDP
--------
The Service Discovery Protocol (SDP) provides a means for applications to discover services offered by a peer Bluetooth device, as well as to determine the characteristics of the available services. The SDP involves communication between an SDP server and an SDP client. A server maintains a list of service records that describe the characteristics of services associated with the server. A client can retrieve this information by issuing an SDP request.
GAP
--------
The Generic Access Profile (GAP) provides a description of the modes and procedures in device discoverability, connection and security.
A2DP and AVRCP
----------------
The Advanced Audio Distribution Profile (A2DP) defines the protocols and procedures that realize the distribution of high-quality audio content in mono or stereo on ACL channels. A2DP handles audio streaming and is often used together with the Audio/Video Remote Control Profile (AVRCP), which includes the audio/video control functions. Figure :ref:`profile-dependencies` depicts the structure and dependencies of the profiles:
.. _profile-dependencies:
.. figure:: ../../../_static/profile-dependencies.png
:align: center
:width: 50%
:alt: Profile Dependencies
Profile Dependencies
As indicated in Figure :ref:`profile-dependencies`, the A2DP is dependent upon GAP, as well as the Generic Audio/Video Distribution Profile (GAVDP), which defines procedures required to set up an audio/video streaming.
A2DP defines two roles: Source (SRC) and Sink (SNK). SRC functions as a source of a digital audio stream and SNK functions as a sink of a digital audio stream delivered from the SRC.
Similarly, AVRCP defines two roles: Controller (CT) and Target (TG). CT is a device that initiates a transaction by sending a command frame to a target. Examples of CT include personal computers, PDAs, and mobile phones. TG is a device that receives a command frame and accordingly generates a response frame. Audio players or headphones are examples of TG.
In the current A2DP solution, the only audio codec supported is SBC, which is mandated in the A2DP specification. A2DP Version 1.4 and AVDTP Version 1.3 are implemented.
Audio/Video Distribution Transport Protocol (AVDTP) defines the binary transactions between Bluetooth devices for a streaming set-up, and media streaming for audio and video using L2CAP. As the basic transport protocol for A2DP, AVDTP is built upon the L2CAP layer and consists of a signaling entity for negotiating streaming parameters and a transport entity that handles the streaming itself.
The basic service of AVDTP transport capabilities is mandated by the A2DP specification. According to the configuration of current service capabilities, Media Transport and Media Codec in the basic service capability are provided.
AVRCP defines the requirements necessary for the support of the Audio/Video remote control use case. The commands used in AVRCP fall into three main categories:
- **AV/C Digital Interface Command Set:** Applied only on certain occasions and transported with the Audio/Video Control Transport Protocol (AVCTP).
- **Browsing commands:** Provides browsing functionality over another transport channel called the AVCTP browsing channel.
- **Cover Art Commands:** Used to transmit images associated with media items, and is provided through the protocol defined in the Bluetooth Basic Imaging Profile (BIP) with the OBEX protocol.
AVRCP uses two sets of AV/C commands. The first set includes the PASS THROUGH command, UNIT INFO command, and SUBUNIT INFO command, as defined in the AV/C specification. The second set consists of AVRCP-specific AV/C commands, which are defined as a Bluetooth SIG Vendor-Dependent extension.
AV/C commands are transmitted over the AVCTP control channel. The PASS THROUGH command transfers user operations from the Controller to the panel subunit via button presses, providing a straightforward mechanism for controlling the target device. For example, the operation IDs in PASS THROUGH include common commands such as Play, Pause, Stop, Volume Up, and Volume Down.
AVRCP arranges the A/V functions in four categories to ensure interoperability:
- Player/ Recorder
- Monitor/ Amplifier
- Tuner
- Menu
In the current implementation, AVRCP Version 1.6 and AVCTP Version 1.4 are provided. The default configuration for AVRCP-supported features is Category 2: Monitor/ Amplifier. Also, APIs for sending PASS THROUGH commands are provided.
A2DP and AVRCP are often used together. In the current solution, the lower Host stack implements AVDTP and the AVCTP logic, while providing interfaces for A2DP and AVRCP independently. In the upper layer of the stack, however, the two profiles combined make up the "AV" module. The BTA layer, for example, provides a unified "AV" interface, and in BTC layer there is a state machine that handles the events for both profiles. The APIs, however, are provided separately for A2DP and AVRCP.

View File

@@ -7,6 +7,7 @@ API Guides
app_trace
startup
:SOC_BT_SUPPORTED: bt-architecture/index
:SOC_BT_CLASSIC_SUPPORTED: classic-bt/index
:SOC_BLE_SUPPORTED: ble/index
:SOC_BLE_MESH_SUPPORTED: esp-ble-mesh/ble-mesh-index

View File

@@ -3,7 +3,7 @@
:link_to_translation:`en:[English]`
本文档为低功耗蓝牙 (Bluetooth Low Energy, Bluetooth LE) 入门教程其三,旨在对 Bluetooth LE 的连接过程进行简要介绍。随后,本教程会结合 NimBLE_Connection 例程,基于 NimBLE 主机层协议栈,对外围设备的代码实现进行介绍。
本文档为低功耗蓝牙 (Bluetooth LE) 入门教程其三,旨在对低功耗蓝牙的连接过程进行简要介绍。随后,本教程会结合 NimBLE_Connection 例程,基于 NimBLE 主机层协议栈,对外围设备的代码实现进行介绍。
学习目标
@@ -21,7 +21,7 @@
连接的发起
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*在 Bluetooth LE 5.0 引入扩展广播特性以后, Legacy ADV 和 Extended ADV 对应的连接建立过程略有差异,下以 Legacy ADV 对应的连接建立过程为例。*
*在蓝牙核心规范 5.0 引入扩展广播特性以后, Legacy ADV 和 Extended ADV 对应的连接建立过程略有差异,下以 Legacy ADV 对应的连接建立过程为例。*
当扫描者在某一个广播信道接收到一个广播数据包时,若该广播者是可连接的,那么扫描者可以在同一广播信道发送连接请求 (Connection Request)。对于广播者来说,它可以设置 *接受列表 (Filter Accept List)* 以过滤不受信任的设备,或接受任一扫描者的连接请求。随后,广播者转变为外围设备,扫描者转变为中央设备,两者之间可以在数据信道进行双向通信。
@@ -101,7 +101,7 @@
* - 2
- 有效负载 (Payload)
- 0-27 / 0-251
- 在 Bluetooth LE 4.2 以前,有效负载最大值为 27 字节; Bluetooth LE 4.2 引入了数据长度扩展 (Data Length Extension, DLE) 特性,有效负载的最大值可达 251 字节
- 在蓝牙核心规范 4.2 以前,有效负载最大值为 27 字节; 蓝牙核心规范 4.2 引入了数据长度扩展 (Data Length Extension, DLE) 特性,有效负载的最大值可达 251 字节
* - 3
- 消息完整性检查 (Message Integrity Check, MIC)
- 4
@@ -124,9 +124,9 @@
- ATT 数据 (ATT Header + ATT Data)
- 0-23 / 0-247
MTU 的默认值为 23 字节,恰为 Bluetooth LE 4.2 之前单个数据 PDU 的最大可承载 ATT 数据字节数。
MTU 的默认值为 23 字节,恰为蓝牙核心规范 4.2 之前单个数据 PDU 的最大可承载 ATT 数据字节数。
MTU 可以设定为更大的值,例如 140 字节。在 Bluetooth LE 4.2 以前,由于有效负载中最多只有 23 字节可以承载 ATT 数据,所以必须将完整的一包 ATT 数据包拆分成若干份,分散到多个数据 PDU 中。在 Bluetooth LE 4.2 以后,单个数据 PDU 最多可以承载 247 字节 ATT 数据,所以 MTU 为 140 字节时仍然可以使用单个数据 PDU 承载。
MTU 可以设定为更大的值,例如 140 字节。在蓝牙核心规范 4.2 以前,由于有效负载中最多只有 23 字节可以承载 ATT 数据,所以必须将完整的一包 ATT 数据包拆分成若干份,分散到多个数据 PDU 中。在蓝牙核心规范 4.2 以后,单个数据 PDU 最多可以承载 247 字节 ATT 数据,所以 MTU 为 140 字节时仍然可以使用单个数据 PDU 承载。
例程实践
@@ -472,6 +472,6 @@ GAP 事件处理
总结
----------------
通过本教程,你了解了连接的基本概念,并通过 :example:`NimBLE_Connection <bluetooth/ble_get_started/nimble/NimBLE_Connection>` 例程掌握了使用 NimBLE 主机层协议栈构建 Bluetooth LE 外围设备的方法。
通过本教程,你了解了连接的基本概念,并通过 :example:`NimBLE_Connection <bluetooth/ble_get_started/nimble/NimBLE_Connection>` 例程掌握了使用 NimBLE 主机层协议栈构建低功耗蓝牙外围设备的方法。
你可以尝试对例程中的参数进行修改,并在日志输出中观察修改结果。例如,你可以修改外围设备延迟或连接超时参数,观察连接参数的修改是否能够触发连接更新事件。

View File

@@ -3,7 +3,7 @@
:link_to_translation:`en:[English]`
本文档为低功耗蓝牙 (Bluetooth Low Energy, Bluetooth LE) 入门教程其四,旨在对 Bluetooth LE 连接中的数据交换过程进行简要介绍。随后,本教程会结合 :example:`NimBLE_GATT_Server <bluetooth/ble_get_started/nimble/NimBLE_GATT_Server>` 例程,基于 NimBLE 主机层协议栈,对 GATT 服务器的代码实现进行介绍。
本文档为低功耗蓝牙 (Bluetooth LE) 入门教程其四,旨在对低功耗蓝牙连接中的数据交换过程进行简要介绍。随后,本教程会结合 :example:`NimBLE_GATT_Server <bluetooth/ble_get_started/nimble/NimBLE_GATT_Server>` 例程,基于 NimBLE 主机层协议栈,对 GATT 服务器的代码实现进行介绍。
学习目标
@@ -17,7 +17,7 @@
GATT 数据特征与服务
----------------------------------
GATT 服务是 Bluetooth LE 连接中两个设备进行数据交换的基础设施,其最小数据单元是属性。在 :ref:`数据表示与交换 <gatt_att_introduction>` 中,我们对 ATT 层的属性以及 GATT 层的特征数据、服务与规范进行了简要介绍。下面我们对基于属性的数据结构细节进行说明。
GATT 服务是低功耗蓝牙连接中两个设备进行数据交换的基础设施,其最小数据单元是属性。在 :ref:`数据表示与交换 <gatt_att_introduction>` 中,我们对 ATT 层的属性以及 GATT 层的特征数据、服务与规范进行了简要介绍。下面我们对基于属性的数据结构细节进行说明。
属性
@@ -46,7 +46,7 @@ GATT 服务是 Bluetooth LE 连接中两个设备进行数据交换的基础设
- 值
- 实际用户数据或另一属性的元数据
Bluetooth LE 中存在两种类型的 UUID ,如下
低功耗蓝牙中存在两种类型的 UUID ,如下
1. SIG 定义的 16 位 UUID
2. 厂商自定义的 128 位 UUID
@@ -74,7 +74,7 @@ Bluetooth LE 中存在两种类型的 UUID ,如下
- 外观 (Appearance)
- `0x2A01`
事实上,这些服务和特征数据的定义也由 SIG 一并给出。例如心率测量值 (Heart Rate Measurement) 的值中必须含有标志位、心率测量值场,可以含有能量拓展场、 RR-间隔场以及传输间隔场等。所以,使用 SIG 定义的 UUID 使得不同厂商的 Bluetooth LE 设备之间可以识别对方的服务或特征数据,实现跨厂商的 Bluetooth LE 设备通信。
事实上,这些服务和特征数据的定义也由 SIG 一并给出。例如心率测量值 (Heart Rate Measurement) 的值中必须含有标志位、心率测量值场,可以含有能量拓展场、 RR-间隔场以及传输间隔场等。所以,使用 SIG 定义的 UUID 使得不同厂商的低功耗蓝牙设备之间可以识别对方的服务或特征数据,实现跨厂商的低功耗蓝牙设备通信。
厂商自定义的 128 位 UUID 则用于满足厂商开发私有服务或数据特征的需求,例如本例程中 LED 特征数据的 UUID 为 `0x00001525-1212-EFDE-1523-785FEABCD123`,是一个厂商自定义的 128 位 UUID 。

View File

@@ -3,7 +3,7 @@
:link_to_translation:`en:[English]`
本文档为低功耗蓝牙 (Bluetooth Low Energy, Bluetooth LE) 入门教程其二,旨在对 Bluetooth LE 设备发现过程进行简要介绍,包括广播与扫描相关的基本概念。随后,本教程会结合 :example:`NimBLE_Beacon <bluetooth/ble_get_started/nimble/NimBLE_Beacon>` 例程,基于 NimBLE 主机层协议栈,对 Bluetooth LE 广播的代码实现进行介绍。
本文档为低功耗蓝牙 (Bluetooth LE) 入门教程其二,旨在对低功耗蓝牙设备发现过程进行简要介绍,包括广播与扫描相关的基本概念。随后,本教程会结合 :example:`NimBLE_Beacon <bluetooth/ble_get_started/nimble/NimBLE_Beacon>` 例程,基于 NimBLE 主机层协议栈,对低功耗蓝牙广播的代码实现进行介绍。
学习目标
@@ -14,7 +14,7 @@
- 学习 :example:`NimBLE_Beacon <bluetooth/ble_get_started/nimble/NimBLE_Beacon>` 例程的代码结构
广播 (Advertising) 与扫描 (Scanning) 是 Bluetooth LE 设备在进入连接前在设备发现 (Device Discovery) 阶段的工作状态。下面,我们先了解与广播有关的基本概念。
广播 (Advertising) 与扫描 (Scanning) 是低功耗蓝牙设备在进入连接前在设备发现 (Device Discovery) 阶段的工作状态。下面,我们先了解与广播有关的基本概念。
广播的基本概念
@@ -39,9 +39,9 @@
蓝牙信道
#######################################
与经典蓝牙相同,蓝牙技术联盟为了解决数据冲突的问题,在 Bluetooth LE 上也应用了自适应跳频技术 (Adaptive Frequency Hopping, AFH) ,该技术可以判断 RF 信道的拥挤程度,通过跳频避开拥挤的 RF 信道,以提高通信质量。不过 Bluetooth LE 与经典蓝牙的不同之处在于,所使用的 2.4 GHz ISM 频段被划分为 40 个 2 MHz 带宽的射频 (Radio Frequency, RF) 信道,中心频率范围为 2402 MHz - 2480 MHz ,而经典蓝牙则是将这一频段划分为 79 个 1MHz 带宽的 RF 信道。
与经典蓝牙相同,蓝牙技术联盟为了解决数据冲突的问题,在低功耗蓝牙上也应用了自适应跳频技术 (Adaptive Frequency Hopping, AFH) ,该技术可以判断 RF 信道的拥挤程度,通过跳频避开拥挤的 RF 信道,以提高通信质量。不过低功耗蓝牙与经典蓝牙的不同之处在于,所使用的 2.4 GHz ISM 频段被划分为 40 个 2 MHz 带宽的射频 (Radio Frequency, RF) 信道,中心频率范围为 2402 MHz - 2480 MHz ,而经典蓝牙则是将这一频段划分为 79 个 1MHz 带宽的 RF 信道。
Bluetooth LE 4.2 标准中, RF 信道分为两种类型,如下
蓝牙核心规范 4.2 (Bluetooth Core Specification 4.2) 中, RF 信道分为两种类型,如下
.. list-table::
:align: center
@@ -67,7 +67,7 @@
扩展广播特性
################################
Bluetooth LE 4.2 标准中,广播数据包允许搭载最多 31 字节广播数据,这无疑限制了广播的功能。为了提高广播的可用性,蓝牙 5.0 标准引入了 扩展广播 (Extended Advertising) 特性,这一特性将广播数据包分为
蓝牙核心规范 4.2 中,广播数据包允许搭载最多 31 字节广播数据,这无疑限制了广播的功能。为了提高广播的可用性,蓝牙 5.0 标准引入了 扩展广播 (Extended Advertising) 特性,这一特性将广播数据包分为
.. list-table::
:align: center
@@ -124,7 +124,7 @@ Bluetooth LE 4.2 标准中,广播数据包允许搭载最多 31 字节广播
广播数据包结构
##########################
对于第三个问题,即广播数据包内含有什么信息,在 Bluetooth LE 4.2 标准给出了广播数据包的格式定义,如下图所示
对于第三个问题,即广播数据包内含有什么信息,在蓝牙核心规范 4.2 给出了广播数据包的格式定义,如下图所示
.. _adv_packet_structure:
@@ -134,7 +134,7 @@ Bluetooth LE 4.2 标准中,广播数据包允许搭载最多 31 字节广播
:scale: 35%
:alt: 广播数据包结构
Bluetooth LE 4.2 广播数据包结构
蓝牙核心规范 4.2 广播数据包结构
看起来非常复杂,让我们来逐层分解。广播数据包的最外层包含四个部分,分别是
@@ -336,7 +336,7 @@ PDU 有效负载也分为两部分
* - 不可解析随机私有地址 (Non-resolvable Random Private Address)
- 完全随机的地址,仅用于防止设备被追踪,非常少用
然后看**广播数据**。一个广播数据结构的格式定义如下
然后看广播数据。一个广播数据结构的格式定义如下
.. list-table::
:align: center
@@ -361,6 +361,148 @@ PDU 有效负载也分为两部分
-
广播流程
^^^^^^^^^
使用公共地址进行广播
########################
使用公共地址进行广播时,需要将 ``esp_ble_adv_params_t`` 成员 ``own_addr_type`` 设置为 ``BLE_ADDR_TYPE_PUBLIC``。广播流程图如下 *点击图片放大*
.. seqdiag::
:caption: 广播流程图——使用公共地址
:align: center
:scale: 200%
seqdiag adv-public-addr {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 12;
"Input\n[Advertiser]";
"API\n[Advertiser]";
"LLM\n[Advertiser]";
"LLM\n[Scanner]";
"API\n[Scanner]";
"Output\n[Scanner]";
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_set_device_name"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_config_adv_data"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends config adv data HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns set adv data event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_data_set_complete_evt"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_start_advertising to start advertising; sets the own_addr_type parameter to ble_addr_type_public"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends start adv HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns start adv event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_start_complete_evt"];
"LLM\n[Scanner]" -> "API\n[Scanner]";
"API\n[Scanner]" -> "Output\n[Scanner]" [label="esp_gap_ble_scan_result_evt"];
}
使用可解析随机私有地址进行广播
##################################
使用可解析随机私有地址进行广播时,底层协议栈在可解析随机私有地址超时时更新广播地址,默认超时设置为 15 分钟。可解析随机私有地址的超时时间可以通过 menuconfig 中的 ``BT_BLE_RPA_TIMEOUT`` 选项进行配置。需要将 ``esp_ble_adv_params_t`` 成员 ``own_addr_type`` 设置为 ``BLE_ADDR_TYPE_RPA_PUBLIC````BLE_ADDR_TYPE_RPA_RANDOM``。广播流程图如下 *点击图片放大*
.. seqdiag::
:caption: 广播流程图——使用可解析随机私有地址
:align: center
:scale: 200%
seqdiag adv-resolvable-addr {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 12;
"Input\n[Advertiser]";
"API\n[Advertiser]";
"LLM\n[Advertiser]";
"LLM\n[Scanner]";
"API\n[Scanner]";
"Output\n[Scanner]";
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_set_device_name"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_config_local_privacy"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_config_adv_data"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends config adv data HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns set adv data event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_data_set_complete_evt"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_start_advertising to start advertising; sets the own_addr_type parameter to ble_addr_type_rpa_public or ble_addr_type_rpa_random"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends start adv HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns start adv event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_start_complete_evt"];
"LLM\n[Scanner]" -> "API\n[Scanner]";
"API\n[Scanner]" -> "Output\n[Scanner]" [label="esp_gap_ble_scan_result_evt"];
}
.. note::
当使用可解析随机私有地址进行广播时,需要等待 ``esp_ble_gap_config_local_privacy`` 事件返回后,才能开始广播,并且需要将广播参数里的 ``own_addr_type`` 类型设置为 ``BLE_ADDR_TYPE_RPA_PUBLIC````BLE_ADDR_TYPE_RPA_RANDOM``
要使用 ``BLE_ADDR_TYPE_RPA_RANDOM`` 地址类型,必须首先通过 API ``esp_ble_gap_set_rand_addr`` 设置一个随机静态地址。如果使用 ``BLE_ADDR_TYPE_RPA_PUBLIC``,则无需设置地址。
``BLE_ADDR_TYPE_RPA_PUBLIC`` 的操作如下:控制器基于解析列表中的本地身份解析密钥 (IRK) 生成可解析随机私有地址 (RPA)。如果解析列表缺乏匹配条目,则使用公共地址。
对于 ``BLE_ADDR_TYPE_RPA_RANDOM``,如果解析列表中没有匹配的条目,则使用随机静态地址。
使用随机静态地址进行广播
#########################
与使用可解析随机私有地址进行广播一样,使用随机静态地址进行广播也需要将 ``esp_ble_adv_params_t`` 成员 ``own_addr_type`` 设置为 ``BLE_ADDR_TYPE_RANDOM``。广播流程图如下 *点击图片放大*
.. seqdiag::
:caption: 广播流程图——使用随机静态地址
:align: center
:scale: 200%
seqdiag adv-random-addr {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 12;
"Input\n[Advertiser]";
"API\n[Advertiser]";
"LLM\n[Advertiser]";
"LLM\n[Scanner]";
"API\n[Scanner]";
"Output\n[Scanner]";
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_set_device_name"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_set_rand_addr"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends set rand address HCI command to LL layer"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns set rand address event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_set_static_rand_addr_evt"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends config adv data HCI command to LL layer"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_config_adv_data"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="return set adv data event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="calls\n esp_gap_ble_adv_data_set_complete_evt"];
"Input\n[Advertiser]" -> "API\n[Advertiser]" [label="calls\n esp_ble_gap_start_advertising to start advertising; sets the own_addr_type parameter to ble_addr_type_random"];
"API\n[Advertiser]" -> "LLM\n[Advertiser]" [label="sends start adv HCI command to LL layer"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"LLM\n[Advertiser]" -> "LLM\n[Scanner]" [label="advertising event"];
"API\n[Advertiser]" <- "LLM\n[Advertiser]" [label="returns start adv event"];
"Input\n[Advertiser]" <- "API\n[Advertiser]" [label="returns\n esp_gap_ble_adv_start_complete_evt"];
"LLM\n[Scanner]" -> "API\n[Scanner]";
"API\n[Scanner]" -> "Output\n[Scanner]" [label="esp_gap_ble_scan_result_evt"];
}
扫描的基本概念
^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -370,8 +512,7 @@ PDU 有效负载也分为两部分
2. 多久扫描一次?一次扫描多久? (When?)
3. 扫描的过程中需要做什么? (What?)
第一个问题已经在广播的介绍中说明了。对于 Bluetooth LE 4.2 设备来说,广播者只会在广播信道,即编号为 37-39 的三个信道发送广播数据;对于 Bluetooth LE 5.0 设备来说,如果广播者启用了扩展广播特性,则会在主广播信道发送 `ADV_EXT_IND` ,在次广播信道发送 `AUX_ADV_IND` ,并在 `ADV_EXT_IND` 指示 `AUX_ADV_IND` 所在的次广播信道。
所以相应的,对于 Bluetooth LE 4.2 设备来说,扫描者只需在广播信道接收广播数据包即可。对于 Bluetooth LE 5.0 设备来说,扫描者应在主广播信道接收主广播数据包和扩展广播数据包的 `ADV_EXT_IND` 若扫描者接收到了 `ADV_EXT_IND` ,且 `ADV_EXT_IND` 指示了一个次广播信道,那么还需要到对应的次广播信道去接收 `AUX_ADV_IND` ,以获取完整的扩展广播数据包。
第一个问题已经在广播的介绍中说明了。对于蓝牙 4.2 设备来说,广播者只会在广播信道,即编号为 37-39 的三个信道发送广播数据;对于蓝牙 5.0 设备来说,如果广播者启用了扩展广播特性,则会在主广播信道发送 `ADV_EXT_IND` ,在次广播信道发送 `AUX_ADV_IND` ,并在 `ADV_EXT_IND` 指示 `AUX_ADV_IND` 所在的次广播信道。所以相应地,对于蓝牙 4.2 设备来说,扫描者只需在广播信道接收广播数据包即可。对于蓝牙 5.0 设备来说,扫描者应在主广播信道接收主广播数据包和扩展广播数据包的 `ADV_EXT_IND` 若扫描者接收到了 `ADV_EXT_IND` ,且 `ADV_EXT_IND` 指示了一个次广播信道,那么还需要到对应的次广播信道去接收 `AUX_ADV_IND` ,以获取完整的扩展广播数据包。
扫描窗口与扫描间隔
@@ -561,7 +702,7 @@ PDU 有效负载也分为两部分
值得一提的是,前五项广播数据结构长度之和为 28 字节,此时广播数据包仅空余 3 字节,无法继续装载后续的两项广播数据结构。所以后两项广播数据结构必须装填至扫描响应数据包。
你可能还注意到,对应于设备外观的 Raw Data 为 `0x0002`,而代码中对 Generic Tag 的定义是 `0x0200`;还有,设备地址的 Raw Data 除了最后一个字节 `0x00` 以外,似乎与实际地址完全颠倒。这是因为, Bluetooth LE 的空中数据包遵循小端 (Little Endian) 传输的顺序,所以低字节的数据反而会在靠前的位置。
你可能还注意到,对应于设备外观的 Raw Data 为 `0x0002`,而代码中对 Generic Tag 的定义是 `0x0200`;还有,设备地址的 Raw Data 除了最后一个字节 `0x00` 以外,似乎与实际地址完全颠倒。这是因为,低功耗蓝牙的空中数据包遵循小端 (Little Endian) 传输的顺序,所以低字节的数据反而会在靠前的位置。
另外,注意到 **nRF Connect for Mobile** 程序并没有为我们提供 **CONNECT** 按钮以连接至此设备。这符合我们的预期,因为 Beacon 设备本来就应该是不可连接的。下面,让我们深入代码细节,看看这样的一个 Beacon 设备是怎样实现的。
@@ -880,6 +1021,6 @@ PDU 有效负载也分为两部分
总结
---------
通过本教程,你了解了广播和扫描的基本概念,并通过 :example:`NimBLE_Beacon <bluetooth/ble_get_started/nimble/NimBLE_Beacon>` 例程掌握了使用 NimBLE 主机层协议栈构建 Bluetooth LE Beacon 设备的方法。
通过本教程,你了解了广播和扫描的基本概念,并通过 :example:`NimBLE_Beacon <bluetooth/ble_get_started/nimble/NimBLE_Beacon>` 例程掌握了使用 NimBLE 主机层协议栈构建低功耗蓝牙 Beacon 设备的方法。
你可以尝试对例程中的数据进行修改,并在 nRF Connect for Mobile 调试工具中查看修改结果。例如,你可以尝试修改 `adv_fields``rsp_fields` 结构体,以修改被填充的广播数据结构,或者交换广播数据包和扫描响应数据包中的广播数据结构。但需要注意的一点是,广播数据包和扫描响应数据包的广播数据上限为 31 字节,若设定的广播数据结构大小超过该限值,调用 `ble_gap_adv_start` API 将会失败。

View File

@@ -3,49 +3,49 @@
:link_to_translation:`en:[English]`
本文档为低功耗蓝牙 (Bluetooth Low Energy, Bluetooth LE) 入门系列教程其一,旨在对 Bluetooth LE 的基本概念进行简要介绍,并引导读者烧录一个完整的 Bluetooth LE 例程至 {IDF_TARGET_NAME} 开发板;随后,指导读者在手机上使用 nRF Connect for Mobile 应用程序,控制开发板上 LED 的开关并读取开发板上随机生成的心率数据。本教程希望帮助读者了解如何使用 ESP-IDF 开发框架对 {IDF_TARGET_NAME} 开发板进行 Bluetooth LE 应用烧录,并通过体验例程功能,对 Bluetooth LE 的功能建立感性认知。
本文档为低功耗蓝牙 (Bluetooth LE) 入门系列教程其一,旨在对低功耗蓝牙的基本概念进行简要介绍,并引导读者烧录一个完整的低功耗蓝牙例程至 {IDF_TARGET_NAME} 开发板;随后,指导读者在手机上使用 nRF Connect for Mobile 应用程序,控制开发板上 LED 的开关并读取开发板上随机生成的心率数据。本教程希望帮助读者了解如何使用 ESP-IDF 开发框架对 {IDF_TARGET_NAME} 开发板进行低功耗蓝牙应用烧录,并通过体验例程功能,对低功耗蓝牙的功能建立感性认知。
学习目标
---------------
- 认识 Bluetooth LE 的分层架构
- 了解 Bluetooth LE 各层基本功能
- 认识低功耗蓝牙的分层架构
- 了解低功耗蓝牙各层基本功能
- 了解 GAP 以及 GATT/ATT 层的功能
- 掌握在 {IDF_TARGET_NAME} 开发板上烧录 Bluetooth LE 例程的方法,并在手机上与之交互
- 掌握在 {IDF_TARGET_NAME} 开发板上烧录低功耗蓝牙例程的方法,并在手机上与之交互
引言
-----------------
大多数人在生活中都接触过蓝牙,可能屏幕前的你现在正佩戴着蓝牙耳机,收听来自手机或电脑的音频。不过,音频传输是经典蓝牙 (Bluetooth Classic) 的典型应用场景,而 Bluetooth LE 是一种与经典蓝牙不兼容的蓝牙通信协议,在蓝牙 4.0 中被引入。顾名思义, Bluetooth LE 是一种功耗非常低的蓝牙协议,通信速率也比经典蓝牙更低一些,其典型应用场景是物联网 (Internet of Things, IoT) 中的数据通信,例如智能开关或智能传感器,这也是本教程中引用的 Bluetooth LE 例程所实现的功能。不过,在体验例程功能以前,让我们来了解一下 Bluetooth LE 的基本概念,以帮助你更好地入门。
大多数人在生活中都接触过蓝牙,可能屏幕前的你现在正佩戴着蓝牙耳机,收听来自手机或电脑的音频。不过,音频传输是经典蓝牙 (Bluetooth Classic) 的典型应用场景,而低功耗蓝牙是一种与经典蓝牙不兼容的蓝牙通信协议,在蓝牙 4.0 中被引入。顾名思义,低功耗蓝牙是一种功耗非常低的蓝牙协议,通信速率也比经典蓝牙更低一些,其典型应用场景是物联网 (Internet of Things, IoT) 中的数据通信,例如智能开关或智能传感器,这也是本教程中引用的低功耗蓝牙例程所实现的功能。不过,在体验例程功能以前,让我们来了解一下低功耗蓝牙的基本概念,以帮助你更好地入门。
Bluetooth LE 的分层架构
低功耗蓝牙的分层架构
-------------------------
Bluetooth LE 协议定义了三层软件结构,自上而下分别是
低功耗蓝牙协议定义了三层软件结构,自上而下分别是
- 应用层 (Application Layer)
- 主机层 (Host Layer)
- 控制器层 (Controller Layer)
应用层即以 Bluetooth LE 为底层通信技术所构建的应用,依赖于主机层向上提供的 API 接口。
应用层即以低功耗蓝牙为底层通信技术所构建的应用,依赖于主机层向上提供的 API 接口。
主机层负责实现 L2CAP、GATT/ATT、SMP、GAP 等底层蓝牙协议,向上对应用层提供 API 接口,向下通过主机控制器接口 (Host Controller Interface, HCI) 与控制器层通信。
控制器层包括物理层 (Physical Layer, PHY) 和链路层 (Link Layer, LL) 两层,向下直接与控制器硬件进行交互,向上通过 HCI 与主机层进行通信。
值得一提的是,蓝牙核心规范 (Core Specification) 允许主机层和控制器层在物理上分离,此时 HCI 体现为物理接口,包括 SDIO、USB 以及 UART 等;当然,主机层和控制器层可以共存于同一芯片,以实现更高的集成度,此时 HCI 体现为逻辑接口,常被称为虚拟主机控制器接口 (Virtual Host Controller Interface, VHCI)。一般认为,主机层和控制器层组成了 Bluetooth LE 协议栈 (Bluetooth LE Stack)。
值得一提的是,蓝牙核心规范 (Core Specification) 允许主机层和控制器层在物理上分离,此时 HCI 体现为物理接口,包括 SDIO、USB 以及 UART 等;当然,主机层和控制器层可以共存于同一芯片,以实现更高的集成度,此时 HCI 体现为逻辑接口,常被称为虚拟主机控制器接口 (Virtual Host Controller Interface, VHCI)。一般认为,主机层和控制器层组成了低功耗蓝牙协议栈 (Bluetooth LE Stack)。
下图展示了 Bluetooth LE 的分层结构。
下图展示了低功耗蓝牙的分层结构。
.. figure:: ../../../../_static/ble/ble-architecture.png
:align: center
:scale: 50%
:alt: Bluetooth LE 分层结构
:alt: 低功耗蓝牙分层结构
Bluetooth LE 分层结构
低功耗蓝牙分层结构
作为应用开发者,在开发过程中我们主要与主机层提供的 API 接口打交道,这要求我们对主机层中的蓝牙协议有一定的了解。接下来,我们会从连接和数据交换两个角度,对 GAP 和 GATT/ATT 层的基本概念进行介绍。
@@ -53,7 +53,7 @@ Bluetooth LE 协议定义了三层软件结构,自上而下分别是
GAP 层 - 定义设备的连接
^^^^^^^^^^^^^^^^^^^^^^^
GAP 层的全称为通用访问规范 (Generic Access Profile, GAP),定义了 Bluetooth LE 设备之间的连接行为以及设备在连接中所扮演的角色。
GAP 层的全称为通用访问规范 (Generic Access Profile, GAP),定义了低功耗蓝牙设备之间的连接行为以及设备在连接中所扮演的角色。
GAP 状态与角色
@@ -85,14 +85,14 @@ GAP 角色之间的转换关系如下图所示
GAP 角色转换关系
Bluetooth LE 网络拓扑
低功耗蓝牙网络拓扑
########################
Bluetooth LE 设备可以同时与多个 Bluetooth LE 设备建立连接,扮演多个外围设备或中央设备角色,或同时作为外围设备和中央设备。以 Bluetooth LE 网关为例,这种设备可以作为中央设备,与智能开关等外围设备连接,同时作为外围设备,与形如手机等中央设备连接,实现数据中转。
低功耗蓝牙设备可以同时与多个低功耗蓝牙设备建立连接,扮演多个外围设备或中央设备角色,或同时作为外围设备和中央设备。以低功耗蓝牙网关为例,这种设备可以作为中央设备,与智能开关等外围设备连接,同时作为外围设备,与形如手机等中央设备连接,实现数据中转。
在一个 Bluetooth LE 网络中,若所有设备都在至少一个连接中,且仅扮演一种类型的角色,则称这种网络为连接拓扑 (Connected Topology);若存在至少一个设备同时扮演外围设备和中央设备,则称这种网络为多角色拓扑 (Multi-role Topology)。
在一个低功耗蓝牙网络中,若所有设备都在至少一个连接中,且仅扮演一种类型的角色,则称这种网络为连接拓扑 (Connected Topology);若存在至少一个设备同时扮演外围设备和中央设备,则称这种网络为多角色拓扑 (Multi-role Topology)。
Bluetooth LE 同时也支持无连接的网络拓扑,即广播拓扑 (Broadcast Topology)。在这种网络中,存在两种角色,其中发送数据的被称为广播者 (Broadcaster),接收数据的被称为观察者 (Observer)。广播者只广播数据,不接受连接;观察者仅接受广播数据,不发起连接。例如,某个智能传感器的数据可能在一个网络中被多个设备共用,此时维护多个连接的成本相对较高,直接向网络中的所有设备广播传感器数据更加合适。
低功耗蓝牙同时也支持无连接的网络拓扑,即广播拓扑 (Broadcast Topology)。在这种网络中,存在两种角色,其中发送数据的被称为广播者 (Broadcaster),接收数据的被称为观察者 (Observer)。广播者只广播数据,不接受连接;观察者仅接受广播数据,不发起连接。例如,某个智能传感器的数据可能在一个网络中被多个设备共用,此时维护多个连接的成本相对较高,直接向网络中的所有设备广播传感器数据更加合适。
了解更多
@@ -172,7 +172,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基
----------------------
在了解了 Bluetooth LE 的基础概念以后,让我们往 {IDF_TARGET_NAME} 开发板中烧录一个简单的 Bluetooth LE 例程,体验 LED 开关与心率数据读取功能,建立对 Bluetooth LE 技术的感性认识。
在了解了低功耗蓝牙的基础概念以后,让我们往 {IDF_TARGET_NAME} 开发板中烧录一个简单的低功耗蓝牙例程,体验 LED 开关与心率数据读取功能,建立对低功耗蓝牙技术的感性认识。
前提条件
@@ -263,7 +263,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基
广播数据详情
点击右侧的 **CONNECT** 按钮,在手机连接的同时,可以在开发板的串口输出中观察到许多与连接相关的日志信息。随后,手机上会显示 NimBLE_GATT 标签页,左上角应有 **CONNECTED** 状态,说明手机已成功通过 Bluetooth LE 协议连接至开发板。在 CLIENT 子页中,你应该能够看到四个 GATT 服务,如图所示
点击右侧的 **CONNECT** 按钮,在手机连接的同时,可以在开发板的串口输出中观察到许多与连接相关的日志信息。随后,手机上会显示 NimBLE_GATT 标签页,左上角应有 **CONNECTED** 状态,说明手机已成功通过低功耗蓝牙协议连接至开发板。在 CLIENT 子页中,你应该能够看到四个 GATT 服务,如图所示
.. figure:: ../../../../_static/ble/ble-get-started-gatt-services-list.jpg
:align: center
@@ -272,7 +272,7 @@ GATT 的全称是通用属性规范 (Generic Attribute Profile),在 ATT 的基
GATT 服务列表
前两个服务是 GAP 服务和 GATT 服务,这两个服务是 Bluetooth LE 应用中的基础服务。后两个服务是 Bluetooth SIG 定义的 Heart Rate Service 服务和 Automation IO Service 服务,分别提供心率数据读取和 LED 控制功能。
前两个服务是 GAP 服务和 GATT 服务,这两个服务是低功耗蓝牙应用中的基础服务。后两个服务是 Bluetooth SIG 定义的 Heart Rate Service 服务和 Automation IO Service 服务,分别提供心率数据读取和 LED 控制功能。
在服务名的下方,对应有各个服务的 UUID 以及服务主次标识。如 Heart Rate Service 服务的 UUID 为 `0x180D`,是一个主服务 (Primary Service)。需要注意的是,服务的名称是通过 UUID 解析得到的。以 nRF Connect for Mobile 为例,在实现 GATT 客户端时,开发者会将 Bluetooth SIG 定义的服务,以及例程自定义的服务预先写入数据库中,然后根据 GATT 服务的 UUID 进行服务信息解析。所以,假如某一服务的 UUID 不在数据库中,那么该服务的服务信息就无法被解析,服务名称将会显示为未知服务 (Unknown Service)。
@@ -339,4 +339,4 @@ Heart Rate Measurement 特征数据的 UUID 是 `0x2A37`,这是一个 Bluetoot
总结
---------
通过本教程,你了解了 Bluetooth LE 的分层架构、Bluetooth LE 协议栈中主机层和控制器层的基本功能以及 GAP 层与 GATT/ATT 层的作用。随后,通过 :example:`NimBLE_GATT_Server <bluetooth/ble_get_started/nimble/NimBLE_GATT_Server>` 例程,你掌握了如何使用 ESP-IDF 开发框架进行 Bluetooth LE 应用的构建与烧录,能够在手机上使用 **nRF Connect for Mobile** 调试程序,远程控制开发板上 LED 的点亮与熄灭,以及接收随机生成的心率数据。你已经迈出了走向 Bluetooth LE 开发者的第一步,恭喜!
通过本教程,你了解了低功耗蓝牙的分层架构、低功耗蓝牙协议栈中主机层和控制器层的基本功能以及 GAP 层与 GATT/ATT 层的作用。随后,通过 :example:`NimBLE_GATT_Server <bluetooth/ble_get_started/nimble/NimBLE_GATT_Server>` 例程,你掌握了如何使用 ESP-IDF 开发框架进行低功耗蓝牙应用的构建与烧录,能够在手机上使用 **nRF Connect for Mobile** 调试程序,远程控制开发板上 LED 的点亮与熄灭,以及接收随机生成的心率数据。你已经迈出了走向低功耗蓝牙开发者的第一步,恭喜!

View File

@@ -26,6 +26,15 @@
get-started/ble-connection
get-started/ble-data-exchange
***************
安全
***************
.. toctree::
:maxdepth: 2
smp
**********
蓝牙规范
**********

View File

@@ -7,17 +7,17 @@
.. only:: esp32
{IDF_TARGET_NAME} 支持双模蓝牙 4.2,并且已经获得双模蓝牙 4.2 认证和蓝牙 LE 5.0 认证
{IDF_TARGET_NAME} 支持双模蓝牙 4.2,并且已经通过双模蓝牙 4.2 认证和低功耗蓝牙 5.0 认证
.. only:: esp32c3 or esp32s3
{IDF_TARGET_NAME} 支持蓝牙 5.0 (LE),并且已经获得蓝牙 LE 5.4 认证。
{IDF_TARGET_NAME} 支持蓝牙 5.0 (LE),并且已经通过低功耗蓝牙 5.4 认证。
.. only:: esp32c2 or esp32c6 or esp32h2 or esp32c5 or esp32c61
{IDF_TARGET_NAME} 支持蓝牙 5.0 (LE),并且已经获得蓝牙 LE 5.3 认证。
{IDF_TARGET_NAME} 支持蓝牙 5.0 (LE),并且已经通过低功耗蓝牙 5.3 认证。
ESP-IDF 中的低功耗蓝牙协议栈是一个分层架构,可在 {IDF_TARGET_NAME} 系列芯片上实现低功耗蓝牙功能,详见下。
ESP-IDF 中的低功耗蓝牙协议栈是一个分层架构,可在 {IDF_TARGET_NAME} 系列芯片上实现低功耗蓝牙功能,详见下
.. only:: esp32 or esp32s3 or esp32c3 or esp32c6 or esp32c5 or esp32c61

View File

@@ -0,0 +1,163 @@
SMP
=======
:link_to_translation:`en:[English]`
在低功耗蓝牙中安全管理协议Security Manager Protocol, SMP作为 GAP 模块的一部分实现。SMP 用于生成加密密钥和身份密钥,定义设备配对和密钥分发协议,并确保协议栈中的设备可以安全地进行通信。此过程要求在数据链路层建立连接,并符合特定的安全标准。
GAP SMP 允许两台设备通过设置适当的安全级别在数据链路层加密通信,这些安全级别的详细信息可参考《蓝牙核心规范》的 SMP 章节。在介绍低功耗蓝牙安全管理模块的具体实现过程之前,需要先明确以下几个概念:
- **配对 (Pairing):** 两个设备同意双方建立一定级别的安全性连接。
- **绑定 (Bonding):** 至少有一台设备向另一台设备发送安全相关信息例如长期密钥LTK、连接签名解析密钥CSRK或身份解析密钥IRK以供将来连接时使用。成功配对后若支持绑定则会进行密钥分发否则不会交换绑定信息。配对可能发生而不一定需要绑定。在配对过程中设备会交换属性以确定对方是否支持绑定。如果双方都不支持绑定则不会存储对方的安全信息。
- **认证 (Authentication):** 此过程验证连接设备的身份,确保其不是第三方攻击者。不认证(Unauthentication) 并不意味着链路不安全。当两台设备确认链路加密密钥具有安全属性时,两个设备之间的关系称为认证。
在配对过程中,短期密钥 (STK) 认证会生成一个密钥词。对于具有输入/输出和带外 (OOB) 功能的设备,所有生成和交换的密钥都具备认证 (MITM) 保护属性。在这种情况下,更长的 PIN 码或 OOB 密钥能够增强安全性。相反,如果使用 Just Works 方法,生成和交换的密钥则不具备 MITM 保护。
- **授权 (Authorization):** 指应用层授予执行某些操作的权限。一些应用可能需要额外的授权,只有在用户明确授权后才能继续操作。如果未获得授权,相关操作将失败。
低功耗蓝牙加密
-------------------
低功耗蓝牙的加密可通过以下两种方式实现:
- **初始加密(未绑定):** 当两个低功耗蓝牙设备之间未进行过绑定时,加密将在配对过程中进行。是否绑定取决于配对配置。
- **重连接加密(已绑定):** 如果两个低功耗蓝牙设备已经绑定,则可使用之前交换的密钥进行加密。在这种情况下,其中一台设备会触发加密请求,并使用绑定过程中存储的密钥完成加密。
Just Works 模式下Master 主动发起加密请求的流程图如下 *点击图片放大*
.. seqdiag::
:caption: Just Works 模式下的加密流程图
:align: center
:scale: 200%
seqdiag just-works-encrypt {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 12;
"Input\n[Master]";
"API\n[Master]";
"SMP\n[Master]";
"SMP\n[Slave]";
"API\n[Slave]";
"Output\n[Slave]";
"Input\n[Master]" -> "API\n[Master]" [label="esp_ble_set_encryption"];
"API\n[Master]" -> "SMP\n[Master]";
"SMP\n[Master]" -> "SMP\n[Slave]" [label="smp_pair_req"];
"SMP\n[Slave]" -> "API\n[Slave]";
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_sec_req_evt"];
"API\n[Slave]" <- "Output\n[Slave]" [label="esp_ble_gap_security_rsp"];
"SMP\n[Slave]" <- "API\n[Slave]";
"SMP\n[Master]" <- "SMP\n[Slave]" [label="smp_pair_rsq"];
"SMP\n[Master]" -> "SMP\n[Slave]" [label="[ENCRYPT]", color=blue];
"SMP\n[Master]" <- "SMP\n[Slave]" [label="[ENCRYPT]", color=blue];
"API\n[Master]" <- "SMP\n[Master]";
"SMP\n[Slave]" -> "API\n[Slave]";
"Input\n[Master]" <- "API\n[Master]" [label="esp_gap_ble_auth_cmpl_evt"];
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_auth_cmpl_evt"];
}
Passkey Entry 模式下Master 主动发起加密请求的流程图如下 *点击图片放大*
.. seqdiag::
:caption: Passkey Entry 模式下的加密流程图
:align: center
:scale: 200%
seqdiag passkey-entry-encrypt {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 12;
"Input\n[Master]";
"API\n[Master]";
"SMP\n[Master]";
"SMP\n[Slave]";
"API\n[Slave]";
"Output\n[Slave]";
"Input\n[Master]" -> "API\n[Master]" [label="esp_ble_set_encryption"];
"API\n[Master]" -> "SMP\n[Master]";
"SMP\n[Master]" -> "SMP\n[Slave]" [label="smp_pair_req"];
"SMP\n[Slave]" -> "API\n[Slave]";
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_sec_req_evt"];
"API\n[Slave]" <- "Output\n[Slave]" [label="esp_ble_gap_security_rsp"];
"SMP\n[Slave]" <- "API\n[Slave]";
"SMP\n[Master]" <- "SMP\n[Slave]" [label="smp_pair_rsq"];
"Input\n[Master]" <- "API\n[Master]" [label="esp_gap_ble_passkey_notify_evt displays the passkey to the user, the peer device should enter this key and send it to the SMP stack"];
"API\n[Slave]" <- "Output\n[Slave]" [label="esp_ble_passkey_reply send the passkey to the SMP stack which is displayed in the peer device"];
"SMP\n[Master]" -> "SMP\n[Slave]" [label="[ENCRYPT]", color=blue];
"SMP\n[Master]" <- "SMP\n[Slave]" [label="[ENCRYPT]", color=blue];
"API\n[Master]" <- "SMP\n[Master]";
"SMP\n[Slave]" -> "API\n[Slave]";
"Input\n[Master]" <- "API\n[Master]" [label="esp_gap_ble_auth_cmpl_evt"];
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_auth_cmpl_evt"];
}
低功耗蓝牙绑定
-----------------
两个低功耗蓝牙设备的绑定通过调用 GAP API 实现。根据蓝牙核心规范,绑定的目的是使得经过 SMP 加密的两台低功耗蓝牙设备在重新连接时能够使用相同的密钥进行链路加密,从而简化重连过程。在配对过程中,设备交换加密密钥并将其存储,以便长期使用。
绑定状态图如下 *点击图片放大*
.. seqdiag::
:caption: 低功耗蓝牙设备的绑定流程图
:align: center
:scale: 200%
seqdiag ble_bonding {
activation = none;
edge_length = 160;
span_height = 20;
default_shape = roundedbox;
default_fontsize = 12;
"Input\n[Master]";
"API\n[Master]";
"SMP\n[Master]";
"LLC\n[Master]";
"LLC\n[Slave]";
"SMP\n[Slave]";
"API\n[Slave]";
"Output\n[Slave]";
"Input\n[Master]" -> "API\n[Master]" [label="esp_ble_set_encryption"];
"API\n[Master]" -> "SMP\n[Master]" [label="continues if bonding is completed with the peer device"];
"SMP\n[Master]" -> "LLC\n[Master]" [label="llc_start_enc_cmd"];
"LLC\n[Master]" -> "LLC\n[Slave]";
"LLC\n[Slave]" -> "SMP\n[Slave]" [label="llc_ltk_req_evt"];
"LLC\n[Slave]" <- "SMP\n[Slave]" [label="llc_ltk_req_reply_cmd"];
"LLC\n[Master]" -> "LLC\n[Slave]" [label="[ENCRYPT]", color=blue];
"LLC\n[Master]" <- "LLC\n[Slave]" [label="[ENCRYPT]", color=blue];
"SMP\n[Master]" <- "LLC\n[Master]" [label="llc_enc_change_evt"];
"LLC\n[Slave]" -> "SMP\n[Slave]" [label="llc_enc_change_evt"];
"API\n[Master]" <- "SMP\n[Master]";
"SMP\n[Slave]" -> "API\n[Slave]";
"Input\n[Master]" <- "API\n[Master]" [label="esp_gap_ble_auth_cmpl_evt"];
"API\n[Slave]" -> "Output\n[Slave]" [label="esp_gap_ble_auth_cmpl_evt"];
}
.. note::
绑定必须由主设备在连接建立后发起。
安全管理实现机制
-----------------
低功耗蓝牙安全管理是采用调用低功耗蓝牙 GAP 的 API 相关的加密函数,注册低功耗蓝牙 GAP 回调,并通过事件返回获取当前的加密状态。

View File

@@ -0,0 +1,11 @@
#####################
蓝牙\ :sup:`®` 架构
#####################
:link_to_translation:`en:[English]`
.. toctree::
:maxdepth: 2
overview

View File

@@ -0,0 +1,174 @@
概述
======
:link_to_translation:`en:[English]`
蓝牙\ :sup:`®` 无线技术是一种短距离通信标准,具备高可靠性、低功耗和低成本等特点。主要分为两种类型:
- **经典蓝牙:** 优化用于连续的高吞吐量数据流,适用于音频传输等应用。
- **低功耗蓝牙 (Bluetooth LE):** 针对低功耗间歇性数据传输设计,适合用于传感器和可穿戴设备等。
.. only:: esp32
{IDF_TARGET_NAME} 支持双模蓝牙,即同时支持经典蓝牙和低功耗蓝牙。
蓝牙协议栈
============
蓝牙协议栈是一种分层通信架构,定义了蓝牙设备如何发现彼此、建立连接、交换数据,并确保通信安全可靠。如图 :ref:`bluetooth-core-system-architecture` 所示协议栈主要分为控制器Controller和主机Host两大部分两者通过 HCI 接口进行通信。
.. _bluetooth-core-system-architecture:
.. figure:: ../../../_static/bluetooth-core-system-architecture.png
:align: center
:width: 80%
:alt: 蓝牙核心系统架构
蓝牙核心系统架构(来源:蓝牙核心规范)
**控制器**
控制器负责硬件层面的操作和底层链路控制,包含:
- **PHY (物理层):** 处理 2.4 GHz ISM 频段的蓝牙信号收发。
- **基带 (Baseband):** 管理底层时序和控制功能,包括跳频、数据包格式化和纠错。
- **链路控制器 (Link Controller):** 处理设备连接/断开的链路状态机、流控和重传机制。
- **链路管理器 (Link Manager):** 管理链路设置、身份验证、加密和功率控制。
- **设备管理器 (Device Manager):** 管理设备状态,处理寻呼/查询流程,存储安全密钥。
**主机**
主机实现应用交互所需的高层协议,包含:
- **L2CAP (逻辑链路控制与适配协议):** 处理数据分段、重组和复用。
- **SMP (安全管理协议):** 管理身份验证、加密和安全配对。
- **GAP (通用访问规范):** 管理设备发现、连接建立,并定义蓝牙设备的角色和模式。
- **ATT/GATT (属性协议/通用属性规范):** 通过服务和特征实现基于属性的数据交换,主要用于低功耗蓝牙。
- **SDP (服务发现协议):** 允许设备广播和发现可用服务,主要用于经典蓝牙。
.. only:: esp32
蓝牙主机和控制器可以集成在同一设备上,也可以在不同设备上实现。{IDF_TARGET_NAME} 可以支持上述两种方式,下图 :ref:`bt-host-controller-structure` 展示了典型的应用结构:
.. _bt-host-controller-structure:
.. figure:: ../../../_static/bt-host-controller-structure.png
:align: center
:width: 70%
:alt: {IDF_TARGET_NAME} 蓝牙主机与控制器的关系结构图
{IDF_TARGET_NAME} 蓝牙主机与控制器的关系结构图
- **场景 1ESP-IDF 默认设置)**
使用 Bluedroid 作为蓝牙主机,通过 VHCI软件实现的虚拟 HCI实现主机与控制器之间的通信。Bluedroid 和控制器运行在同一设备上(即 {IDF_TARGET_NAME} 芯片),无需外部主机设备。
- **场景 2仅控制器模式**
{IDF_TARGET_NAME} 仅作为蓝牙控制器。外部主机设备(如运行 BlueZ 的 Linux PC 或运行 Bluedroid 的 Android 设备)负责蓝牙操作。
- **场景 3测试/认证)**
类似于场景 2但用于蓝牙认证机构BQB控制器测试或认证。{IDF_TARGET_NAME} 芯片通过 UART 连接到测试工具。
蓝牙运行环境
=============
ESP-IDF 蓝牙协议栈运行在 FreeRTOS 环境中,蓝牙任务根据功能和优先级进行分配。由于实时性要求,控制器任务具有最高优先级(部分跨核通信 IPC 任务除外)。
.. only:: esp32
{IDF_TARGET_NAME} 的运行环境为双核 FreeRTOS控制器任务的优先级最高仅次于用于双核 CPU 之间通信的 IPC 任务。默认的蓝牙主机 Bluedroid 包含三个任务BTC、BTU 和 HCI。
Bluedroid
============
ESP-Bluedroid 是基于 Android 蓝牙协议栈 Bluedroid 的修改版, 支持经典蓝牙和低功耗蓝牙。由两层组成:
- **蓝牙上层 (BTU):** 实现核心协议L2CAP、GATT、SMP 等)。
- **蓝牙传输控制器层 (BTC):** 提供应用层 API 并管理配置文件。
**使用场景:** 推荐用于同时需要经典蓝牙和蓝牙低能耗的应用。
操作系统适配
--------------
Bluedroid 通过适配系统相关功能与 FreeRTOS 集成:
- **Timer (Alarm):** FreeRTOS 的 Timer 封装成 Alarm⽤于启动定时器触发某些特定任务。
- **Task (Thread):** FreeRTOS 的 Task 取代 POSIX Thread并使用 FreeRTOS 的 Queue 来触发任务的运行(唤醒)。
- **Future Await/Ready (Semaphore):** ``xSemaphoreTake`` 封装成 ``future_await````xSemphoreGive`` 封装成 ``future_ready````future_await````future_ready`` 不能在同一任务中调用。
- **Allocator (malloc/free):** 标准库中的 ``malloc/free`` 被封装为 ``Allocator``,用于分配 (malloc) 或释放 (free) 内存。
Bluedroid 目录结构
--------------------
ESP-IDF 目录 *component/bt/host/bluedroid* 包含如下子文件夹:
.. code-block:: text
├── api
├── bta
├── btc
├── common/include/common
├── config
├── device
├── external/sbc
├── hci
├── main
├── stack
└── Kconfig.in
子文件夹的具体说明见下表:
.. list-table:: ESP-IDF *component/bt/host/bluedroid* 目录描述
:header-rows: 1
:widths: 20 80
* - **子文件夹**
- **说明**
* - *api*
- API 目录,所有的 API除 Controller 相关)都在此目录下。
* - *bta*
- 蓝牙适配层,适配一些主机底层协议的接口。
* - *btc*
- 蓝牙控制层,控制主机上层协议(包括规范)以及杂项的处理。
* - *common*
- 协议栈的通用头文件。
* - *config*
- 为协议栈配置一些参数。
* - *device*
- 与控制器设备控制相关的,如控制器基本设置的 HCI CMD 流程等。
* - *external*
- 与蓝⽛⾃身⽆关,但⼜要使⽤的代码,如 SBC codec 软件程序等。
* - *hci*
- HCI 层协议。
* - *main*
- 主程序⽬录(主要为启动、关闭流程)。
* - *stack*
- 主机底层协议栈GAP/ ATT/ GATT/ SDP/ SMP 等)。
* - *Kconfig.in*
- Menuconfig 文件。

View File

@@ -4,10 +4,9 @@
:link_to_translation:`en:[English]`
*****
概览
*****
.. toctree::
:maxdepth: 2
overview
profiles-protocols

View File

@@ -1,4 +1,4 @@
介绍
概述
=======
:link_to_translation:`en:[English]`
@@ -9,7 +9,7 @@
{IDF_TARGET_NAME} 支持双模蓝牙 4.2,并且已经获得双模蓝牙 4.2 认证。
ESP-IDF 中的经典蓝牙协议栈是一个分层架构,可在 {IDF_TARGET_NAME} 系列芯片上实现经典蓝牙功能,详见下。
ESP-IDF 中的经典蓝牙协议栈是一个分层架构,可在 {IDF_TARGET_NAME} 系列芯片上实现经典蓝牙功能,详见下
.. only:: esp32
@@ -20,29 +20,6 @@ ESP-IDF 中的经典蓝牙协议栈是一个分层架构,可在 {IDF_TARGET_NA
{IDF_TARGET_NAME} 经典蓝牙协议栈架构
参考下表可知特定芯片是否支持经典蓝牙控制器。
.. list-table::
:width: 100%
:widths: auto
:header-rows: 1
* - 芯片系列
- 控制器
* - ESP32
- Y
* - ESP32-S2
- \
* - ESP32-S3
- \
* - ESP32-C2
- \-
* - ESP32-C3
- \-
* - ESP32-C6
- \-
* - ESP32-H2
- \-
以下各节简要介绍了每个层,并提供了相关文档和应用示例的快速链接。

View File

@@ -0,0 +1,103 @@
规范和协议
===========
:link_to_translation:`en:[English]`
协议 (Protocol) 定义了完成特定功能的消息格式和过程,例如数据传输、链路控制、安全服务和服务信息交换等。另一方面,蓝牙规范 (Profile) 则定义了蓝牙系统中从 PHY 到 L2CAP 及核心规范外的其他协议所需的功能和特性。
以下是 ESP-Bluedroid 支持的经典蓝牙协议和规范:
- 协议L2CAP、SDP、AVDTP、AVCTP、RFCOMM
- 规范GAP、A2DP、AVRCP、SPP、HFP
协议模型如图 :ref:`bluetooth-protocol-model` 所示。
.. _bluetooth-protocol-model:
.. figure:: ../../../_static/bluetooth-protocol-model.png
:align: center
:width: 60%
:alt: 蓝牙协议模型
蓝牙协议模型
如图 :ref:`bluetooth-protocol-model` 所示L2CAP 和 SDP 是经典蓝牙最小主机协议栈的必备组成部分AVDTP、AV/C 和 AVCTP 并不属于核心规范,仅用于特定规范。
L2CAP
--------
蓝牙逻辑链路控制和适配协议 (Logical Link Control and Adaptation Protocol, L2CAP) 是 OSI 2 层协议支持上层的协议复用、分段和重组及服务质量信息的传递。L2CAP 可以让不同的应用程序共享一条 ACL-U 逻辑链路。应用程序和服务协议可通过一个面向信道的接口,与 L2CAP 进行交互,从而与其他设备上的等效实体进行连接。
L2CAP 信道共支持 6 种模式,可通过 L2CAP 信道配置过程进行选择,不同模式的应用场合不同,主要差别在于可提供的 QoS 不同。这些模式分别是:
- 基本 L2CAP 模式
- 流量控制模式
- 重传模式
- 加强重传模式
- 流模式
- 基于 LE Credit 的流量控制模式
其中ACL-U 逻辑链路支持的操作模式包括基本 L2CAP 模式、加强重传模式和流模式。L2CAP 信道为支持的固定信道,也支持帧校验序列 (Frame Check Sequence, FCS)。
SDP
--------
服务发现协议 (Service Discovery Protocol, SDP) 允许应用程序发现其他对等蓝牙设备提供的服务并确定可用服务的特征。SDP 包含 SDP 服务器和 SDP 客户端之间的通信。服务器维护一个描述服务特性的服务记录表。客户端可通过发出 SDP 请求,从服务器维护的服务记录表中进行信息检索。
GAP
--------
通用访问规范 (Generic Access Profile, GAP) 提供有关设备可发现性、可连接性和安全性的模式和过程描述。
A2DP 和 AVRCP
----------------
高级音频分发规范 (Advanced Audio Distribution Profile, A2DP) 定义了在 ACL 信道上实现高质量单声道或立体声音频内容传输的协议和过程。A2DP 负责处理音频流,通常与音频/视频远程控制规范 (Audio/Video Remote Control Profile, AVRCP)(包括音频/视频控制功能)一起使用。图 :ref:`profile-dependencies` 描述了这些规范的结构和关系图:
.. _profile-dependencies:
.. figure:: ../../../_static/profile-dependencies.png
:align: center
:width: 50%
:alt: 规范关系图
规范关系图
如图 :ref:`profile-dependencies` 所示A2DP 的工作基于 GAP 以及通用音频/ 视频分发规范 (Generic Audio/Video Distribution Profile, GAVDP),定义了建立音频/视频流的过程。
A2DP 中共定义了两个角色Source (SRC) 和 Sink (SNK)。SRC 代表数字音频流的源端SNK 代表数字音频流的接收端。
AVRCP 中共定义了两个角色:控制器 (CT) 和目标 (TG)。控制器可通过向目标发送命令帧发起事务。控制器的常见例子包括个人电脑、PDA 和移动电话等。目标可接收控制器发送的命令帧,并生成相应的响应帧。目标的常见例子包括音频播放器或耳机。
在目前的 A2DP 解决方案中SBC 是唯一支持的音频编解码器SBC 在 A2DP 规范中是必须的编解码格式。目前方案中实现的规范、协议版本是 A2DP V1.4 和 AVDTP V1.3。
AVDTP 协议定义了蓝牙设备之间在 L2CAP 协议层上建立和传输媒体流的二进制业务。作为 A2DP 的基本传输协议AVDTP 建立在 L2CAP 层协议之上,由 “一个协商媒体流参数的信令传输实体” 和 “一个传输媒体流的实体” 组成。
A2DP 规范规定了 AVDTP 传输功能的基本服务。根据当前服务功能的配置,基本服务功能中提供了媒体传输和媒体编解码器。
AVRCP 定义了支持音频/ 视频遥控的应用场景的各项需求。AVRCP 中的命令主要分为三个大组:
- **AV/C 数字接口命令集:** 其特定命令子集被采用,且通过 AVCTP 协议传输。
- **浏览命令:** 可通过 AVCTP 浏览信道,提供浏览功能。
- **封面艺术命令:** 用于传输与媒体项目有关的图像,通过基于 OBEX 协议的蓝牙基本图像规范 (BIP) 实现。
AVRCP 使用了其中的两套 AV/C 命令:其一包括 AV/C 规范中定义的 PASS THROUGH、UNIT INFO 和 SUBUNIT INFO 命令;其二是 AVRCP 专用 AV/C 命令,作为对 Bluetooth SIG Vendor Dependent 的扩展。
AV/C 命令通过 AVCTP 控制信道发送。PASS THROUGH 命令可通过控制器上的按钮向面板子单元传送用户操作并提供一个简单的通用机制来控制目标。例如PASS THROUGH 中的操作 ID 包括播放、暂停、停止、调高音量和调低音量等常用指令。
为了保证互操作性AVRCP 将 A/V 功能分为四类:
- 播放机/ 录像机
- 监控器/ 放大器
- 调音器
- 菜单
目前的方案提供了 AVRCP V1.6 和 AVCTP V1.4。AVRCP 支持功能的默认配置属于第二类,即监视器/放大器。此外,方案还提供了用于发送 PASS THROUGH 命令的 API。
A2DP 和 AVRCP 经常一起使用。在目前的解决方案中,下层主机堆栈实现了 AVDTP 和 AVCTP 逻辑,并独立为 A2DP 和 AVRCP 提供接口。然而,在堆栈上层中,两个规范组合匹配成为 “AV” 模块。例如BTA 层提供一个统一的 “AV” 接口,而在 BTC 层中状态机将处理两种规范的事务。然而A2DP 和 AVRCP 的 API 是分别提供的。

View File

@@ -7,6 +7,7 @@ API 指南
app_trace
startup
:SOC_BT_SUPPORTED: bt-architecture/index
:SOC_BT_CLASSIC_SUPPORTED: classic-bt/index
:SOC_BLE_SUPPORTED: ble/index
:SOC_BLE_MESH_SUPPORTED: esp-ble-mesh/ble-mesh-index