Wi-Fi Vendor 特性
========================

:link_to_translation:`en:[English]`

.. only:: SOC_WIFI_MESH_SUPPORT

    ESP-WIFI-MESH
    -------------------------

    详细信息请参阅 :doc:`ESP-WIFI-MESH <../esp-wifi-mesh>`.


Wi-Fi 80211 数据包发送
---------------------------

:cpp:func:`esp_wifi_80211_tx()` API 可用于：

 - 发送 beacon、probe request、probe response 和 action 帧。
 - 发送非 QoS 数据帧。

不能用于发送加密或 QoS 帧。

使用 :cpp:func:`esp_wifi_80211_tx()` 的前提条件
+++++++++++++++++++++++++++++++++++++++++++++++++++++++

 - Wi-Fi 模式为 station 模式，AP 模式，或 station/AP 共存模式。
 - API esp_wifi_set_promiscuous(true) 或 :cpp:func:`esp_wifi_start()`，或者二者都返回 :c:macro:`ESP_OK`。这是为确保在调用函数 :cpp:func:`esp_wifi_80211_tx()` 前，Wi-Fi 硬件已经初始化。对于 {IDF_TARGET_NAME}，esp_wifi_set_promiscuous(true) 和 :cpp:func:`esp_wifi_start()` 都可以触发 Wi-Fi 硬件初始化。
 - 提供正确的 :cpp:func:`esp_wifi_80211_tx()` 参数。

传输速率
+++++++++++++++++++++++++++++

 - 默认传输速率为 1 Mbps。
 - 可以通过函数 :cpp:func:`esp_wifi_config_80211_tx_rate()` 设置任意速率。
 - 可以通过函数 :cpp:func:`esp_wifi_set_bandwidth()` 设置任意带宽。

在不同情况下需要避免的副作用
+++++++++++++++++++++++++++++++++++++++++++++++++++++

理论上，如果不考虑 API 对 Wi-Fi 驱动程序或其他 station 或 AP 的副作用，可以通过空中发送一个原始的 802.11 数据包，包括任何目的地址的 MAC、任何源地址的 MAC、任何 BSSID、或任何其他类型的数据包。但是，一个具有强健、有用的应用程序应该避免这种副作用。下表针对如何避免 :cpp:func:`esp_wifi_80211_tx()` 的副作用提供了一些提示或建议。

.. list-table::
   :header-rows: 1
   :widths: 10 55

   * - 场景
     - 描述
   * - 无 Wi-Fi 连接
     - 在这种情况下，因为没有 Wi-Fi 连接，Wi-Fi 驱动程序不会受到副作用影响。如果 ``en_sys_seq==true``，则 Wi-Fi 驱动程序负责序列控制。如果 ``en_sys_seq==false``，应用程序需要确保缓冲区的序列正确。

       理论上，MAC 地址可以是任何地址。但是，这样可能会影响其他使用相同 MAC/BSSID 的 station/AP。

       例如，AP 模式下，应用程序调用函数 :cpp:func:`esp_wifi_80211_tx` 发送带有 BSSID == mac_x 的 beacon，但是 mac_x 并非 AP 接口的 MAC。而且，还有另一个 AP（我们称之为 “other-AP”）的 bssid 是 mac_x。因此，连接到 “other-AP” 的 station 无法分辨 beacon 来自 “other-AP” 还是 :cpp:func:`esp_wifi_80211_tx`，就会出现 “意外行为”。

       为了避免上述副作用，我们建议：

       - 如果在 station 模式下调用函数 :cpp:func:`esp_wifi_80211_tx`，第一个 MAC 应该是组播 MAC 或是目标设备的 MAC，第二个 MAC 应该是 station 接口的 MAC。

       - 如果在 AP 模式下调用函数 :cpp:func:`esp_wifi_80211_tx`，第一个 MAC 应该是组播 MAC 或是目标设备的 MAC，第二个 MAC 应该是 AP 接口的 MAC。

       上述建议仅供避免副作用，在有充分理由的情况下可以忽略。

   * - 有 Wi-Fi 连接
     - 当 Wi-Fi 已连接，且序列由应用程序控制，应用程序可能会影响整个 Wi-Fi 连接的序列控制。 因此，en_sys_seq 要为 true，否则将返回 ``ESP_ERR_INVALID_ARG``。

       “无 Wi-Fi 连接”情况下的 MAC 地址建议也适用于此情况。

       如果 Wi-Fi 模式是 station 模式，MAC 的地址 1 是 station 所连 AP 的 MAC，地址 2 是 station 接口的 MAC，那么就称数据包是从 station 发送到 AP。另一方面，如果 Wi-Fi 模式是 AP 模式，且 MAC 地址 1 是该 AP 所连 station 的 MAC，地址 2 是 AP 接口的 MAC，那么就称数据包是从 AP 发送到 station。为避免与 Wi-Fi 连接冲突，可采用以下检查方法：

       - 如果数据包类型是数据，且是从 station 发送到 AP，IEEE 802.11 Frame control 字段中的 ToDS 位应该为 1，FromDS 位为 0，否则，Wi-Fi 驱动程序不接受该数据包。

       - 如果数据包类型是数据，且是从 AP 发送到 station，IEEE 802.11 Frame control 字段中的 ToDS 位应该为 0，FromDS 位为 1，否则，Wi-Fi 驱动程序不接受该数据包。

       - 如果数据包是从 station 发送到 AP，或从 AP 到 station，Power Management、More Data 和 Re-Transmission 位应该为 0，否则，Wi-Fi 驱动程序不接受该数据包。

       如果任何检查失败，将返回 ``ESP_ERR_INVALID_ARG``。


Wi-Fi 供应商 IE 配置
-----------------------------

默认情况下，所有 Wi-Fi 管理帧都由 Wi-Fi 驱动程序处理，应用程序不需要任何操作。但是，某些应用程序可能需要处理 beacon、probe request、probe response 和其他管理帧。例如，如果在管理帧中插入一些只针对供应商的 IE，则只有包含此 IE 的管理帧才能得到处理。{IDF_TARGET_NAME} 中，:cpp:func:`esp_wifi_set_vendor_ie()` 和 :cpp:func:`esp_wifi_set_vendor_ie_cb()` 负责此类任务。


.. only:: SOC_WIFI_CSI_SUPPORT

    Wi-Fi 信道状态信息
    ------------------------------------

    .. only:: esp32 or esp32s2 or esp32c3 or esp32s3

        信道状态信息 (CSI) 是指 Wi-Fi 连接的信道信息。{IDF_TARGET_NAME} 中，CSI 由子载波的信道频率响应组成，CSI 从发送端接收数据包时开始估计。每个子载波信道频率响由两个字节的有符号字符记录，第一个字节是虚部，第二个字节是实部。根据接收数据包的类型，信道频率响应最多有三个字段。分别是 LLTF、HT-LTF 和 STBC-HT-LTF。对于在不同状态的信道上接收到的不同类型的数据包，CSI 的子载波索引和总字节数如下表所示。

        +------------+-------------+-----------------------------------------+-----------------------------------------------------+--------------------------------------------------------+
        | 信道       | 辅助信道    |                                         | 下                                                  | 上                                                     |
        +------------+-------------+-------------+---------------------------+---------+-------------------------------------------+---------+----------------------------------------------+
        | 数据包信息 | 信号模式    | 非 HT       | HT                        | 非 HT   | HT                                        | 非 HT   | HT                                           |
        |            +-------------+-------------+---------------------------+---------+---------------+---------------------------+---------+------------------+---------------------------+
        |            | 信道带宽    | 20 MHz      | 20 MHz                    | 20 MHz  | 20 MHz        | 40 MHz                    | 20 MHz  | 20 MHz           | 40 MHz                    |
        |            +-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+
        |            | STBC        | 非 STBC     | 非 STBC     | STBC        | 非 STBC | 非 STBC| STBC | 非 STBC     | STBC        | 非 STBC | 非 STBC | STBC   | 非 STBC     | STBC        |
        +------------+-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+
        | 子载波索引 | LLTF        | 0~31,-32~-1 | 0~31,-32~-1 | 0~31,-32~-1 |    0~63 |   0~63 | 0~63 |        0~63 |        0~63 |  -64~-1 |  -64~-1 | -64~-1 |      -64~-1 |      -64~-1 |
        |            +-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+
        |            | HT-LTF      |           — | 0~31,-32~-1 | 0~31,-32~-1 |       — |   0~63 | 0~62 | 0~63,-64~-1 | 0~60,-60~-1 |       — |  -64~-1 | -62~-1 | 0~63,-64~-1 | 0~60,-60~-1 |
        |            +-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+
        |            | STBC-HT-LTF |           — |           — | 0~31,-32~-1 |       — |      — | 0~62 |           — | 0~60,-60~-1 |       — |       — | -62~-1 |           — | 0~60,-60~-1 |
        +------------+-------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+
        | 总字节数                 |         128 |         256 |         384 |     128 |    256 |  380 |         384 |         612 |     128 |     256 |    376 |         384 |         612 |
        +--------------------------+-------------+-------------+-------------+---------+--------+------+-------------+-------------+---------+---------+--------+-------------+-------------+

        表中的所有信息可以在 wifi_csi_info_t 结构中找到。

            - 辅助信道指 rx_ctrl 字段的 secondary_channel 字段。
            - 数据包的信号模式指 rx_ctrl 字段的 sig_mode 字段。
            - 信道带宽指 rx_ctrl 字段中的 cwb 字段。
            - STBC 指 rx_ctrl 字段的 stbc 字段。
            - 总字节数指 len 字段。
            - 每个长训练字段 (LTF) 类型对应的 CSI 数据存储在从 buf 字段开始的缓冲区中。每个元素以两个字节的形式存储：虚部和实部。每个元素的顺序与表中的子载波相同。LTF 的顺序是 LLTF、HT-LTF 和 STBC-HT-LTF。但是，根据信道和数据包的信息，3 个 LTF 可能都不存在（见上文）。
            - 如果 :cpp:type:`wifi_csi_info_t` 的 first_word_invalid 字段为 true，表示由于 {IDF_TARGET_NAME} 的硬件限制，CSI 数据的前四个字节无效。
            - 更多信息，如 RSSI，射频的噪声底，接收时间和天线 rx_ctrl 领域。

        子载波的虚部和实部的使用请参考下表。

        +----------------+-------------------+------------------------------+------------------------------+
        | PHY 标准       | 子载波范围        | 导频子载波                   | 子载波个数（总数/数据子载波）|
        +================+===================+==============================+==============================+
        | 802.11a/g      | -26 to +26        | -21, -7, +7, +21             | 52 total, 48 usable          |
        +----------------+-------------------+------------------------------+------------------------------+
        | 802.11n, 20 MHz| -28 to +28        | -21, -7, +7, +21             | 56 total, 52 usable          |
        +----------------+-------------------+------------------------------+------------------------------+
        | 802.11n, 40 MHz| -57 to +57        | -53, -25, -11, +11, +25, +53 | 114 total, 108 usable        |
        +----------------+-------------------+------------------------------+------------------------------+

        .. note::

            - 对于 STBC 数据包，每个空时流都提供了 CSI，不会出现 CSD（循环移位延迟）。由于附加链上的每一次循环移位为 -200 ns，因为子载波 0 中没有信道频率响应，在 HT-LTF 和 STBC-HT-LTF 中只记录第一空时流的 CSD 角度。CSD[10:0] 是 11 位，范围从 -pi 到 pi。

            - 如果调用 API :cpp:func:`esp_wifi_set_csi_config()` 没有使能 LLTF、HT-LTF 或 STBC-HT-LTF，则 CSI 数据的总字节数会比表中的少。例如，如果没有使能 LLTF 和 HT-LTF，而使能 STBC-HT-LTF，当接收到上述条件、HT、40 MHz 或 STBC 的数据包时，CSI 数据的总字节数为 244（(61+60)*2+2=244，结果对齐为四个字节，最后两个字节无效）。

    .. only:: esp32c5

        信道状态信息 (CSI) 是指 Wi-Fi 连接的信道信息。{IDF_TARGET_NAME} 中，CSI 由子载波的信道频率响应组成，CSI 从发送端接收数据包时开始估计。每个子载波信道频率响由两个字节的有符号字符记录，第一个字节是虚部，第二个字节是实部。除了 IEEE 802.11g 模式外，其他模式均存在两段 LTF 序列（LLTF + HT/VHT/HE-LTF）。{IDF_TARGET_NAME}可以通过 :cpp:struct:`wifi_csi_acquire_config_t` 中 ``acquire_csi_force_lltf`` 字段决定包含 LLTF 或 HT/VHT/HE-LTF。对于在不同状态的信道上接收到的不同类型的数据包，CSI 的子载波索引和总字节数如下表所示。

        +------------+------------------+-----------------------------------------+--------------------------------------------+----------------------------------------------------------------+----------------------------------------------------------------+
        | 信道       | 辅助信道         |                                                                                      | 下                                                             | 上                                                             |
        +------------+------------------+-------------+---------------------------+--------------------------------------------+-------------+--------------------------------------------------+-------------+--------------------------------------------------+
        | 数据包信息 | 信号模式         | 非 HT       | HT                        | HE                                         | 非 HT       | HT                                               | 非 HT       | HT                                               |
        |            +------------------+-------------+---------------------------+--------------------------------------------+-------------+----------------------+---------------------------+-------------+----------------------+---------------------------+
        |            | 信道带宽         | 20 MHz      | 20 MHz                    | 20 MHz                                     | 20 MHz      | 20 MHz               | 40 MHz                    | 20 MHz      | 20 MHz               | 40 MHz                    |
        |            +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+
        |            | STBC             | 非 STBC     | 非 STBC     | STBC        | 非 STBC       | STBC                       | 非 STBC     | 非 STBC     | STBC   | 非 STBC     | STBC        | 非 STBC     | 非 STBC     | STBC   | 非 STBC     | STBC        |
        +------------+------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+
        | 子载波索引 | LLTF             | 0~26,-26~-1 |           — |           — |             — |                          — |   0~52      |           — |      — |           — |           — |       -53~-1|           — |      — |           — |           — |
        |            +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+
        |            | HT-LTF (HT-LTF1) |           — | 0~28,-28~-1 | 0~28,-28~-1 |             — |                          — |           — |         0~56|  0~56  | 0~58,-58~-1 | 0~58,-58~-1 |           — |       -57~-1| -57~-1 | 0~58,-58~-1 | 0~58,-58~-1 |
        |            +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+
        |            | HT-LTF2          |           — |           — | 0~28,-28~-1 |             — |                          — |           — |           — |  0~56  |           — | 0~58,-58~-1 |           — |           — | -57~-1 |           — | 0~58,-58~-1 |
        |            +------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+
        |            | HE-LTF (HE-LTF1) |           — |           — |           — | 0~122,-122~1  |       由CSI配置决定        |           — |           — |      — |           — |           — |           — |           — |      — |           — |           — |
        |            +------------------+-------------+-------------+-------------+---------------+                            +-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+
        |            | HE-LTF2          |           — |           — |           — |             — |                            |           — |           — |      — |           — |           — |           — |           — |      — |           — |           — |
        +------------+------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+
        | 总字节数                      |         106 |          114|         228 |           490 |                        490 |         106 |          114|   228  |         234 |         468 |       106   |          114|    228 |         234 |         468 |
        +-------------------------------+-------------+-------------+-------------+---------------+----------------------------+-------------+-------------+--------+-------------+-------------+-------------+-------------+--------+-------------+-------------+

        .. note::

            - HT/VHT/HE 模式均存在两段 LTF 序列即：LLTF + HT/VHT/HE-LTF， 如果 :cpp:struct:`wifi_csi_acquire_config_t` 中 ``acquire_csi_force_lltf`` 为 false 时， CSI 数据中仅包含 HT/VHT/HE-LTF(如上表所示)， 否则 CSI 数据中仅包含 LLTF。 HT/VHT/HE 模式 LLTF 的子载波索引和 CSI 总字节数同非 HT 模式 LLTF 子载波索引和 CSI 总字节数一致。
            - VHT 模式时子载波索引和 CSI 总字节数同 HT 模式的子载波索引和 CSI 总字节数一致。

        表中的信息可以在 :cpp:type:`wifi_csi_info_t` 结构体中找到。

            - 辅助信道指 ``rx_ctrl`` 字段的 ``second`` 字段。
            - 数据包的信号模式指 ``rx_ctrl`` 字段的 ``cur_bb_format`` 字段。
            - 总字节数指 ``len`` 字段。
            - 每个长训练字段 (LTF) 类型对应的 CSI 数据存储在从 buf 字段开始的缓冲区中。每个元素以两个字节的形式存储：虚部和实部。每个元素的顺序与表中的子载波相同。LTF 的顺序是 LLTF、HT/VHT/HE-LTF。根据信道和数据包的信息，LTF 的存在情况见上文。
            - 如果 ``first_word_invalid`` 字段为 true，表示由于 {IDF_TARGET_NAME} 的硬件限制，CSI 数据的前四个字节无效。
            - 如果 ``rx_ctrl`` 字段中的 ``rx_channel_estimate_info_vld`` 为 1,表明CSI数据是有效的，否则，CSI数据是无效的。
            - 更多信息，如 RSSI、射频底噪声、接收时间及天线，请参见 ``rx_ctrl`` 字段。

        对于 STBC 数据包，HE-LTF 和 STBC-HE-LTF 的子载波索引由 :cpp:type:`wifi_csi_config_t` 中的 ``acquire_csi_he_stbc_mode`` 字段决定，具体请参见下表。

        +---------------------+------------------+-------------------+
        | acquire_csi_he_stbc | HE-LTF1          | HE-LTF2           |
        +---------------------+------------------+-------------------+
        |         0           |  -122~-1, 0~122  |                 — |
        +---------------------+------------------+-------------------+
        |         1           |                — |  -122~-1, 0~122   |
        +---------------------+------------------+-------------------+
        |         2           | 在 HE-LTF1 和 HE-LTF2 中进行均匀采样 |
        +---------------------+------------------+-------------------+

        有效子载波的虚部和实部的使用请参考下表。

        +-----------------------+------------------+------------------------------------------+------------------------------+
        | PHY 标准              | 子载波范围       |               无效子载波                 | 子载波个数（总数/数据子载波）|
        +=======================+==================+==========================================+==============================+
        | 802.11a/g             | -26 to +26       |                    0                     | 53 total, 52 usable          |
        +-----------------------+------------------+------------------------------------------+------------------------------+
        | 802.11n, 20 MHz       | -28 to +28       |                    0                     | 57 total, 56 usable          |
        +-----------------------+------------------+------------------------------------------+------------------------------+
        | 802.11n, 40 MHz       | -58 to +58       |                -1, 0, 1                  | 117 total, 114 usable        |
        +-----------------------+------------------+------------------------------------------+------------------------------+
        | 802.11ac, 20 MHz      | -28 to +28       |                    0                     | 57 total, 56 usable          |
        +-----------------------+------------------+------------------------------------------+------------------------------+
        | 802.11ax, 20 MHz (SU) | -122 to + 122    |                -1, 0, 1                  | 245 total, 242 usable        |
        +-----------------------+------------------+------------------------------------------+------------------------------+

        .. note::

            - PHY 为 802.11ax时，MU 数据包的 CSI 子载波范围和无效子载波索引请参考协议。

        .. note::

            - 对于 STBC 数据包，每个空时流都提供了 CSI，不会出现 CSD（循环移位延迟）。由于附加链上的每一次循环移位为 -200 ns，因为子载波 0 中没有信道频率响应，在 HT-LTF1 和 HT-LTF2 中只记录第一空时流的 CSD 角度。CSD[10:0] 是 11 位，范围从 -pi 到 pi。


    Wi-Fi 信道状态信息配置
    -------------------------------------------

    要使用 Wi-Fi CSI，需要执行以下步骤。

        - 在菜单配置中选择 Wi-Fi CSI。方法是 ``Menuconfig`` > ``Components config`` > ``Wi-Fi`` > ``Wi-Fi CSI (Channel State Information)``。
        - 调用 API :cpp:func:`esp_wifi_set_csi_rx_cb()` 设置 CSI 接收回调函数。
        - 调用 API :cpp:func:`esp_wifi_set_csi_config()` 配置 CSI。
        - 调用 API :cpp:func:`esp_wifi_set_csi()` 使能 CSI。

    CSI 接收回调函数从 Wi-Fi 任务中运行。因此，不要在回调函数中进行冗长的操作。可以将需要的数据发布到队列中，并从一个较低优先级的任务中处理。由于 station 在断开连接时不会收到任何数据包，只有在连接时才会收到来自 AP 的数据包，因此建议通过调用函数 :cpp:func:`esp_wifi_set_promiscuous()` 使能 Sniffer 模式接收更多 CSI 数据。


Wi-Fi 多根天线
--------------------------

具体请参考 :doc:`PHY <../../api-guides/phy>`。
