Merge branch 'feat/support_nan_usd' into 'master'

Add support for Unsynchronized Service Discovery (USD)

See merge request espressif/esp-idf!30990
This commit is contained in:
Jiang Jiang Jian
2025-10-22 14:00:49 +08:00
49 changed files with 3585 additions and 178 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ const esp_netif_ip_info_t _g_esp_netif_soft_ap_ip = {
const esp_netif_inherent_config_t _g_esp_netif_inherent_ap_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_AP();
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
const esp_netif_inherent_config_t _g_esp_netif_inherent_nan_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_NAN();
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -158,7 +158,7 @@ extern "C" {
}
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
/**
* @brief Default configuration reference of WIFI NAN
*/
@@ -204,7 +204,7 @@ extern "C" {
#define ESP_NETIF_BASE_DEFAULT_WIFI_AP &_g_esp_netif_inherent_ap_config
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
/**
* @brief Default base config (esp-netif inherent) of WIFI NAN
*/
@@ -230,7 +230,7 @@ extern "C" {
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
#define ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP _g_esp_netif_netstack_default_wifi_ap
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
#define ESP_NETIF_NETSTACK_DEFAULT_WIFI_NAN _g_esp_netif_netstack_default_wifi_nan
#endif
#ifdef CONFIG_PPP_SUPPORT
@@ -249,7 +249,7 @@ extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap;
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_nan;
#endif
#ifdef CONFIG_PPP_SUPPORT
@@ -264,7 +264,7 @@ extern const esp_netif_inherent_config_t _g_esp_netif_inherent_sta_config;
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_ap_config;
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_nan_config;
#endif
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config;
+1 -1
View File
@@ -48,7 +48,7 @@ if(CONFIG_ESP_WIFI_ENABLED OR CONFIG_ESP_HOST_WIFI_ENABLED)
"src/smartconfig_ack.c")
endif()
if(CONFIG_ESP_WIFI_NAN_ENABLE)
if(CONFIG_ESP_WIFI_NAN_SYNC_ENABLE OR CONFIG_ESP_WIFI_NAN_USD_ENABLE)
list(APPEND srcs "wifi_apps/nan_app/src/nan_app.c")
endif()
if(CONFIG_ESP_WIFI_ENABLE_ROAMING_APP)
+10 -3
View File
@@ -576,13 +576,20 @@ menu "Wi-Fi"
Maximum espnow encrypted peers number + maximum number of connections of SoftAP = Max hardware
keys number. When using ESP mesh, this value should be set to a maximum of 6.
config ESP_WIFI_NAN_ENABLE
bool "WiFi Aware"
config ESP_WIFI_NAN_SYNC_ENABLE
bool "Enable Wi-Fi Aware: Synchronization (NAN-Sync)"
default n
depends on SOC_WIFI_NAN_SUPPORT
select LWIP_IPV6
help
Enable WiFi Aware (NAN) feature.
Enable Wi-Fi Aware: Synchronization feature (NAN-Sync).
config ESP_WIFI_NAN_USD_ENABLE
bool "Enable Wi-Fi Aware: Unsynchronized service discovery (NAN-USD)"
depends on IDF_EXPERIMENTAL_FEATURES
default n
help
Enable Wi-Fi Aware: Unsynchronized service discovery (NAN-USD)
config ESP_WIFI_MBEDTLS_CRYPTO
bool "Use MbedTLS crypto APIs"
@@ -39,7 +39,7 @@ typedef struct {
void *storage; /**< storage for FreeRTOS queue */
} wifi_static_queue_t;
struct nan_callbacks {
struct nan_sync_callbacks {
void (* service_match)(uint8_t sub_id, uint8_t pub_id, uint8_t pub_mac[6], uint16_t capab,
uint8_t ssi_ver, uint8_t *ssi, uint16_t ssi_len);
void (* replied)(uint8_t pub_id, uint8_t sub_id, uint8_t pub_mac[6], uint8_t *ssi, uint16_t ssi_len);
@@ -780,7 +780,7 @@ esp_err_t esp_nan_internal_datapath_end(wifi_nan_datapath_end_req_t *req);
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_nan_internal_register_callbacks(struct nan_callbacks *cb);
esp_err_t esp_nan_internal_register_callbacks(struct nan_sync_callbacks *cb);
/**
* @brief Connect WiFi station to the AP.
+2
View File
@@ -1788,6 +1788,8 @@ esp_err_t esp_wifi_action_tx_req(wifi_action_tx_req_t *req);
/**
* @brief Remain on the target channel for required duration
*
* @attention 1. The API returns ESP_ERR_INVALID_ARG when `req->allow_broadcast` is true and the device operates in AP+STA mode.
*
* @param req roc request structure containing relevant fields
*
* @return
@@ -592,7 +592,7 @@ typedef struct {
uint8_t master_pref; /**< Device's preference value to serve as NAN Master */
uint8_t scan_time; /**< Scan time in seconds while searching for a NAN cluster */
uint16_t warm_up_sec; /**< Warm up time before assuming NAN Anchor Master role */
} wifi_nan_config_t;
} wifi_nan_sync_config_t;
/**
* @brief Configuration data for device's AP or STA or NAN.
@@ -604,7 +604,7 @@ typedef struct {
typedef union {
wifi_ap_config_t ap; /**< Configuration of AP */
wifi_sta_config_t sta; /**< Configuration of STA */
wifi_nan_config_t nan; /**< Configuration of NAN */
wifi_nan_sync_config_t nan; /**< Configuration of NAN */
} wifi_config_t;
/**
@@ -798,6 +798,7 @@ typedef struct {
bool no_ack; /**< Indicates no ack required */
wifi_action_rx_cb_t rx_cb; /**< Rx Callback to receive action frames */
uint8_t op_id; /**< Unique Identifier for operation provided by wifi driver */
uint8_t bssid[6]; /**< BSSID (A3) address. If all zeroes, broadcast address will be used */
uint32_t data_len; /**< Length of the appended Data */
uint8_t data[0]; /**< Appended Data payload */
} wifi_action_tx_req_t;
@@ -830,9 +831,14 @@ typedef struct {
uint8_t channel; /**< Channel on which to perform ROC Operation */
wifi_second_chan_t sec_channel; /**< Secondary channel */
uint32_t wait_time_ms; /**< Duration to wait for on target channel */
wifi_action_rx_cb_t rx_cb; /**< Rx Callback to receive any response */
wifi_action_rx_cb_t rx_cb; /**< Rx Callback to receive action mgmt frames */
uint8_t op_id; /**< ID of this specific ROC operation provided by wifi driver */
wifi_action_roc_done_cb_t done_cb; /**< Callback to function that will be called upon ROC done. If assigned, WIFI_EVENT_ROC_DONE event will not be posted */
bool allow_broadcast; /**< If set to true, broadcast/multicast action frames from any network (Address3/BSSID=ANY)
will be received in the ROC Rx callback, enabling peer discovery.
If false (default), broadcast/multicast action frames from other networks
will be filtered out in hardware and not passed to the Rx callback, reducing CPU usage.
Frames whose Address3/BSSID is already broadcast are always delivered. */
} wifi_roc_req_t;
/**
@@ -846,7 +852,7 @@ typedef struct {
uint16_t burst_period; /**< Requested period between FTM bursts in 100's of milliseconds (allowed values 0(No pref) - 100) */
} wifi_ftm_initiator_cfg_t;
#define ESP_WIFI_NAN_MAX_SVC_SUPPORTED 2 /**< Maximum number of NAN services supported */
#define ESP_WIFI_NAN_MAX_SVC_SUPPORTED 2 /**< Maximum number of NAN or NAN-USD services supported */
#define ESP_WIFI_NAN_DATAPATH_MAX_PEERS 2 /**< Maximum number of NAN datapath peers supported */
#define ESP_WIFI_NDP_ROLE_INITIATOR 1 /**< Initiator role for NAN Data Path */
@@ -878,7 +884,7 @@ typedef enum {
*/
typedef struct {
uint8_t wfa_oui[WIFI_OUI_LEN]; /**< WFA OUI - 0x50, 0x6F, 0x9A */
wifi_nan_svc_proto_t proto; /**< WFA defined protocol types */
uint8_t proto; /**< WFA defined protocol of type wifi_nan_svc_proto_t */
uint8_t payload[0]; /**< Service Info payload */
} wifi_nan_wfa_ssi_t;
@@ -893,6 +899,19 @@ typedef enum {
NAN_SUBSCRIBE_PASSIVE, /**< Passively listens to Publish frames */
} wifi_nan_service_type_t;
/**
* @brief USD specific configuration parameters
*
*/
typedef struct {
uint8_t usd_default_channel; /**< If not specified, default channel 6 is used */
wifi_scan_channel_bitmap_t usd_chan_bitmap; /**< Indicates publish channel list used in USD */
uint8_t n_min; /**< Indicates minimum value of dwell period N used in the USD (Nmin) */
uint8_t n_max; /**< Indicates maximum value of dwell period N used in the USD (Nmax) */
uint8_t m_min; /**< Indicates minimum value of dwell period M used in the USD (Mmin) */
uint8_t m_max; /**< Indicates maximum value of dwell period M used in the USD (Mmax)*/
} wifi_nan_usd_config_t;
/**
* @brief NAN Publish service configuration parameters
*
@@ -906,9 +925,13 @@ typedef struct {
uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
uint8_t ndp_resp_needed: 1; /**< 0 - Auto-Accept NDP Requests, 1 - Require explicit response with esp_wifi_nan_datapath_resp */
uint8_t reserved: 3; /**< Reserved */
uint8_t usd_discovery_flag: 1; /**< 0 - NAN Synchronization for Discovery, 1 - USD for Discovery. 'NAN Discovery flag' from specification */
uint8_t reserved: 2; /**< Reserved */
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_SVC_SSI_LEN */
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
unsigned int ttl; /**< Run publish function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
only one Publish message is transmitted */
wifi_nan_usd_config_t usd_publish_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
} wifi_nan_publish_cfg_t;
/**
@@ -923,9 +946,13 @@ typedef struct {
uint8_t datapath_reqd: 1; /**< NAN Datapath required for the service */
uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
uint8_t reserved: 4; /**< Reserved */
uint8_t usd_discovery_flag: 1; /**< 0 - NAN Synchronization for Discovery, 1 - USD for Discovery. 'NAN Discovery flag' from specification */
uint8_t reserved: 3; /**< Reserved */
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_SVC_SSI_LEN */
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
unsigned int ttl; /**< Run subscribe function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
the subscriber listens until the first service match is reported. */
wifi_nan_usd_config_t usd_subscribe_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
} wifi_nan_subscribe_cfg_t;
/**
@@ -1098,8 +1125,8 @@ typedef enum {
WIFI_EVENT_BTWT_SETUP, /**< bTWT setup */
WIFI_EVENT_BTWT_TEARDOWN, /**< bTWT teardown*/
WIFI_EVENT_NAN_STARTED, /**< NAN Discovery has started */
WIFI_EVENT_NAN_STOPPED, /**< NAN Discovery has stopped */
WIFI_EVENT_NAN_SYNC_STARTED, /**< NAN Synchronization Discovery has started */
WIFI_EVENT_NAN_SYNC_STOPPED, /**< NAN Synchronization Discovery has stopped */
WIFI_EVENT_NAN_SVC_MATCH, /**< NAN Service Discovery match found */
WIFI_EVENT_NAN_REPLIED, /**< Replied to a NAN peer with Service Discovery match */
WIFI_EVENT_NAN_RECEIVE, /**< Received a Follow-up message */
+1
View File
@@ -28,6 +28,7 @@ CONFIG_ESP32_WIFI_IRAM_OPT CONFIG_ESP_WIFI_IRAM_OPT
CONFIG_ESP32_WIFI_RX_IRAM_OPT CONFIG_ESP_WIFI_RX_IRAM_OPT
CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE CONFIG_ESP_WIFI_ENABLE_WPA3_SAE
CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA
CONFIG_ESP_WIFI_NAN_ENABLE CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
# renaming supplicant kconfig to esp_wifi kconfig
CONFIG_WPA_MBEDTLS_CRYPTO CONFIG_ESP_WIFI_MBEDTLS_CRYPTO
+13 -13
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -12,7 +12,7 @@
#include "esp_wifi_netif.h"
#include <string.h>
#include <inttypes.h>
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
#include "apps_private/wifi_apps_private.h"
#endif
#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP
@@ -170,7 +170,7 @@ static void wifi_default_action_sta_got_ip(void *arg, esp_event_base_t base, int
}
}
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
static void wifi_default_action_nan_started(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
if (s_wifi_netifs[WIFI_IF_NAN] != NULL) {
@@ -202,9 +202,9 @@ static esp_err_t clear_default_wifi_handlers(void)
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_AP_STOP, wifi_default_action_ap_stop);
#endif
esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_default_action_sta_got_ip);
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NAN_STARTED, wifi_default_action_nan_started);
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NAN_STOPPED, wifi_default_action_nan_stopped);
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NAN_SYNC_STARTED, wifi_default_action_nan_started);
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_NAN_SYNC_STOPPED, wifi_default_action_nan_stopped);
#endif
esp_unregister_shutdown_handler((shutdown_handler_t)esp_wifi_stop);
wifi_default_handlers_set = false;
@@ -258,13 +258,13 @@ static esp_err_t set_default_wifi_handlers(void)
goto fail;
}
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NAN_STARTED, wifi_default_action_nan_started, NULL);
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NAN_SYNC_STARTED, wifi_default_action_nan_started, NULL);
if (err != ESP_OK) {
goto fail;
}
err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NAN_STOPPED, wifi_default_action_nan_stopped, NULL);
err = esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_NAN_SYNC_STOPPED, wifi_default_action_nan_stopped, NULL);
if (err != ESP_OK) {
goto fail;
}
@@ -364,7 +364,7 @@ static inline esp_err_t esp_netif_attach_wifi(esp_netif_t *esp_netif, wifi_inter
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
&& wifi_if != WIFI_IF_AP
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
&& wifi_if != WIFI_IF_NAN
#endif
)) {
@@ -386,7 +386,7 @@ esp_err_t esp_netif_attach_wifi_ap(esp_netif_t *esp_netif)
}
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
esp_err_t esp_netif_attach_wifi_nan(esp_netif_t *esp_netif)
{
return esp_netif_attach_wifi(esp_netif, WIFI_IF_NAN);
@@ -425,7 +425,7 @@ esp_netif_t* esp_netif_create_default_wifi_sta(void)
return netif;
}
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
/**
* @brief User init default NAN (official API)
*/
@@ -465,7 +465,7 @@ esp_netif_t* esp_netif_create_wifi(wifi_interface_t wifi_if, const esp_netif_inh
} else if (wifi_if == WIFI_IF_AP) {
cfg.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP;
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
} else if (wifi_if == WIFI_IF_NAN) {
cfg.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_NAN;
#endif
+6 -6
View File
@@ -27,7 +27,7 @@
#if __has_include("esp_psram.h")
#include "esp_psram.h"
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
#include "apps_private/wifi_apps_private.h"
#endif
#ifdef CONFIG_ESP_WIFI_FTM_ENABLE
@@ -187,7 +187,7 @@ static esp_err_t wifi_deinit_internal(void)
ESP_LOGW(TAG, "Failed to unregister Rx callbacks");
}
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
esp_nan_app_deinit();
#endif
@@ -484,7 +484,7 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
esp_wifi_config_info();
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
esp_nan_app_init();
#endif
@@ -649,7 +649,7 @@ void create_new_bss_for_sa_query_failed_sta(uint8_t arg)
}
#endif /* CONFIG_ESP_WIFI_SOFTAP_SUPPORT */
#ifndef CONFIG_ESP_WIFI_NAN_ENABLE
#ifndef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
esp_err_t nan_start(void)
{
@@ -680,7 +680,7 @@ int wifi_create_nan(void)
return 0;
}
int wifi_nan_set_config_local(wifi_nan_config_t *p)
int wifi_nan_set_config_local(wifi_nan_sync_config_t *p)
{
/* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
return 0;
@@ -707,7 +707,7 @@ void nan_ndp_resp_timeout_process(void *p)
{
/* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
}
#endif /* CONFIG_ESP_WIFI_NAN_ENABLE */
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
#if CONFIG_IDF_TARGET_ESP32C2
#if CONFIG_ESP32C2_REV_MIN_FULL < 200
+2 -2
View File
@@ -46,7 +46,7 @@ static esp_err_t wifi_ap_receive(void *buffer, uint16_t len, void *eb)
}
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
static esp_err_t wifi_nan_receive(void *buffer, uint16_t len, void *eb)
{
return s_wifi_rxcbs[WIFI_IF_NAN](s_wifi_netifs[WIFI_IF_NAN], buffer, len, eb);
@@ -158,7 +158,7 @@ esp_err_t esp_wifi_register_if_rxcb(wifi_netif_driver_t ifx, esp_netif_receive_t
break;
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
case WIFI_IF_NAN:
rxcb = wifi_nan_receive;
break;
@@ -1 +1 @@
CONFIG_ESP_WIFI_NAN_ENABLE=y
CONFIG_ESP_WIFI_NAN_SYNC_ENABLE=y
@@ -15,7 +15,7 @@
extern "C" {
#endif
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
/**
* @brief Initialize the NAN App and required Data Structures
@@ -35,7 +35,7 @@ void esp_nan_app_deinit(void);
* @brief NAN App action handler for NAN Started event. Sets up other event handlers and
* initializes NAN App context
*
* @attention This API should be called in WIFI_EVENT_NAN_STARTED event handler
* @attention This API should be called in WIFI_EVENT_NAN_SYNC_STARTED event handler
*
* @param nan_netif Netif handle corresponding to NAN interface.
*/
@@ -45,11 +45,11 @@ void esp_nan_action_start(esp_netif_t *nan_netif);
* @brief NAN App action handler for NAN Stopped event. Clears other event handlers and
* resets NAN App context
*
* @attention This API should be called in WIFI_EVENT_NAN_STOPPED event handler
* @attention This API should be called in WIFI_EVENT_NAN_SYNC_STOPPED event handler
*/
void esp_nan_action_stop(void);
#endif /* CONFIG_ESP_WIFI_NAN_ENABLE */
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
#ifdef __cplusplus
}
@@ -15,7 +15,8 @@
extern "C" {
#endif
#define WIFI_NAN_CONFIG_DEFAULT() { \
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
#define WIFI_NAN_SYNC_CONFIG_DEFAULT() { \
.op_channel = 6, \
.master_pref = 2, \
.scan_time = 3, \
@@ -40,7 +41,8 @@ struct nan_peer_record {
};
/**
* @brief Start NAN Discovery with provided configuration
* @brief Start NAN Synchronization using the provided parameters.
* @note Discovery traffic begins only after publish/subscribe services are started.
*
* @attention This API should be called after esp_wifi_init().
*
@@ -50,69 +52,21 @@ struct nan_peer_record {
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg);
esp_err_t esp_wifi_nan_sync_start(const wifi_nan_sync_config_t *nan_cfg);
/**
* @brief Stop NAN Discovery, end NAN Services and Datapaths
* @brief Stop NAN Synchronization discovery and end publish/subscribe services
*
* @attention This API will end datapaths if any in NAN synchronization
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_stop(void);
esp_err_t esp_wifi_nan_sync_stop(void);
/**
* @brief Start Publishing a service to the NAN Peers in vicinity
*
* @attention This API should be called after esp_wifi_nan_start().
*
* @param publish_cfg Configuration parameters for publishing a service.
*
* @return
* - non-zero: Publish service identifier
* - zero: failed
*/
uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg);
/**
* @brief Subscribe for a service within the NAN cluster
*
* @attention This API should be called after esp_wifi_nan_start().
*
* @param subscribe_cfg Configuration parameters for subscribing for a service.
*
* @return
* - non-zero: Subscribe service identifier
* - zero: failed
*/
uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe_cfg);
/**
* @brief Send a follow-up message to the NAN Peer with matched service
*
* @attention This API should be called after a NAN service is discovered due to a match.
*
* @param fup_params Configuration parameters for sending a Follow-up message.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params);
/**
* @brief Cancel a NAN service
*
* @param service_id Publish/Subscribe service id to be cancelled.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_cancel_service(uint8_t service_id);
/**
* @brief Send NAN Datapath Request to a NAN Publisher with matched service
* @brief Send a NAN datapath request to a matched publisher within the synchronized NAN cluster
*
* @attention This API should be called by the Subscriber after a match occurs with a Publisher.
*
@@ -125,7 +79,7 @@ esp_err_t esp_wifi_nan_cancel_service(uint8_t service_id);
uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req);
/**
* @brief Respond to a NAN Datapath request with Accept or Reject
* @brief Respond to a NAN datapath request within the synchronized NAN cluster
*
* @attention This API should be called if ndp_resp_needed is set 1 in wifi_nan_publish_cfg_t and
* a WIFI_EVENT_NDP_INDICATION event is received due to an incoming NDP request.
@@ -139,7 +93,7 @@ uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req);
esp_err_t esp_wifi_nan_datapath_resp(wifi_nan_datapath_resp_t *resp);
/**
* @brief Terminate a NAN Datapath
* @brief Terminate an active NAN datapath within the synchronized NAN cluster
*
* @param req NAN Datapath end request parameters.
*
@@ -161,6 +115,7 @@ void esp_wifi_nan_get_ipv6_linklocal_from_mac(ip6_addr_t *ip6, uint8_t *mac_addr
* brief Get own Service information from Service ID OR Name.
*
* @attention If service information is to be fetched from service name, set own_svc_id as zero.
* @note Returns records discovered while participating in a synchronized NAN cluster.
*
* @param[inout] own_svc_id As input, it indicates Service ID to search for.
* As output, it indicates Service ID of the service found using Service Name.
@@ -171,11 +126,14 @@ void esp_wifi_nan_get_ipv6_linklocal_from_mac(ip6_addr_t *ip6, uint8_t *mac_addr
* - ESP_OK: succeed
* - ESP_FAIL: failed
*/
esp_err_t esp_wifi_nan_get_own_svc_info(uint8_t *own_svc_id, char *svc_name, int *num_peer_records);
/**
* brief Get a list of Peers discovered by the given Service.
*
* @note Reports peers discovered via synchronized NAN operations.
*
* @param[inout] num_peer_records As input param, it stores max peers peer_record can hold.
* As output param, it specifies the actual number of peers this API returns.
* @param own_svc_id Service ID of own service.
@@ -184,11 +142,14 @@ esp_err_t esp_wifi_nan_get_own_svc_info(uint8_t *own_svc_id, char *svc_name, int
* - ESP_OK: succeed
* - ESP_FAIL: failed
*/
esp_err_t esp_wifi_nan_get_peer_records(int *num_peer_records, uint8_t own_svc_id, struct nan_peer_record *peer_record);
/**
* brief Find Peer's Service information using Peer MAC and optionally Service Name.
*
* @note Provides peer information available from synchronized NAN discovery.
*
* @param svc_name Service Name of the published/subscribed service.
* @param peer_mac Peer's NAN Management Interface MAC address.
* @param[out] peer_info Peer's service information structure.
@@ -196,8 +157,141 @@ esp_err_t esp_wifi_nan_get_peer_records(int *num_peer_records, uint8_t own_svc_i
* - ESP_OK: succeed
* - ESP_FAIL: failed
*/
esp_err_t esp_wifi_nan_get_peer_info(char *svc_name, uint8_t *peer_mac, struct nan_peer_record *peer_info);
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
#if defined(CONFIG_ESP_WIFI_NAN_SYNC_ENABLE) || defined(CONFIG_ESP_WIFI_NAN_USD_ENABLE)
/**
* @brief Start publishing a service to NAN peers within a synchronized cluster or to NAN-USD peers
*
* @attention Call after `esp_wifi_nan_sync_start()` when operating in NAN-Sync, or after
* `esp_wifi_nan_usd_start()` when operating in NAN-USD.
* @attention When NAN-USD discovery is active the publish request is routed through the
* USD engine, otherwise it uses NAN synchronization.
* @attention A maximum of two services is allowed simultaneously
* (e.g., one publish and one subscribe, or two publish/subscribe).
* This limit is defined by the ESP_WIFI_NAN_MAX_SVC_SUPPORTED.
*
* @param publish_cfg Configuration parameters for publishing a service.
* When operating in NAN-USD, populate `publish_cfg->usd_publish_config`
* (for example using `esp_wifi_usd_get_default_publish_cfg()`) to tune
* the USD dwell and channel parameters.
*
* @return
* - non-zero: Publish service identifier
* - zero: failed
*/
uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg);
/**
* @brief Subscribe to a service published by a NAN peer within a synchronized cluster or by a NAN-USD peer
*
* @attention Call after `esp_wifi_nan_sync_start()` when operating in NAN-Sync, or after
* `esp_wifi_nan_usd_start()` when operating in NAN-USD.
* @attention With NAN-USD discovery enabled the subscribe request is handled by the USD
* engine, otherwise it uses NAN synchronization.
* @attention A maximum of two services is allowed simultaneously
* (e.g., one publish and one subscribe, or two publish/subscribe).
* This limit is defined by the ESP_WIFI_NAN_MAX_SVC_SUPPORTED.
*
* @param subscribe_cfg Configuration parameters for subscribing for a service.
* When operating in NAN-USD, populate `subscribe_cfg->usd_subscribe_config`
* (for example using `esp_wifi_usd_get_default_subscribe_cfg()`) to tune
* the USD dwell and channel parameters.
*
* @return
* - non-zero: Subscribe service identifier
* - zero: failed
*/
uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe_cfg);
/**
* @brief Send a follow-up message to a matched peer in NAN synchronization or USD
*
* @attention This API should be called after a NAN/USD service is discovered due to a match.
*
* @param fup_params Configuration parameters for sending a Follow-up message.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params);
/**
* @brief Cancel a NAN synchronization or NAN-USD service
*
* @param service_id Publish/Subscribe service id to be cancelled.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_cancel_service(uint8_t service_id);
#endif /* NAN-Sync || NAN-USD */
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
/**
* @brief Start NAN Unsynchronized service discovery (USD)
*
* @attention This API should be called after esp_wifi_start().
* @note USD currently operates over the Station interface; this may change in future releases.
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_usd_start(void);
/**
* @brief Stop NAN Unsynchronized service discovery (USD) and end publish/subscribe services
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_nan_usd_stop(void);
/**
* @brief Get default configuration for USD publish operation.
*
* @note This function returns a default configuration structure for initiating
* a USD (Unsynchronized Service Discovery) publish session.
* - The default channel is set to channel 6 (2.437 GHz) in the 2.4 GHz band.
* - The channel list will include all 20 MHz channels in the 2.4 GHz frequency band,
* as permitted by the regulatory domain of the current geographic location.
* - Default values for dwell periods are set as per Wi-Fi Aware Specification:
* - Nmin = 5, Nmax = 10
* - Mmin = 5, Mmax = 10
*
* @return wifi_nan_usd_config_t structure with pre-filled default values for publishing.
*/
wifi_nan_usd_config_t esp_wifi_usd_get_default_publish_cfg(void);
/**
* @brief Get default configuration for USD subscribe operation.
*
* @note This function returns a default configuration structure for initiating
* a USD (Unsynchronized Service Discovery) subscribe session.
* - The default channel is set to channel 6 (2.437 GHz) in the 2.4 GHz band.
* - The channel list will include all 20 MHz channels in the 2.4 GHz frequency band,
* as permitted by the regulatory domain of the current geographic location.
* - Default values for dwell periods are set as per Wi-Fi Aware Specification:
* - Nmin = 5, Nmax = 10
* - Mmin = 5, Mmax = 10
*
* @warning Currently, the subscribe function operates only on the default channel.
* It does not alternate between the default channel and channels in the channel list.
*
* @return wifi_nan_usd_config_t structure with pre-filled default values for subscribing.
*/
wifi_nan_usd_config_t esp_wifi_usd_get_default_subscribe_cfg(void);
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
#ifdef __cplusplus
}
#endif
@@ -17,6 +17,9 @@
#include "os.h"
#include "esp_nan.h"
#include "utils/common.h"
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
#include "esp_private/esp_nan_usd.h"
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
/* NAN States */
#define NAN_STARTED_BIT BIT0
@@ -42,18 +45,27 @@
/* Global Variables */
static const char *TAG = "nan_app";
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
static EventGroupHandle_t nan_event_group;
static bool s_app_default_handlers_set = false;
static uint8_t null_mac[MACADDR_LEN] = {0};
static void *s_nan_data_lock = NULL;
static const uint8_t s_wfa_oui[3] = {0x50, 0x6f, 0x9a};
static uint32_t s_fup_context;
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
static bool s_usd_in_progress = false;
static const uint8_t s_wfa_oui[3] = {0x50, 0x6f, 0x9a};
/* Definitions */
#define NAN_SDEA_CTRL_FSD_REQD BIT(0)
#define NAN_SDEA_CTRL_FSD_GAS BIT(1)
#define NAN_SDEA_CTRL_DATAPATH_REQD BIT(2)
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
#define NAN_DATA_LOCK() os_mutex_lock(s_nan_data_lock)
#define NAN_DATA_UNLOCK() os_mutex_unlock(s_nan_data_lock)
struct peer_svc_info {
SLIST_ENTRY(peer_svc_info) next;
uint8_t peer_svc_info[ESP_WIFI_MAX_SVC_INFO_LEN]; /**< Information for followup message */
@@ -748,7 +760,7 @@ void esp_nan_action_start(esp_netif_t *nan_netif)
s_nan_ctx.state = NAN_STARTED_BIT;
NAN_DATA_UNLOCK();
struct nan_callbacks nan_cb = {
struct nan_sync_callbacks nan_cb = {
.service_match = nan_app_service_match_cb,
.replied = nan_app_replied_cb,
.receive = nan_app_receive_cb,
@@ -782,11 +794,10 @@ void esp_nan_action_stop(void)
os_event_group_set_bits(nan_event_group, NAN_STOPPED_BIT);
}
esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg)
esp_err_t esp_wifi_nan_sync_start(const wifi_nan_sync_config_t *nan_cfg)
{
wifi_mode_t mode;
esp_err_t ret;
wifi_config_t config = {0};
ret = esp_wifi_get_mode(&mode);
if (ret == ESP_ERR_WIFI_NOT_INIT) {
@@ -797,6 +808,10 @@ esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg)
return ret;
}
/* XXX: For now, NAN-USD and NAN-Sync can not coexist. */
/* NAN-Synchronization Only */
wifi_config_t config = {0};
if (!s_nan_data_lock) {
ESP_LOGE(TAG, "NAN Data lock doesn't exist");
return ESP_FAIL;
@@ -812,7 +827,7 @@ esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg)
ESP_RETURN_ON_ERROR(esp_wifi_set_mode(WIFI_MODE_NAN), TAG, "Set mode NAN failed");
memcpy(&config.nan, nan_cfg, sizeof(wifi_nan_config_t));
memcpy(&config.nan, nan_cfg, sizeof(wifi_nan_sync_config_t));
ESP_RETURN_ON_ERROR(esp_wifi_set_config(WIFI_IF_NAN, &config), TAG, "Setting NAN config failed");
if (esp_wifi_start() != ESP_OK) {
@@ -833,7 +848,7 @@ esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg)
return ESP_OK;
}
esp_err_t esp_wifi_nan_stop(void)
esp_err_t esp_wifi_nan_sync_stop(void)
{
NAN_DATA_LOCK();
if (!(s_nan_ctx.state & NAN_STARTED_BIT)) {
@@ -873,41 +888,77 @@ esp_err_t esp_wifi_nan_stop(void)
NAN_DATA_UNLOCK();
return ESP_OK;
}
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg)
{
uint8_t pub_id;
int pub_id;
if (publish_cfg->usd_discovery_flag && !s_usd_in_progress) {
ESP_LOGE(TAG, "Can not start Publish function with USD Discovery "
"when USD is not enabled");
return 0;
}
if (!publish_cfg->usd_discovery_flag && s_usd_in_progress) {
// XXX Add support for NAN-Sync and NAN-USD concurrent discovery
ESP_LOGE(TAG, "Can not start Publish function with "
"NAN-Synchronization Discovery when USD is enabled");
return 0;
}
if ((publish_cfg->ssi_len && publish_cfg->ssi == NULL) ||
(publish_cfg->ssi &&
(!publish_cfg->ssi_len ||
publish_cfg->ssi_len > ESP_WIFI_MAX_SVC_SSI_LEN))) {
ESP_LOGE(TAG, "Configured ssi and ssi_len(%d) incorrect",
publish_cfg->ssi_len);
return 0;
}
if (publish_cfg->ssi &&
!memcmp(publish_cfg->ssi, s_wfa_oui, sizeof(s_wfa_oui))) {
/* WFA defined Service Specific Info */
wifi_nan_wfa_ssi_t *wfa_ssi = (wifi_nan_wfa_ssi_t *)publish_cfg->ssi;
if (wfa_ssi->proto >= WIFI_SVC_PROTO_MAX) {
ESP_LOGI(TAG, "Unrecognized WFA Defined SSI protocol (%d)",
wfa_ssi->proto);
}
}
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
if (s_usd_in_progress) {
if ((pub_id = esp_nan_usd_publish(publish_cfg)) == -1) {
ESP_LOGE(TAG, "Failed to publish service '%s'",
publish_cfg->service_name);
return 0;
}
ESP_LOGI(TAG, "Started Publishing %s [Service ID - %u]",
publish_cfg->service_name, pub_id);
return pub_id;
}
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
NAN_DATA_LOCK();
if (!(s_nan_ctx.state & NAN_STARTED_BIT)) {
ESP_LOGE(TAG, "NAN not started!");
goto fail;
}
if (nan_services_limit_reached()) {
ESP_LOGE(TAG, "Maximum services limit reached");
goto fail;
}
if (nan_find_own_svc_by_name(publish_cfg->service_name)) {
ESP_LOGE(TAG, "Service name %s already used!", publish_cfg->service_name);
ESP_LOGE(TAG, "Service name %s already used!",
publish_cfg->service_name);
goto fail;
}
if ((publish_cfg->ssi_len && publish_cfg->ssi == NULL) ||
(publish_cfg->ssi && (!publish_cfg->ssi_len || publish_cfg->ssi_len > ESP_WIFI_MAX_SVC_SSI_LEN))) {
ESP_LOGE(TAG, "Configured ssi and ssi_len(%d) incorrect", publish_cfg->ssi_len);
goto fail;
}
if (publish_cfg->ssi && !memcmp(publish_cfg->ssi, s_wfa_oui, sizeof(s_wfa_oui))) {
/* WFA defined Service Specific Info */
wifi_nan_wfa_ssi_t *wfa_ssi = (wifi_nan_wfa_ssi_t *)publish_cfg->ssi;
if (wfa_ssi->proto >= WIFI_SVC_PROTO_MAX) {
ESP_LOGI(TAG, "Unrecognized WFA Defined SSI protocol (%d)", wfa_ssi->proto);
}
}
if (esp_nan_internal_publish_service(publish_cfg, &pub_id, false) != ESP_OK) {
if (esp_nan_internal_publish_service(publish_cfg, (uint8_t *) &pub_id, false) != ESP_OK) {
ESP_LOGE(TAG, "Failed to publish service '%s'", publish_cfg->service_name);
goto fail;
}
@@ -920,12 +971,55 @@ uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg)
fail:
NAN_DATA_UNLOCK();
return 0;
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
return 0;
}
uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe_cfg)
{
uint8_t sub_id;
int sub_id;
if (subscribe_cfg->usd_discovery_flag && !s_usd_in_progress) {
ESP_LOGE(TAG, "Can not start Subscribe function with USD Discovery "
"when USD is not enabled");
return 0;
}
if (!subscribe_cfg->usd_discovery_flag && s_usd_in_progress) {
// XXX Add support for NAN-Sync and NAN-USD concurrent discovery
ESP_LOGE(TAG, "Can not start Subscribe function with "
"NAN-Synchronization Discovery when USD is enabled");
return 0;
}
if ((subscribe_cfg->ssi_len && subscribe_cfg->ssi == NULL) ||
(subscribe_cfg->ssi && (!subscribe_cfg->ssi_len || subscribe_cfg->ssi_len > ESP_WIFI_MAX_SVC_SSI_LEN))) {
ESP_LOGE(TAG, "Configured ssi and ssi_len(%d) incorrect", subscribe_cfg->ssi_len);
return 0;
}
if (subscribe_cfg->ssi && !memcmp(subscribe_cfg->ssi, s_wfa_oui, sizeof(s_wfa_oui))) {
/* WFA defined Service Specific Info */
wifi_nan_wfa_ssi_t *wfa_ssi = (wifi_nan_wfa_ssi_t *)subscribe_cfg->ssi;
if (wfa_ssi->proto >= WIFI_SVC_PROTO_MAX) {
ESP_LOGI(TAG, "Unrecognized WFA Defined SSI protocol (%d)", wfa_ssi->proto);
}
}
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
if (s_usd_in_progress) {
if ((sub_id = esp_nan_usd_subscribe(subscribe_cfg)) == -1) {
ESP_LOGE(TAG, "Failed to subscribe to service '%s'",
subscribe_cfg->service_name);
return 0;
}
ESP_LOGI(TAG, "Started Subscribing to %s [Service ID - %u]",
subscribe_cfg->service_name, sub_id);
return sub_id;
}
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
NAN_DATA_LOCK();
if (!(s_nan_ctx.state & NAN_STARTED_BIT)) {
ESP_LOGE(TAG, "NAN not started!");
@@ -941,63 +1035,70 @@ uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe
goto fail;
}
if ((subscribe_cfg->ssi_len && subscribe_cfg->ssi == NULL) ||
(subscribe_cfg->ssi && (!subscribe_cfg->ssi_len || subscribe_cfg->ssi_len > ESP_WIFI_MAX_SVC_SSI_LEN))) {
ESP_LOGE(TAG, "Configured ssi and ssi_len(%d) incorrect", subscribe_cfg->ssi_len);
goto fail;
}
if (subscribe_cfg->ssi && !memcmp(subscribe_cfg->ssi, s_wfa_oui, sizeof(s_wfa_oui))) {
/* WFA defined Service Specific Info */
wifi_nan_wfa_ssi_t *wfa_ssi = (wifi_nan_wfa_ssi_t *)subscribe_cfg->ssi;
if (wfa_ssi->proto >= WIFI_SVC_PROTO_MAX) {
ESP_LOGI(TAG, "Unrecognized WFA Defined SSI protocol (%d)", wfa_ssi->proto);
}
}
if (esp_nan_internal_subscribe_service(subscribe_cfg, &sub_id, false) != ESP_OK) {
if (esp_nan_internal_subscribe_service(subscribe_cfg, (uint8_t*) &sub_id, false) != ESP_OK) {
ESP_LOGE(TAG, "Failed to subscribe to service '%s'", subscribe_cfg->service_name);
goto fail;
}
ESP_LOGI(TAG, "Started Subscribing to %s [Service ID - %u]", subscribe_cfg->service_name, sub_id);
nan_record_own_svc(sub_id, ESP_NAN_SUBSCRIBE, subscribe_cfg->service_name, false);
nan_record_own_svc((uint8_t) sub_id, ESP_NAN_SUBSCRIBE, subscribe_cfg->service_name, false);
NAN_DATA_UNLOCK();
return sub_id;
fail:
NAN_DATA_UNLOCK();
return 0;
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
return 0;
}
esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params)
{
struct peer_svc_info *p_peer_svc;
esp_err_t ret = ESP_OK;
if ((fup_params->ssi_len && fup_params->ssi == NULL) ||
(fup_params->ssi &&
(!fup_params->ssi_len ||
fup_params->ssi_len > ESP_WIFI_MAX_FUP_SSI_LEN))) {
ESP_LOGE(TAG, "Configured ssi and ssi_len(%d) incorrect",
fup_params->ssi_len);
return ESP_FAIL;
}
if (fup_params->ssi &&
!memcmp(fup_params->ssi, s_wfa_oui, sizeof(s_wfa_oui))) {
/* WFA defined Service Specific Info */
wifi_nan_wfa_ssi_t *wfa_ssi = (wifi_nan_wfa_ssi_t *)fup_params->ssi;
if (wfa_ssi->proto >= WIFI_SVC_PROTO_MAX) {
ESP_LOGI(TAG, "Unrecognized WFA Defined SSI protocol (%d)",
wfa_ssi->proto);
}
}
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
if (s_usd_in_progress) {
if (esp_nan_usd_transmit(fup_params->inst_id, fup_params->ssi,
fup_params->ssi_len, fup_params->peer_mac,
fup_params->peer_inst_id) != ESP_OK) {
ESP_LOGE(TAG, "Failed to send Follow-up message!");
return ESP_FAIL;
}
return ESP_OK;
}
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
struct peer_svc_info *p_peer_svc;
NAN_DATA_LOCK();
p_peer_svc = nan_find_peer_svc(fup_params->inst_id, fup_params->peer_inst_id,
fup_params->peer_mac);
p_peer_svc = nan_find_peer_svc(fup_params->inst_id,
fup_params->peer_inst_id, fup_params->peer_mac);
if (!p_peer_svc) {
ESP_LOGE(TAG, "Cannot send Follow-up, peer not found!");
NAN_DATA_UNLOCK();
return ESP_FAIL;
}
if ((fup_params->ssi_len && fup_params->ssi == NULL) ||
(fup_params->ssi && (!fup_params->ssi_len || fup_params->ssi_len > ESP_WIFI_MAX_FUP_SSI_LEN))) {
ESP_LOGE(TAG, "Configured ssi and ssi_len(%d) incorrect", fup_params->ssi_len);
return ESP_FAIL;
}
if (fup_params->ssi && !memcmp(fup_params->ssi, s_wfa_oui, sizeof(s_wfa_oui))) {
/* WFA defined Service Specific Info */
wifi_nan_wfa_ssi_t *wfa_ssi = (wifi_nan_wfa_ssi_t *)fup_params->ssi;
if (wfa_ssi->proto >= WIFI_SVC_PROTO_MAX) {
ESP_LOGI(TAG, "Unrecognized WFA Defined SSI protocol (%d)", wfa_ssi->proto);
}
}
if (!fup_params->inst_id) {
fup_params->inst_id = p_peer_svc->own_svc_id;
}
@@ -1018,9 +1119,12 @@ esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params)
EventBits_t bits = os_event_group_wait_bits(nan_event_group, NAN_TX_SUCCESS | NAN_TX_FAILURE, pdFALSE, pdFALSE, pdMS_TO_TICKS(NAN_ACTION_TIMEOUT));
if (bits & NAN_TX_SUCCESS) {
if (fup_params->ssi) {
ESP_LOGD(TAG, "Sent below payload to Peer "MACSTR" with Service ID %d",
ESP_LOGD(TAG, "Sent below payload in Follow-up message to Peer "MACSTR" with Service ID %d",
MAC2STR(fup_params->peer_mac), fup_params->peer_inst_id);
ESP_LOG_BUFFER_HEXDUMP(TAG, fup_params->ssi, fup_params->ssi_len, ESP_LOG_DEBUG);
} else {
ESP_LOGI(TAG, "Sent message to Peer "MACSTR" with Service ID %d",
MAC2STR(fup_params->peer_mac), fup_params->peer_inst_id);
}
ret = ESP_OK;
} else if (bits & NAN_TX_FAILURE) {
@@ -1030,12 +1134,19 @@ esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params)
ESP_LOGE(TAG, "Timeout, failed to send Follow-up message!");
ret = ESP_FAIL;
}
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
return ret;
}
esp_err_t esp_wifi_nan_cancel_service(uint8_t service_id)
{
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
if (s_usd_in_progress) {
return esp_nan_usd_cancel_service(service_id);
}
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
NAN_DATA_LOCK();
struct own_svc_info *p_own_svc = nan_find_own_svc(service_id);
@@ -1067,8 +1178,12 @@ fail:
done:
NAN_DATA_UNLOCK();
return ESP_OK;
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
return ESP_FAIL;
}
#ifdef CONFIG_ESP_WIFI_NAN_SYNC_ENABLE
uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req)
{
uint8_t ndp_id = 0;
@@ -1337,3 +1452,81 @@ esp_err_t esp_wifi_nan_get_peer_info(char *svc_name, uint8_t *peer_mac, struct n
return ESP_FAIL;
}
}
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
esp_err_t esp_wifi_nan_usd_start(void)
{
if (!s_usd_in_progress) {
ESP_RETURN_ON_ERROR(esp_wifi_set_mode(WIFI_MODE_STA), "NAN-USD", "Setting STA mode failed");
ESP_RETURN_ON_ERROR(esp_nan_usd_init(), "NAN-USD", "Failed to initialise NAN USD engine");
s_usd_in_progress = true;
ESP_LOGI(TAG, "NaN-USD Started");
return ESP_OK;
}
return ESP_OK;
}
esp_err_t esp_wifi_nan_usd_stop(void)
{
if (s_usd_in_progress) {
s_usd_in_progress = false;
esp_nan_usd_deinit();
ESP_LOGI(TAG, "NaN-USD Stopped");
return ESP_OK;
}
return ESP_OK;
}
wifi_nan_usd_config_t esp_wifi_usd_get_default_publish_cfg(void)
{
wifi_country_t country;
uint8_t start_chan, end_chan;
wifi_nan_usd_config_t cfg = {
.usd_default_channel = 6,
.n_min = 5,
.n_max = 10,
.m_min = 5,
.m_max = 10,
};
esp_wifi_get_country(&country);
start_chan = country.schan;
end_chan = country.schan + country.nchan - 1;
for (uint8_t chan = start_chan; chan <= end_chan; chan++) {
cfg.usd_chan_bitmap.ghz_2_channels |= CHANNEL_TO_BIT(chan);
}
#if CONFIG_SOC_WIFI_SUPPORT_5G
cfg.usd_chan_bitmap.ghz_5_channels = country.wifi_5g_channel_mask;
#endif
return cfg;
}
wifi_nan_usd_config_t esp_wifi_usd_get_default_subscribe_cfg(void)
{
wifi_country_t country;
uint8_t start_chan, end_chan;
wifi_nan_usd_config_t cfg = {
.usd_default_channel = 6,
.n_min = 5,
.n_max = 10,
.m_min = 5,
.m_max = 10
};
esp_wifi_get_country(&country);
start_chan = country.schan;
end_chan = country.schan + country.nchan - 1;
for (uint8_t chan = start_chan; chan <= end_chan; chan++) {
cfg.usd_chan_bitmap.ghz_2_channels |= CHANNEL_TO_BIT(chan);
}
#if CONFIG_SOC_WIFI_SUPPORT_5G
cfg.usd_chan_bitmap.ghz_5_channels = country.wifi_5g_channel_mask;
#endif
return cfg;
}
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
+13 -1
View File
@@ -240,12 +240,21 @@ else()
set(wps_registrar_src "")
endif()
if(CONFIG_ESP_WIFI_NAN_USD_ENABLE)
set(usd_src
"src/common/nan_de.c"
"esp_supplicant/src/esp_nan_usd.c")
else()
set(usd_src "")
endif()
idf_component_register(SRCS "${srcs}" "${esp_srcs}" "${tls_src}" "${roaming_src}"
"${crypto_src}" "${mbo_src}" "${dpp_src}" "${wps_registrar_src}"
"${crypto_src}" "${mbo_src}" "${dpp_src}" "${wps_registrar_src}" "${usd_src}"
INCLUDE_DIRS include port/include esp_supplicant/include
PRIV_INCLUDE_DIRS src src/utils esp_supplicant/src src/crypto
../esp_wifi/wifi_apps/roaming_app/include
../esp_wifi/wifi_apps/roaming_app/src
esp_supplicant/include/esp_private
LDFRAGMENTS ${linker_fragments}
PRIV_REQUIRES mbedtls esp_timer esp_wifi)
@@ -349,6 +358,9 @@ endif()
if(CONFIG_ESP_WIFI_EAP_TLS1_3)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_TLSV13)
endif()
if(CONFIG_ESP_WIFI_NAN_USD_ENABLE)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_NAN_USD)
endif()
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
@@ -0,0 +1,56 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_err.h"
#include "esp_wifi_types.h"
#define GLOBAL_OPERATING_CLASS_81 81
#define ESP_USD_SUBSCRIBE_DEFAULT_PARAMS() { \
.active = false, \
.ttl = 0, \
.freq = NAN_USD_DEFAULT_FREQ, \
.query_period = 0, \
};
#define ESP_USD_PUBLISH_DEFAULT_PARAMS() { \
.unsolicited = true, \
.solicited = true, \
.ttl = 100, \
.fsd = true, \
.freq = NAN_USD_DEFAULT_FREQ, \
.freq_list = NULL, \
};
/* Note: These NaN-USD APIs are intended for internal use only.
* For application development, use the public APIs provided in:
* 'wifi_apps/nan_app/include/esp_nan.h'
*/
esp_err_t esp_nan_usd_init(void);
esp_err_t esp_nan_usd_deinit(void);
int esp_nan_usd_publish(const wifi_nan_publish_cfg_t *publish_cfg);
esp_err_t esp_nan_usd_cancel_publish(int publish_id);
int esp_nan_usd_subscribe(const wifi_nan_subscribe_cfg_t *subscribe_cfg);
esp_err_t esp_nan_usd_cancel_subscribe(int subscribe_id);
esp_err_t esp_nan_usd_transmit(int handle, const uint8_t *ssi, uint16_t ssi_len,
const uint8_t *peer_addr, uint8_t req_instance_id);
esp_err_t esp_nan_usd_cancel_service(int service_id);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,679 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_wifi.h"
#include "esp_check.h"
#include "esp_nan_usd.h"
#include "common/nan_de.h"
#include "esp_wifi_driver.h"
#include "common/ieee802_11_common.h"
#include "utils/eloop.h"
#include "esp_nan.h"
struct nan_de *g_nan_de = NULL;
static void *s_nan_usd_data_lock = NULL;
#define NAN_USD_DATA_LOCK() os_mutex_lock(s_nan_usd_data_lock)
#define NAN_USD_DATA_UNLOCK() os_mutex_unlock(s_nan_usd_data_lock)
#ifdef DEBUG_PRINT
static const char *nan_reason_txt(enum nan_de_reason reason)
{
switch (reason) {
case NAN_DE_REASON_TIMEOUT:
return "timeout";
case NAN_DE_REASON_USER_REQUEST:
return "user-request";
case NAN_DE_REASON_FAILURE:
return "failure";
}
return "unknown";
}
#endif /* DEBUG_PRINT */
static void nan_sta_stop_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
if (event_id == WIFI_EVENT_STA_STOP) {
esp_wifi_nan_usd_stop();
}
}
/* Per section 4.5.3 of the Wi-Fi Aware Specification v4.0 (NaN-USD),
* only 20 MHz bandwidth channels are permitted for NAN-USD operation
* in both the 2.4 GHz and 5 GHz frequency bands.
* */
static int esp_nan_chan_to_freq(uint8_t chan)
{
// 2.4 GHz band
if (chan >= 1 && chan <= 13) {
return 2407 + 5 * chan;
} else if (chan == 14) {
return 2414 + 5 * chan;
}
// 5 GHz band — standard 20 MHz channel ranges
if ((chan >= 36 && chan <= 64) ||
(chan >= 100 && chan <= 144) ||
(chan >= 149 && chan <= 165)) {
return 5000 + chan * 5;
}
return -1;
}
static int esp_nan_freq_to_chan(int freq)
{
// 2.4 GHz band
if (freq >= 2412 && freq <= 2472) {
return (freq - 2407) / 5;
} else if (freq == 2484) {
return 14;
}
// 5 GHz band
if ((freq >= 5180 && freq <= 5240) || // Channels 3664
(freq >= 5500 && freq <= 5720) || // Channels 100144
(freq >= 5745 && freq <= 5825)) { // Channels 149165
return (freq - 5000) / 5;
}
return -1;
}
static void nan_de_tx_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
if (event_id == WIFI_EVENT_ACTION_TX_STATUS) {
wifi_event_action_tx_status_t *evt = (wifi_event_action_tx_status_t *)event_data;
if (evt->status == WIFI_ACTION_TX_DONE) {
int freq = esp_nan_chan_to_freq(evt->channel);
if (freq == -1) {
wpa_printf(MSG_ERROR, "Invalid channel received from Action Tx handler");
return;
}
NAN_USD_DATA_LOCK();
nan_de_tx_status(g_nan_de, freq, NULL);
NAN_USD_DATA_UNLOCK();
} else if (evt->status == WIFI_ACTION_TX_DURATION_COMPLETED) {
NAN_USD_DATA_LOCK();
nan_de_tx_wait_ended(g_nan_de);
NAN_USD_DATA_UNLOCK();
}
} else if (event_id == WIFI_EVENT_ROC_DONE) {
wifi_event_roc_done_t *evt = (wifi_event_roc_done_t *)event_data;
int freq = esp_nan_chan_to_freq(evt->channel);
if (freq == -1) {
wpa_printf(MSG_ERROR, "Invalid channel received from ROC done handler");
}
NAN_USD_DATA_LOCK();
nan_de_listen_ended(g_nan_de, freq);
NAN_USD_DATA_UNLOCK();
}
}
int esp_nan_de_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel)
{
struct ieee80211_hdr *rx_hdr = (struct ieee80211_hdr *)hdr;
int freq;
if (len < 6) {
/* Frame too short for NAN-SDF frame */
return ESP_FAIL;
}
/* NAN SDF
* Category code - 1 byte
* Public Action - 1 byte
* OUI - 3 bytes
* WFA subtype - 1 byte
* NAN PROTOCOL - Variable */
uint8_t category = *payload++;
uint8_t public_action = *payload++;
uint32_t oui_value = WPA_GET_BE24(payload);
payload += 3;
uint8_t oui_type = *payload++;
if (category == WLAN_ACTION_PUBLIC &&
public_action == WLAN_PA_VENDOR_SPECIFIC &&
oui_value == OUI_WFA &&
oui_type == NAN_OUI_TYPE) {
/* Received a valid NAN Service Discovery Frame */
} else {
/* Frame is not a NAN SDF frame */
return ESP_FAIL;
}
freq = esp_nan_chan_to_freq(channel);
if (freq == -1) {
wpa_printf(MSG_ERROR, "Invalid channel from Rx action frame");
return ESP_FAIL;
}
NAN_USD_DATA_LOCK();
nan_de_rx_sdf(g_nan_de, rx_hdr->addr2, rx_hdr->addr3, freq, payload, len - 6);
NAN_USD_DATA_UNLOCK();
return ESP_OK;
}
static int esp_nan_de_tx(void *ctx, unsigned int freq, unsigned int wait_time,
const u8 *dst, const u8 *src, const u8 *bssid,
const struct wpabuf *buf)
{
int buf_len = buf->used;
int channel;
wifi_action_tx_req_t *req = os_zalloc(sizeof(*req) + buf_len);
if (!req) {
wpa_printf(MSG_ERROR, "Allocation for tx request failed");
return ESP_FAIL;
}
req->ifx = WIFI_IF_STA;
req->type = WIFI_OFFCHAN_TX_REQ;
req->wait_time_ms = wait_time;
memcpy(req->dest_mac, dst, ETH_ALEN);
memcpy(req->bssid, bssid, ETH_ALEN);
req->no_ack = false;
req->data_len = buf_len;
req->rx_cb = esp_nan_de_rx_action;
memcpy(req->data, buf->buf, buf_len);
channel = esp_nan_freq_to_chan(freq);
if (channel == -1) {
wpa_printf(MSG_ERROR, "Could not determine channel for freq %d", freq);
os_free(req);
return ESP_FAIL;
}
req->channel = channel;
if (esp_wifi_action_tx_req(req) != ESP_OK) {
wpa_printf(MSG_ERROR, "Offchannel tx request failed");
os_free(req);
return ESP_FAIL;
}
os_free(req);
return ESP_OK;
}
static int esp_nan_de_listen(void *ctx, unsigned int freq, unsigned int duration)
{
int channel;
channel = esp_nan_freq_to_chan(freq);
if (channel == -1) {
wpa_printf(MSG_ERROR, "Could not determine channel for freq %d", freq);
return ESP_FAIL;
}
wifi_roc_req_t *req = os_zalloc(sizeof(wifi_roc_req_t));
if (req == NULL) {
wpa_printf(MSG_ERROR, "Failed to allocate for ROC request");
return ESP_FAIL;
}
req->ifx = WIFI_IF_STA;
req->type = WIFI_ROC_REQ;
req->channel = channel;
req->wait_time_ms = duration;
req->rx_cb = esp_nan_de_rx_action;
req->done_cb = NULL;
req->allow_broadcast = true;
if (esp_wifi_remain_on_channel(req) != ESP_OK) {
wpa_printf(MSG_ERROR, "ROC request failure");
os_free(req);
return ESP_FAIL;
}
NAN_USD_DATA_LOCK();
nan_de_listen_started(g_nan_de, freq, duration);
NAN_USD_DATA_UNLOCK();
os_free(req);
return ESP_OK;
}
static void esp_nan_de_discovery_result(void *ctx, int subscribe_id, enum nan_service_protocol_type srv_proto_type,
const u8 *ssi, size_t ssi_len, int peer_publish_id, const u8 *peer_addr, bool fsd, bool fsd_gas)
{
wpa_printf(MSG_INFO, "NAN_USD DISCOVERY_RESULT - subscribe_id = %d peer_publish_id = %d peer_address = "MACSTR" service_protocol_type = %d",
subscribe_id, peer_publish_id, MAC2STR(peer_addr), srv_proto_type);
wifi_event_nan_svc_match_t *evt = os_zalloc(sizeof(wifi_event_nan_svc_match_t) + ssi_len);
if (evt == NULL) {
return;
}
evt->subscribe_id = subscribe_id;
evt->publish_id = peer_publish_id;
memcpy(evt->pub_if_mac, peer_addr, ETH_ALEN);
if (ssi && ssi_len) {
memcpy(evt->ssi, ssi, ssi_len);
evt->ssi_len = ssi_len;
}
esp_event_post(WIFI_EVENT, WIFI_EVENT_NAN_SVC_MATCH, evt, sizeof(wifi_event_nan_svc_match_t) + ssi_len, portMAX_DELAY);
os_free(evt);
}
static void esp_nan_de_replied(void *ctx, int publish_id, const u8 *peer_addr,
int peer_subscribe_id,
enum nan_service_protocol_type srv_proto_type,
const u8 *ssi, size_t ssi_len)
{
wpa_printf(MSG_INFO, "NAN_USD REPLIED - publish_id = %d peer_subscribe_id = %d peer_address = "MACSTR" service_protocol_type = %d",
publish_id, peer_subscribe_id, MAC2STR(peer_addr), srv_proto_type);
wifi_event_nan_replied_t *evt = os_zalloc(sizeof(wifi_event_nan_replied_t) + ssi_len);
if (evt == NULL) {
return;
}
evt->publish_id = publish_id;
evt->subscribe_id = peer_subscribe_id;
memcpy(evt->sub_if_mac, peer_addr, ETH_ALEN);
if (ssi && ssi_len) {
memcpy(evt->ssi, ssi, ssi_len);
evt->ssi_len = ssi_len;
}
esp_event_post(WIFI_EVENT, WIFI_EVENT_NAN_REPLIED, evt, sizeof(wifi_event_nan_replied_t) + ssi_len, portMAX_DELAY);
os_free(evt);
}
static void esp_nan_de_publish_terminated(void *ctx, int publish_id,
enum nan_de_reason reason)
{
wpa_printf(MSG_INFO, "NAN_USD PUBLISH_TERMINATED - publish_id = %d reason = %s", publish_id, nan_reason_txt(reason));
}
static void esp_nan_de_subscribe_terminated(void *ctx, int subscribe_id,
enum nan_de_reason reason)
{
wpa_printf(MSG_INFO, "NAN_USD SUBSCRIBE_TERMINATED - subscribe_id = %d reason = %s", subscribe_id, nan_reason_txt(reason));
}
static void esp_nan_de_receive(void *ctx, int id, int peer_instance_id,
const u8 *ssi, size_t ssi_len,
const u8 *peer_addr)
{
wpa_hexdump(MSG_INFO, "NAN_RECEIVE", ssi, ssi_len);
wifi_event_nan_receive_t *evt = os_zalloc(sizeof(wifi_event_nan_receive_t) + ssi_len);
if (evt == NULL) {
return;
}
evt->inst_id = id;
evt->peer_inst_id = peer_instance_id;
memcpy(evt->peer_if_mac, peer_addr, ETH_ALEN);
if (ssi && ssi_len) {
memcpy(evt->ssi, ssi, ssi_len);
evt->ssi_len = ssi_len;
}
esp_event_post(WIFI_EVENT, WIFI_EVENT_NAN_RECEIVE, evt, sizeof(wifi_event_nan_receive_t) + ssi_len, portMAX_DELAY);
os_free(evt);
}
esp_err_t esp_nan_usd_deinit()
{
NAN_USD_DATA_LOCK();
if (!g_nan_de) {
NAN_USD_DATA_UNLOCK();
return ESP_FAIL;
}
nan_de_deinit(g_nan_de);
g_nan_de = NULL;
NAN_USD_DATA_UNLOCK();
if (s_nan_usd_data_lock) {
os_mutex_delete(s_nan_usd_data_lock);
s_nan_usd_data_lock = NULL;
}
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_ACTION_TX_STATUS, &nan_de_tx_event_handler);
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_ROC_DONE, &nan_de_tx_event_handler);
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_STOP,
&nan_sta_stop_handler);
return ESP_OK;
}
esp_err_t esp_nan_usd_init(void)
{
struct nan_callbacks cb;
uint8_t mac[ETH_ALEN];
#ifndef ESP_SUPPLICANT
bool offload = wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD;
#else
bool offload = false;
#endif
int max_listen = 1000; // default supplicant value; hardcoded for now
os_memset(&cb, 0, sizeof(cb));
cb.ctx = NULL;
cb.tx = esp_nan_de_tx;
cb.listen = esp_nan_de_listen;
cb.discovery_result = esp_nan_de_discovery_result;
cb.replied = esp_nan_de_replied;
cb.publish_terminated = esp_nan_de_publish_terminated;
cb.subscribe_terminated = esp_nan_de_subscribe_terminated;
cb.receive = esp_nan_de_receive;
s_nan_usd_data_lock = os_recursive_mutex_create();
if (!s_nan_usd_data_lock) {
ESP_LOGE("NAN-USD", "Failed to create NAN-USD data lock");
return ESP_FAIL;
}
ESP_RETURN_ON_ERROR(esp_wifi_get_mac(WIFI_IF_STA, mac), "NAN-USD", "Fetching MAC of STA ifx failed");
g_nan_de = nan_de_init(mac, offload, false, max_listen, &cb);
if (!g_nan_de) {
return ESP_FAIL;
}
esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_ACTION_TX_STATUS,
&nan_de_tx_event_handler, NULL);
esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_ROC_DONE,
&nan_de_tx_event_handler, NULL);
esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_STOP,
&nan_sta_stop_handler, NULL);
return ESP_OK;
}
int esp_nan_get_freq_list(int *freq_list, const uint8_t *chan_list, uint8_t chan_list_len)
{
int freq, freq_ind = 0;
for (int i = 0; i < chan_list_len; i++) {
freq = esp_nan_chan_to_freq(chan_list[i]);
if (freq != -1) {
freq_list[freq_ind++] = freq;
}
}
freq_list[freq_ind++] = 0;
return freq_ind;
}
static int esp_nan_usd_publish_internal(const char *service_name, enum nan_service_protocol_type srv_proto_type,
unsigned int ttl, uint8_t *ssi, uint16_t ssi_len, uint8_t default_channel,
const wifi_scan_channel_bitmap_t channel_bitmap)
{
int publish_id;
struct wpabuf *buf = NULL;
int freq, *freq_list = NULL;
struct nan_publish_params pub_params = ESP_USD_PUBLISH_DEFAULT_PARAMS();
bool p2p = false;
uint8_t i = 0, chan_list_len;
uint8_t bitmap_idx_2g = 1; // BIT-0 is not used in channel bitmap
uint16_t channel_2ghz_bitmap;
#if CONFIG_SOC_WIFI_SUPPORT_5G
uint8_t bitmap_idx_5g = 1; // BIT-0 is not used in channel bitmap
uint32_t channel_5ghz_bitmap;
#endif
NAN_USD_DATA_LOCK();
if (!g_nan_de) {
goto fail;
}
pub_params.ttl = ttl;
if (ssi && ssi_len) {
buf = wpabuf_alloc(ssi_len);
if (!buf) {
wpa_printf(MSG_ERROR, "Allocating memory failed for NaN-USD Publish");
goto fail;
}
wpabuf_put_data(buf, ssi, ssi_len);
}
freq = esp_nan_chan_to_freq(default_channel);
if (freq != -1) {
pub_params.freq = freq;
} else {
pub_params.freq = NAN_USD_DEFAULT_FREQ;
}
channel_2ghz_bitmap = channel_bitmap.ghz_2_channels;
channel_2ghz_bitmap &= ~BIT(0); // BIT-0 is not used for channel
chan_list_len = __builtin_popcount(channel_2ghz_bitmap);
#if CONFIG_SOC_WIFI_SUPPORT_5G
channel_5ghz_bitmap = channel_bitmap.ghz_5_channels;
channel_5ghz_bitmap &= ~BIT(0); // BIT-0 is not used for channel
chan_list_len += __builtin_popcount(channel_5ghz_bitmap);
#endif
if (chan_list_len) {
uint8_t chan_list[chan_list_len];
while (channel_2ghz_bitmap) {
bitmap_idx_2g = __builtin_ctz(channel_2ghz_bitmap);
uint8_t chan_num = BIT_NUMBER_TO_CHANNEL(bitmap_idx_2g, WIFI_BAND_2G);
if (chan_num != 0) {
chan_list[i++] = chan_num;
}
channel_2ghz_bitmap &= ~BIT(bitmap_idx_2g);
}
#if CONFIG_SOC_WIFI_SUPPORT_5G
while (channel_5ghz_bitmap) {
bitmap_idx_5g = __builtin_ctz(channel_5ghz_bitmap);
uint8_t chan_num = BIT_NUMBER_TO_CHANNEL(bitmap_idx_5g, WIFI_BAND_5G);
if (chan_num != 0) {
chan_list[i++] = chan_num;
}
channel_5ghz_bitmap &= ~BIT(bitmap_idx_5g);
}
#endif
chan_list_len = i;
freq_list = (int *)os_malloc(sizeof(int) * (chan_list_len + 1));
if (freq_list) {
esp_nan_get_freq_list(freq_list, chan_list, chan_list_len);
pub_params.freq_list = freq_list;
} else {
wpa_printf(MSG_ERROR, "Allocating memory failed for frequency list");
wpabuf_free(buf);
goto fail;
}
}
publish_id = nan_de_publish(g_nan_de, service_name, srv_proto_type,
buf, NULL, &pub_params, p2p);
wpabuf_free(buf);
if (freq_list) {
os_free(freq_list);
}
NAN_USD_DATA_UNLOCK();
return publish_id;
fail:
NAN_USD_DATA_UNLOCK();
return -1;
}
int esp_nan_usd_publish(const wifi_nan_publish_cfg_t *publish_cfg)
{
return esp_nan_usd_publish_internal(publish_cfg->service_name, WIFI_SVC_PROTO_RESERVED,
publish_cfg->ttl, publish_cfg->ssi,
publish_cfg->ssi_len, publish_cfg->usd_publish_config.usd_default_channel,
publish_cfg->usd_publish_config.usd_chan_bitmap);
}
esp_err_t esp_nan_usd_update_publish(int publish_id, uint8_t *ssi, uint16_t ssi_len)
{
struct wpabuf *buf = NULL;
esp_err_t ret;
NAN_USD_DATA_LOCK();
if (!g_nan_de) {
goto fail;
}
if (ssi && ssi_len) {
buf = wpabuf_alloc(ssi_len);
if (!buf) {
wpa_printf(MSG_ERROR, "Allocating memory failed for NaN-USD Update Publish");
goto fail;
}
wpabuf_put_data(buf, ssi, ssi_len);
}
ret = nan_de_update_publish(g_nan_de, publish_id, buf);
wpabuf_free(buf);
NAN_USD_DATA_UNLOCK();
return ret;
fail:
NAN_USD_DATA_UNLOCK();
return ESP_FAIL;
}
esp_err_t esp_nan_usd_cancel_publish(int publish_id)
{
NAN_USD_DATA_LOCK();
if (!g_nan_de) {
NAN_USD_DATA_UNLOCK();
return ESP_FAIL;
}
nan_de_cancel_publish(g_nan_de, publish_id);
NAN_USD_DATA_UNLOCK();
return ESP_OK;
}
/* Note: Our USD implementation uses the Service Protocol Type provided in SSI.
* The 'srv_proto_type' parameter will be ignored.
*/
static int esp_nan_usd_subscribe_internal(const char *service_name, enum nan_service_protocol_type srv_proto_type,
unsigned int ttl, uint8_t default_channel, uint8_t *ssi, uint16_t ssi_len,
const wifi_scan_channel_bitmap_t channel_bitmap)
{
int subscribe_id;
struct wpabuf *buf = NULL;
int freq, *freq_list = NULL;
/* USD Specification allows either active or passive mode for subscriber.
* By default USD-Subscriber will be in passive mode */
struct nan_subscribe_params sub_params = ESP_USD_SUBSCRIBE_DEFAULT_PARAMS();
bool p2p = false;
uint8_t i = 0, chan_list_len;
uint8_t bitmap_idx_2g = 1; // BIT-0 is not used in channel bitmap
uint16_t channel_2ghz_bitmap;
NAN_USD_DATA_LOCK();
if (!g_nan_de) {
goto fail;
}
sub_params.ttl = ttl;
freq = esp_nan_chan_to_freq(default_channel);
if (freq != -1) {
sub_params.freq = freq;
} else {
sub_params.freq = NAN_USD_DEFAULT_FREQ;
}
if (ssi && ssi_len) {
buf = wpabuf_alloc(ssi_len);
if (!buf) {
wpa_printf(MSG_ERROR, "Allocating memory failed for NaN-USD Subscribe");
goto fail;
}
wpabuf_put_data(buf, ssi, ssi_len);
}
channel_2ghz_bitmap = channel_bitmap.ghz_2_channels;
channel_2ghz_bitmap &= ~BIT(0); // BIT-0 is not used for channel
chan_list_len = __builtin_popcount(channel_2ghz_bitmap);
if (chan_list_len) {
uint8_t chan_list[chan_list_len];
while (channel_2ghz_bitmap) {
bitmap_idx_2g = __builtin_ctz(channel_2ghz_bitmap);
uint8_t chan_num = BIT_NUMBER_TO_CHANNEL(bitmap_idx_2g, WIFI_BAND_2G);
if (chan_num != 0) {
chan_list[i++] = chan_num;
}
channel_2ghz_bitmap &= ~BIT(bitmap_idx_2g);
}
freq_list = (int *)os_malloc(sizeof(int) * (chan_list_len + 1));
if (freq_list) {
esp_nan_get_freq_list(freq_list, chan_list, chan_list_len);
sub_params.freq_list = freq_list;
} else {
wpa_printf(MSG_ERROR, "Allocating memory failed for frequency list");
wpabuf_free(buf);
goto fail;
}
}
subscribe_id = nan_de_subscribe(g_nan_de, service_name, srv_proto_type, buf, NULL, &sub_params, p2p);
wpabuf_free(buf);
if (freq_list) {
os_free(freq_list);
}
NAN_USD_DATA_UNLOCK();
return subscribe_id;
fail:
NAN_USD_DATA_UNLOCK();
return -1;
}
int esp_nan_usd_subscribe(const wifi_nan_subscribe_cfg_t *subscribe_cfg)
{
return esp_nan_usd_subscribe_internal(subscribe_cfg->service_name, WIFI_SVC_PROTO_RESERVED, subscribe_cfg->ttl,
subscribe_cfg->usd_subscribe_config.usd_default_channel, subscribe_cfg->ssi, subscribe_cfg->ssi_len,
subscribe_cfg->usd_subscribe_config.usd_chan_bitmap);
}
esp_err_t esp_nan_usd_cancel_subscribe(int subscribe_id)
{
NAN_USD_DATA_LOCK();
if (!g_nan_de) {
NAN_USD_DATA_UNLOCK();
return ESP_FAIL;
}
nan_de_cancel_subscribe(g_nan_de, subscribe_id);
NAN_USD_DATA_UNLOCK();
return ESP_OK;
}
esp_err_t esp_nan_usd_cancel_service(int service_id)
{
NAN_USD_DATA_LOCK();
if (!g_nan_de) {
NAN_USD_DATA_UNLOCK();
return ESP_FAIL;
}
nan_de_cancel_service(g_nan_de, service_id);
NAN_USD_DATA_UNLOCK();
return ESP_OK;
}
esp_err_t esp_nan_usd_transmit(int handle, const uint8_t *ssi, uint16_t ssi_len, const u8 *peer_addr, u8 req_instance_id)
{
struct wpabuf *buf = NULL;
esp_err_t ret;
NAN_USD_DATA_LOCK();
if (!g_nan_de || !peer_addr) {
goto fail;
}
if (ssi && ssi_len) {
buf = wpabuf_alloc(ssi_len);
if (!buf) {
wpa_printf(MSG_ERROR, "Allocating memory failed for NaN-USD transmit");
goto fail;
}
wpabuf_put_data(buf, ssi, ssi_len);
}
ret = nan_de_transmit(g_nan_de, handle, buf, NULL, peer_addr, req_instance_id);
wpabuf_free(buf);
NAN_USD_DATA_UNLOCK();
return ret;
fail:
NAN_USD_DATA_UNLOCK();
return ESP_FAIL;
}
@@ -567,8 +567,12 @@ struct ieee80211_ht_operation {
/* 2 - Reserved */
#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3
#define MBO_IE_VENDOR_TYPE 0x506f9a16
#define OSEN_IE_VENDOR_TYPE 0x506f9a12
#define NAN_IE_VENDOR_TYPE 0x506f9a13
#define NAN_SDF_VENDOR_TYPE 0x506f9a13
#define NAN_OUI_TYPE 0x13
#define MBO_IE_VENDOR_TYPE 0x506f9a16
#define NAN_NAF_VENDOR_TYPE 0x506f9a18
#define SAE_PK_IE_VENDOR_TYPE 0x506f9a1f
#define SAE_PK_OUI_TYPE 0x1f
#define MBO_OUI_TYPE 22
@@ -0,0 +1,98 @@
/*
* NAN (Wi-Fi Aware) definitions
* Copyright (c) 2024, Qualcomm Innovation Center, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef NAN_H
#define NAN_H
enum nan_attr_id {
NAN_ATTR_MASTER_INDICATION = 0x00,
NAN_ATTR_CLUSTER = 0x01,
NAN_ATTR_NAN_ATTR_SERVICE_ID_LIST = 0x02,
NAN_ATTR_SDA = 0x03, /* Service Descriptor attribute */
NAN_ATTR_CONN_CAPA = 0x04,
NAN_ATTR_WLAN_INFRA = 0x05,
NAN_ATTR_P2P_OPER = 0x06,
NAN_ATTR_IBSS = 0x07,
NAN_ATTR_MESH = 0x08,
NAN_ATTR_FURTHER_NAN_SD = 0x09,
NAN_ATTR_FURTHER_AVAIL_MAP = 0x0A,
NAN_ATTR_COUNTRY_CODE = 0x0B,
NAN_ATTR_RANGIN = 0x0C,
NAN_ATTR_CLUSTER_DISCOVERY = 0x0D,
NAN_ATTR_SDEA = 0x0E, /* Service Descriptor Extension attribute */
NAN_ATTR_DEVICE_CAPABILITY = 0x0F,
NAN_ATTR_NDP = 0x10,
NAN_ATTR_NAN_AVAILABILITY = 0x12,
NAN_ATTR_NDC = 0x13,
NAN_ATTR_NDL = 0x14,
NAN_ATTR_NDL_QOS = 0x15,
NAN_ATTR_UNALIGNED_SCHEDULE = 0x17,
NAN_ATTR_RANGING_INFO = 0x1A,
NAN_ATTR_RANGING_SETUP = 0x1B,
NAN_ATTR_FTM_RANGING_REPORT = 0x1C,
NAN_ATTR_ELEM_CONTAINER = 0x1D,
NAN_ATTR_EXT_WLAN_INFRA = 0x1E,
NAN_ATTR_EXT_P2P_OPER = 0x1FE,
NAN_ATTR_EXT_IBSS = 0x20,
NAN_ATTR_EXT_MESH = 0x21,
NAN_ATTR_CSIA = 0x22, /* Cipher Suite Info attribute */
NAN_ATTR_SCIA = 0x23, /* Security Context Info attribute */
NAN_ATTR_SHARED_KEY_DESCR = 0x24,
NAN_ATTR_PUBLIC_AVAILABILITY = 0x27,
NAN_ATTR_SUBSC_SERVICE_ID_LIST = 0x28,
NAN_ATTR_NDP_EXT = 0x29,
NAN_ATTR_DCEA = 0x2A, /* Device Capability Extension attribute */
NAN_ATTR_NIRA = 0x2B, /* NAN Identity Resolution attribute */
NAN_ATTR_BPBA = 0x2C, /* NAN Pairing Bootstrapping attribute */
NAN_ATTR_S3 = 0x2D,
NAN_ATTR_TPEA = 0x2E, /* Transmit Power Envelope attribute */
NAN_ATTR_VENDOR_SPECIFIC = 0xDD,
};
/* Service Descriptor attribute (SDA) */
/* Service Control field */
#define NAN_SRV_CTRL_TYPE_MASK (BIT(0) | BIT(1))
#define NAN_SRV_CTRL_MATCHING_FILTER BIT(2)
#define NAN_SRV_CTRL_RESP_FILTER BIT(3)
#define NAN_SRV_CTRL_SRV_INFO BIT(4)
#define NAN_SRV_CTRL_DISCOVERY_RANGE_LIMITED BIT(5)
#define NAN_SRV_CTRL_BINDING_BITMAP BIT(6)
enum nan_service_control_type {
NAN_SRV_CTRL_PUBLISH = 0,
NAN_SRV_CTRL_SUBSCRIBE = 1,
NAN_SRV_CTRL_FOLLOW_UP = 2,
};
/* Service Descriptor Extension attribute (SDEA) */
/* SDEA Control field */
#define NAN_SDEA_CTRL_FSD_REQ BIT(0)
#define NAN_SDEA_CTRL_FSD_GAS BIT(1)
#define NAN_SDEA_CTRL_DATA_PATH_REQ BIT(2)
#define NAN_SDEA_CTRL_DATA_PATH_TYPE BIT(3)
#define NAN_SDEA_CTRL_QOS_REQ BIT(5)
#define NAN_SDEA_CTRL_SECURITY_REQ BIT(6)
#define NAN_SDEA_CTRL_RANGING_REQ BIT(7)
#define NAN_SDEA_CTRL_RANGE_LIMIT BIT(8)
#define NAN_SDEA_CTRL_SRV_UPD_INDIC BIT(9)
#define NAN_SDEA_CTRL_GTK_REQ BIT(10)
enum nan_service_protocol_type {
NAN_SRV_PROTO_BONJOUR = 1,
NAN_SRV_PROTO_GENERIC = 2,
NAN_SRV_PROTO_CSA_MATTER = 3,
};
#define NAN_ATTR_HDR_LEN 3
#define NAN_SERVICE_ID_LEN 6
#define NAN_USD_DEFAULT_FREQ 2437
#endif /* NAN_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,160 @@
/*
* NAN Discovery Engine
* Copyright (c) 2024, Qualcomm Innovation Center, Inc.
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef NAN_DE_H
#define NAN_DE_H
#include "nan.h"
#include "utils/common.h"
/* Maximum number of active local publish and subscribe instances */
#ifndef NAN_DE_MAX_SERVICE
#ifndef ESP_SUPPLICANT
#define NAN_DE_MAX_SERVICE 20
#else
#define NAN_DE_MAX_SERVICE 2
#endif
#endif /* NAN_DE_MAX_SERVICE */
struct nan_de;
enum nan_de_reason {
NAN_DE_REASON_TIMEOUT,
NAN_DE_REASON_USER_REQUEST,
NAN_DE_REASON_FAILURE,
};
struct nan_callbacks {
void *ctx;
int (*tx)(void *ctx, unsigned int freq, unsigned int wait_time,
const u8 *dst, const u8 *src, const u8 *bssid,
const struct wpabuf *buf);
int (*listen)(void *ctx, unsigned int freq, unsigned int duration);
/* NAN DE Events */
void (*discovery_result)(void *ctx, int subscribe_id,
enum nan_service_protocol_type srv_proto_type,
const u8 *ssi, size_t ssi_len,
int peer_publish_id,
const u8 *peer_addr, bool fsd, bool fsd_gas);
void (*replied)(void *ctx, int publish_id, const u8 *peer_addr,
int peer_subscribe_id,
enum nan_service_protocol_type srv_proto_type,
const u8 *ssi, size_t ssi_len);
void (*publish_terminated)(void *ctx, int publish_id,
enum nan_de_reason reason);
void (*subscribe_terminated)(void *ctx, int subscribe_id,
enum nan_de_reason reason);
void (*receive)(void *ctx, int id, int peer_instance_id,
const u8 *ssi, size_t ssi_len,
const u8 *peer_addr);
};
bool nan_de_is_nan_network_id(const u8 *addr);
bool nan_de_is_p2p_network_id(const u8 *addr);
struct nan_de * nan_de_init(const u8 *nmi, bool offload, bool ap,
unsigned int max_listen,
const struct nan_callbacks *cb);
void nan_de_flush(struct nan_de *de);
void nan_de_deinit(struct nan_de *de);
void nan_de_listen_started(struct nan_de *de, unsigned int freq,
unsigned int duration);
void nan_de_listen_ended(struct nan_de *de, unsigned int freq);
void nan_de_tx_status(struct nan_de *de, unsigned int freq, const u8 *dst);
void nan_de_tx_wait_ended(struct nan_de *de);
void nan_de_rx_sdf(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
unsigned int freq, const u8 *buf, size_t len);
const u8 * nan_de_get_service_id(struct nan_de *de, int id);
struct nan_publish_params {
/* configuration_parameters */
/* Publish type */
bool unsolicited;
bool solicited;
/* Solicited transmission type */
bool solicited_multicast;
/* Time to live (in seconds); 0 = one TX only */
unsigned int ttl;
/* Event conditions */
bool disable_events;
/* Further Service Discovery flag */
bool fsd;
/* Further Service Discovery function */
bool fsd_gas;
/* Default frequency (defaultPublishChannel) */
unsigned int freq;
/* Multi-channel frequencies (publishChannelList) */
const int *freq_list;
/* Announcement period in ms; 0 = use default */
unsigned int announcement_period;
};
/* Returns -1 on failure or >0 publish_id */
int nan_de_publish(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
struct nan_publish_params *params, bool p2p);
void nan_de_cancel_publish(struct nan_de *de, int publish_id);
int nan_de_update_publish(struct nan_de *de, int publish_id,
const struct wpabuf *ssi);
struct nan_subscribe_params {
/* configuration_parameters */
/* Subscribe type */
bool active;
/* Time to live (in seconds); 0 = until first result */
unsigned int ttl;
/* Selected frequency */
unsigned int freq;
/* Multi-channel frequencies (publishChannelList) */
const int *freq_list;
/* Query period in ms; 0 = use default */
unsigned int query_period;
};
/* Returns -1 on failure or >0 subscribe_id */
int nan_de_subscribe(struct nan_de *de, const char *service_name,
enum nan_service_protocol_type srv_proto_type,
const struct wpabuf *ssi, const struct wpabuf *elems,
struct nan_subscribe_params *params, bool p2p);
void nan_de_cancel_subscribe(struct nan_de *de, int subscribe_id);
/* handle = publish_id or subscribe_id
* req_instance_id = peer publish_id or subscribe_id */
int nan_de_transmit(struct nan_de *de, int handle,
const struct wpabuf *ssi, const struct wpabuf *elems,
const u8 *peer_addr, u8 req_instance_id);
#ifdef ESP_SUPPLICANT
void nan_de_cancel_service(struct nan_de *de, int service_id);
#endif
#endif /* NAN_DE_H */
@@ -543,6 +543,23 @@ int os_reltime_initialized(struct os_reltime *t)
return t->sec != 0 || t->usec != 0;
}
void os_reltime_add_ms(struct os_reltime *ts, int ms)
{
ts->usec += ms * 1000;
while (ts->usec >= 1000000) {
ts->sec++;
ts->usec -= 1000000;
}
while (ts->usec < 0) {
ts->sec--;
ts->usec += 1000000;
}
}
int os_reltime_in_ms(struct os_reltime *ts)
{
return ts->sec * 1000 + ts->usec / 1000;
}
u8 rssi_to_rcpi(int rssi)
{
@@ -398,6 +398,8 @@ int os_reltime_expired(struct os_time *now,
struct os_time *ts,
os_time_t timeout_secs);
int os_reltime_initialized(struct os_reltime *t);
void os_reltime_add_ms(struct os_reltime *ts, int ms);
int os_reltime_in_ms(struct os_reltime *ts);
#ifdef CONFIG_NATIVE_WINDOWS
void wpa_unicode2ascii_inplace(TCHAR *str);
@@ -435,6 +437,11 @@ static inline int is_multicast_ether_addr(const u8 *a)
return a[0] & 0x01;
}
static inline bool ether_addr_equal(const u8 *a, const u8 *b)
{
return os_memcmp(a, b, ETH_ALEN) == 0;
}
#define broadcast_ether_addr (const u8 *) "\xff\xff\xff\xff\xff\xff"
+8
View File
@@ -2094,6 +2094,14 @@ Detailed information on creating certificates and how to run wpa2_enterprise exa
Refer to ESP-IDF examples :idf_file:`examples/wifi/wifi_aware/nan_publisher/README.md` and :idf_file:`examples/wifi/wifi_aware/nan_subscriber/README.md` to setup a NAN Publisher and Subscriber.
Wi-Fi Aware\ :sup:`TM` (NAN): Unsynchronized Service Discovery (USD)
--------------------------------------------------------------------
Unsynchronized Service Discovery (USD) is a mechanism for devices to discover the services that have been made discoverable on new devices that enter the RF environment, without requiring synchronization between the devices.
USD uses Service Info field in the SDEA of a Publish and Follow-up message to convey the service specific information.
Refer to ESP-IDF examples :idf_file:`examples/wifi/wifi_aware/usd_publisher/README.md` and :idf_file:`examples/wifi/wifi_aware/usd_subscriber/README.md` to setup a NAN-USD Publisher and Subscriber.
Wireless Network Management
----------------------------
@@ -18,6 +18,10 @@ Application Examples
- :example:`wifi/wifi_aware/nan_subscriber` demonstrates how to use the NAN protocol to discover other devices that publishes the required service in the proximity, and communicate with them either by sending a message or initiating a datapath.
- :example:`wifi/wifi_aware/usd_publisher` demonstrates how to use lightweight NAN Unsynchronized Service Discovery (NAN-USD) to advertise a service to nearby devices without forming NAN clusters. It walks through bringing up USD, publishing a service, responding to subscribers with follow-up messages, and returning to the idle state once discovery completes.
- :example:`wifi/wifi_aware/usd_subscriber` demonstrates how to use the lightweight NAN Unsynchronized Service Discovery (NAN-USD) protocol to discover services advertised by nearby devices and interact with them. It covers enabling USD discovery, subscribing to services, handling follow-up exchanges, and terminating discovery after the session ends.
API Reference
-------------
@@ -46,4 +46,18 @@ The following Wi-Fi functions have been modified.
- **WPS:** The function ``esp_wifi_wps_start`` no longer accepts a ``timeout_ms`` argument. It should now be called as ``esp_wifi_wps_start(void)``.
- **NAN:** The function argument ``ndp_resp_needed`` of ``esp_wifi_nan_publish_service`` has been moved to structure ``wifi_nan_publish_cfg_t``.
- **NAN:**
- NAN API's are modified so that they can be shared between two separate NAN modes of operation called NAN Synchronization (NAN-Sync) and NAN Unsynchronized Discovery (NAN-USD) roles:
- ``esp_wifi_nan_sync_start`` and ``esp_wifi_nan_sync_stop`` replace the previous ``esp_wifi_nan_start`` / ``esp_wifi_nan_stop`` pair.
- Functions starting with prefix ``esp_wifi_nan_*`` are shared by both NAN-Sync and NAN-USD modes (for example ``esp_wifi_nan_publish_service`` and ``esp_wifi_nan_subscribe_service``).
- Use ``WIFI_NAN_SYNC_CONFIG_DEFAULT()`` instead of the former ``WIFI_NAN_CONFIG_DEFAULT()`` macro when initialising synchronized NAN configuration.
- The structure ``wifi_nan_config_t`` has been renamed to ``wifi_nan_sync_config_t``; update declarations such as ``wifi_config_t.nan`` to use the new type.
- NAN datapath APIs and associated structures are valid for NAN Synchronization (NAN-Sync) clusters only.
- Wi-Fi events ``WIFI_EVENT_NAN_STARTED`` / ``WIFI_EVENT_NAN_STOPPED`` have been renamed to ``WIFI_EVENT_NAN_SYNC_STARTED`` / ``WIFI_EVENT_NAN_SYNC_STOPPED``.
- The function argument ``ndp_resp_needed`` of ``esp_wifi_nan_publish_service`` has been moved to structure ``wifi_nan_publish_cfg_t``.
- The structure ``wifi_nan_wfa_ssi_t`` now declares its ``proto`` field as ``uint8_t`` (previously ``wifi_nan_svc_proto_t``). Update code that stores pointers to this field or relies on its size to treat it as a single octet.
- The structures ``wifi_nan_publish_cfg_t`` and ``wifi_nan_subscribe_cfg_t`` now include a ``usd_discovery_flag`` bitfield together with corresponding ``wifi_nan_usd_config_t`` members. Add designated initialisers for these fields when constructing the structures to avoid accidental field shifts.
- **Off-Channel Operations:**
- The structure :cpp:struct:`wifi_action_tx_req_t` now includes a ``bssid`` field that is placed in Address3 of the transmitted action frame. Initialise this field explicitly; leaving it all zeros retains the previous behaviour where the Wi-Fi driver inserts the broadcast address, so frames do not carry unintended BSSID values.
- The structure :cpp:struct:`wifi_roc_req_t` now includes an ``allow_broadcast`` flag that controls whether broadcast and multicast action frames are passed to the ``rx_cb`` callback during remain-on-channel operations. Existing applications should review the default ``false`` value and enable it when discovery of broadcast peers is required. Frames whose Address3/BSSID is already broadcast continue to reach the callback even when ``allow_broadcast`` remains ``false``.
@@ -46,5 +46,18 @@ Wi-Fi
- **WPS** 函数 ``esp_wifi_wps_start`` 不再接受 ``timeout_ms`` 参数。现在应调用为 ``esp_wifi_wps_start(void)``
- **NAN** 函数 ``esp_wifi_nan_publish_service`` 的参数 ``ndp_resp_needed`` 已移至结构体 ``wifi_nan_publish_cfg_t``
- **NAN**
- 已调整 NAN API,使其可在两个独立的 NAN 工作模式间共享:NAN 同步(NAN-Sync)与 NAN 非同步发现(NAN-USD):
- ``esp_wifi_nan_sync_start````esp_wifi_nan_sync_stop`` 取代原有的 ``esp_wifi_nan_start`` / ``esp_wifi_nan_stop``
- 以 ``esp_wifi_nan_*`` 为前缀的函数在 NAN-Sync 与 NAN 非同步发现(NAN-USD) 模式间通用(例如 ``esp_wifi_nan_publish_service````esp_wifi_nan_subscribe_service``)。
- 初始化 NAN 同步配置时,请使用 ``WIFI_NAN_SYNC_CONFIG_DEFAULT()``,原 ``WIFI_NAN_CONFIG_DEFAULT()`` 已停用。
- 结构体 ``wifi_nan_config_t`` 已重命名为 ``wifi_nan_sync_config_t``,例如需将 ``wifi_config_t.nan`` 等声明更新为新类型。
- NAN 数据通道相关的 API 与结构体目前仅适用于 NAN 同步(NAN-Sync)集群。
- Wi-Fi 事件 ``WIFI_EVENT_NAN_STARTED`` / ``WIFI_EVENT_NAN_STOPPED`` 已重命名为 ``WIFI_EVENT_NAN_SYNC_STARTED`` / ``WIFI_EVENT_NAN_SYNC_STOPPED``
- 函数 ``esp_wifi_nan_publish_service`` 的参数 ``ndp_resp_needed`` 已移至结构体 ``wifi_nan_publish_cfg_t``
- 结构体 ``wifi_nan_wfa_ssi_t`` 中的 ``proto`` 字段类型现为 ``uint8_t`` (之前为 ``wifi_nan_svc_proto_t``)。如果代码存储该字段的指针或依赖其大小,请按单个八位字节处理。
- 结构体 ``wifi_nan_publish_cfg_t````wifi_nan_subscribe_cfg_t`` 新增 ``usd_discovery_flag`` 位域及对应的 ``wifi_nan_usd_config_t`` 成员。构造这些结构体时,请为新增字段提供指定初始化器,以避免字段偏移。
- **离信道操作:**
- 结构体 :cpp:struct:`wifi_action_tx_req_t` 新增 ``bssid`` 字段,该字段会写入发送动作帧的 Address3。请显式初始化该字段;保持全零时将沿用之前的行为,由 Wi-Fi 驱动填入广播地址,从而避免帧携带意外的 BSSID。
- 结构体 :cpp:struct:`wifi_roc_req_t` 新增 ``allow_broadcast`` 标志,用于控制在驻留信道期间是否将广播/组播动作帧传递给 ``rx_cb`` 回调。现有应用应结合默认值 ``false`` 评估是否需要启用该选项,以便在需要时进行广播节点发现。若动作帧的 Address3/BSSID 本身为广播地址,即便 ``allow_broadcast`` 保持 ``false``,回调仍会收到该帧。
+41 -1
View File
@@ -98,7 +98,7 @@ examples/wifi/softap_sta:
disable:
- if: (SOC_WIFI_SUPPORTED != 1) and (SOC_WIRELESS_HOST_SUPPORTED != 1)
examples/wifi/wifi_aware:
examples/wifi/wifi_aware/nan_console:
disable:
- if: SOC_WIFI_NAN_SUPPORT != 1
reason: targets esp32c3, esp32s3, esp32c2 and esp32c6 are not supported
@@ -114,3 +114,43 @@ examples/wifi/wifi_aware:
- nvs_flash
depends_filepatterns:
- examples/system/console/advanced/components/**/*
examples/wifi/wifi_aware/nan_publisher:
disable:
- if: SOC_WIFI_NAN_SUPPORT != 1
reason: targets esp32c3, esp32s3, esp32c2 and esp32c6 are not supported
depends_components:
- esp_wifi
- esp_phy
- esp_netif
- lwip
- esp_event
- esp_coex
- wpa_supplicant
- mbedtls
- nvs_flash
examples/wifi/wifi_aware/nan_subscriber:
disable:
- if: SOC_WIFI_NAN_SUPPORT != 1
reason: targets esp32c3, esp32s3, esp32c2 and esp32c6 are not supported
depends_components:
- esp_wifi
- esp_phy
- esp_netif
- lwip
- esp_event
- esp_coex
- wpa_supplicant
- mbedtls
- nvs_flash
examples/wifi/wifi_aware/usd_publisher:
<<: *wifi_depends_default
disable:
- if: SOC_WIFI_SUPPORTED != 1
examples/wifi/wifi_aware/usd_subscriber:
<<: *wifi_depends_default
disable:
- if: SOC_WIFI_SUPPORTED != 1
@@ -234,7 +234,7 @@ static int wifi_cmd_nan_disc(int argc, char **argv)
}
if (nan_args.init->count) {
wifi_nan_config_t nan_cfg = WIFI_NAN_CONFIG_DEFAULT();
wifi_nan_sync_config_t nan_cfg = WIFI_NAN_SYNC_CONFIG_DEFAULT();
if (nan_args.master_pref->count) {
nan_cfg.master_pref = nan_args.master_pref->ival[0];
@@ -250,7 +250,7 @@ static int wifi_cmd_nan_disc(int argc, char **argv)
g_nan_netif = esp_netif_create_default_wifi_nan();
}
if ((esp_wifi_nan_start(&nan_cfg)) != ESP_OK) {
if ((esp_wifi_nan_sync_start(&nan_cfg)) != ESP_OK) {
ESP_LOGI(TAG, "Failed to start NAN");
esp_netif_destroy_default_wifi(g_nan_netif);
g_nan_netif = NULL;
@@ -266,7 +266,7 @@ static int wifi_cmd_nan_disc(int argc, char **argv)
}
if (nan_args.deinit->count) {
ret = esp_wifi_nan_stop();
ret = esp_wifi_nan_sync_stop();
if (ret != ESP_OK) {
ESP_LOGI(TAG, "Failed to stop NAN");
@@ -1 +1 @@
CONFIG_ESP_WIFI_NAN_ENABLE=y
CONFIG_ESP_WIFI_NAN_SYNC_ENABLE=y
@@ -81,10 +81,10 @@ void wifi_nan_publish(void)
&instance_any_id));
/* Start NAN Discovery */
wifi_nan_config_t nan_cfg = WIFI_NAN_CONFIG_DEFAULT();
wifi_nan_sync_config_t nan_cfg = WIFI_NAN_SYNC_CONFIG_DEFAULT();
esp_netif_create_default_wifi_nan();
esp_wifi_nan_start(&nan_cfg);
esp_wifi_nan_sync_start(&nan_cfg);
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_NDP_INDICATION,
@@ -1 +1 @@
CONFIG_ESP_WIFI_NAN_ENABLE=y
CONFIG_ESP_WIFI_NAN_SYNC_ENABLE=y
@@ -177,10 +177,10 @@ void wifi_nan_subscribe(void)
#endif
/* Start NAN Discovery */
wifi_nan_config_t nan_cfg = WIFI_NAN_CONFIG_DEFAULT();
wifi_nan_sync_config_t nan_cfg = WIFI_NAN_SYNC_CONFIG_DEFAULT();
esp_netif_t *nan_netif = esp_netif_create_default_wifi_nan();
(void) nan_netif;
esp_wifi_nan_start(&nan_cfg);
esp_wifi_nan_sync_start(&nan_cfg);
/* Subscribe a service */
uint8_t sub_id;
@@ -1 +1 @@
CONFIG_ESP_WIFI_NAN_ENABLE=y
CONFIG_ESP_WIFI_NAN_SYNC_ENABLE=y
@@ -0,0 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(usd_publisher)
@@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- |
@@ -0,0 +1,2 @@
idf_component_register(SRCS "usd_publisher_example_main.c"
INCLUDE_DIRS ".")
@@ -0,0 +1,20 @@
menu "Example Configuration"
config ESP_WIFI_USD_PUB_SVC_NAME
string "USD publish service name"
default "ESP-USD-TEST"
config ESP_WIFI_USD_PUB_TTL
int "Time to live (in seconds)"
range 0 1000
default 100
help
Time to live of the Publish instance, in seconds. If TTL = 0, only one publish message is transmitted.
config ESP_WIFI_USD_SVC_SPECIFIC_INFO
string "Service specific info to be transmitted in a followup message"
default "Welcome"
help
SSI to be transmitted in a followup frame
endmenu
@@ -0,0 +1,129 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_nan.h"
#include "esp_mac.h"
#include "esp_event.h"
#include "esp_check.h"
#include "esp_log.h"
#include "nvs_flash.h"
#define MAC_ADDR_LEN 6
#define EXAMPLE_USD_SVC_NAME CONFIG_ESP_WIFI_USD_PUB_SVC_NAME
#define EXAMPLE_USD_TTL CONFIG_ESP_WIFI_USD_PUB_TTL
#define EXAMPLE_USD_SVC_INFO CONFIG_ESP_WIFI_USD_SVC_SPECIFIC_INFO
static EventGroupHandle_t s_nan_event_group;
static int NAN_RECEIVE = BIT0;
const char *TAG = "usd_publisher";
uint8_t g_peer_inst_id;
uint8_t g_peer_mac[MAC_ADDR_LEN];
uint8_t g_publish_id;
static void nan_receive_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
wifi_event_nan_receive_t *evt = (wifi_event_nan_receive_t *)event_data;
if (evt == NULL) {
return;
}
g_peer_inst_id = evt->peer_inst_id;
memcpy(g_peer_mac, evt->peer_if_mac, MAC_ADDR_LEN);
ESP_LOGI(TAG, "Received Follow-up message from peer with ID %d and MAC "MACSTR"",
evt->peer_inst_id, MAC2STR(evt->peer_if_mac));
if (evt->ssi_len) {
ESP_LOG_BUFFER_HEXDUMP(TAG, evt->ssi, evt->ssi_len, ESP_LOG_INFO);
xEventGroupSetBits(s_nan_event_group, NAN_RECEIVE);
} else {
ESP_LOGI(TAG, "SSI - [NULL]");
}
}
void wifi_usd_publish(void)
{
s_nan_event_group = xEventGroupCreate();
esp_event_handler_instance_t instance_any_id;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_NAN_RECEIVE,
&nan_receive_event_handler,
NULL,
&instance_any_id));
ESP_RETURN_VOID_ON_ERROR(esp_wifi_start(), TAG, "NAN-USD failed to start Wi-Fi");
/* Start USD-NAN Discovery */
ESP_RETURN_VOID_ON_ERROR(esp_wifi_nan_usd_start(), TAG, "NAN-USD initialization failed");
wifi_nan_publish_cfg_t publish_cfg = {
.service_name = EXAMPLE_USD_SVC_NAME,
.ttl = EXAMPLE_USD_TTL,
.ssi = NULL,
.ssi_len = 0,
.usd_discovery_flag = 1,
.usd_publish_config = esp_wifi_usd_get_default_publish_cfg(),
};
g_publish_id = esp_wifi_nan_publish_service(&publish_cfg);
if (g_publish_id == 0) {
ESP_LOGE(TAG, "Publishing to %s failed", publish_cfg.service_name);
return;
}
EventBits_t bits = xEventGroupWaitBits(s_nan_event_group, NAN_RECEIVE, pdFALSE, pdFALSE, pdMS_TO_TICKS(EXAMPLE_USD_TTL*1000));
if (bits & NAN_RECEIVE) {
xEventGroupClearBits(s_nan_event_group, NAN_RECEIVE);
wifi_nan_followup_params_t fup_params = {
.inst_id = g_publish_id,
.peer_inst_id = g_peer_inst_id,
.ssi = (uint8_t *)EXAMPLE_USD_SVC_INFO,
.ssi_len = strlen(EXAMPLE_USD_SVC_INFO),
};
memcpy(fup_params.peer_mac, g_peer_mac, MAC_ADDR_LEN);
ESP_LOGI(TAG, "Sending message to the peer with ID %d", g_peer_inst_id);
if (fup_params.ssi_len) {
ESP_LOG_BUFFER_HEXDUMP(TAG, fup_params.ssi, fup_params.ssi_len, ESP_LOG_INFO);
} else {
ESP_LOGI(TAG, "SSI - [NULL]");
}
ESP_RETURN_VOID_ON_ERROR(esp_wifi_nan_send_message(&fup_params), TAG, "Sending message to the peer with ID %d failed!", g_peer_inst_id);
}
esp_wifi_nan_cancel_service(g_publish_id);
esp_wifi_nan_usd_stop();
}
void initialise_wifi(void)
{
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
}
void app_main(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
initialise_wifi();
wifi_usd_publish();
return;
}
@@ -0,0 +1,2 @@
CONFIG_ESP_WIFI_NAN_USD_ENABLE=y
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
@@ -0,0 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(usd_subscriber)
@@ -0,0 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- |
@@ -0,0 +1,2 @@
idf_component_register(SRCS "usd_subscriber_example_main.c"
INCLUDE_DIRS ".")
@@ -0,0 +1,28 @@
menu "Example Configuration"
config ESP_WIFI_USD_SUB_SVC_NAME
string "USD subscribe service name"
default "ESP-USD-TEST"
config ESP_WIFI_USD_SUB_TTL
int "Time to live (in seconds)"
range 0 1000
default 100
help
Time to live of the Subscribe instance, in seconds. If TTL = 0,
the subscriber listens until the first service match is reported.
config ESP_WIFI_USD_DEFAULT_CHAN
int "Default Subscribe channel"
range 1 13
default 6
help
Default channel of subscriber
config ESP_WIFI_USD_SVC_SPECIFIC_INFO
string "Service specific info to be transmitted in a followup message"
default "Hello"
help
SSI to be transmitted in a followup frame
endmenu
@@ -0,0 +1,153 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_nan.h"
#include "esp_mac.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_check.h"
#include "nvs_flash.h"
#define MAC_ADDR_LEN 6
#define EXAMPLE_USD_SVC_NAME CONFIG_ESP_WIFI_USD_SUB_SVC_NAME
#define EXAMPLE_USD_TTL CONFIG_ESP_WIFI_USD_SUB_TTL
#define EXAMPLE_USD_DEFAULT_SUB_CHANNEL CONFIG_ESP_WIFI_USD_DEFAULT_CHAN
#define EXAMPLE_USD_SVC_INFO CONFIG_ESP_WIFI_USD_SVC_SPECIFIC_INFO
static EventGroupHandle_t s_nan_event_group;
static int NAN_RECEIVE = BIT0;
static int NAN_SRV_MATCH = BIT1;
const char *TAG = "usd_subscriber";
uint8_t g_peer_inst_id;
uint8_t g_peer_mac[MAC_ADDR_LEN];
uint8_t g_subscribe_id;
static void nan_svc_match_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
wifi_event_nan_svc_match_t *evt = (wifi_event_nan_svc_match_t *)event_data;
if (evt == NULL) {
return;
}
g_peer_inst_id = evt->publish_id;
memcpy(g_peer_mac, evt->pub_if_mac, MAC_ADDR_LEN);
ESP_LOGI(TAG, "Service matched with peer_id %d peer mac "MACSTR"", evt->publish_id, MAC2STR(evt->pub_if_mac));
if (evt->ssi_len) {
ESP_LOGI(TAG, "SSI -");
ESP_LOG_BUFFER_HEXDUMP(TAG, evt->ssi,
evt->ssi_len, ESP_LOG_INFO);
} else {
ESP_LOGI(TAG, "SSI - [NULL]");
}
xEventGroupSetBits(s_nan_event_group, NAN_SRV_MATCH);
}
static void nan_receive_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
wifi_event_nan_receive_t *evt = (wifi_event_nan_receive_t *)event_data;
if (evt == NULL) {
return;
}
ESP_LOGI(TAG, "Received Follow-up message from peer with ID %d and MAC "MACSTR"",
evt->peer_inst_id, MAC2STR(evt->peer_if_mac));
if (evt->ssi_len) {
ESP_LOG_BUFFER_HEXDUMP(TAG, evt->ssi, evt->ssi_len, ESP_LOG_INFO);
} else {
ESP_LOGI(TAG, "SSI - [NULL]");
}
xEventGroupSetBits(s_nan_event_group, NAN_RECEIVE);
esp_wifi_nan_cancel_service(g_subscribe_id);
}
void wifi_usd_subscribe(void)
{
s_nan_event_group = xEventGroupCreate();
esp_event_handler_instance_t instance_any_id;
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_NAN_SVC_MATCH,
&nan_svc_match_event_handler,
NULL,
&instance_any_id));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
WIFI_EVENT_NAN_RECEIVE,
&nan_receive_event_handler,
NULL,
&instance_any_id));
ESP_RETURN_VOID_ON_ERROR(esp_wifi_start(), TAG, "NAN-USD failed to start Wi-Fi");
/* Start NAN-USD Discovery */
ESP_RETURN_VOID_ON_ERROR(esp_wifi_nan_usd_start(), TAG, "NAN-USD initialization failed");
wifi_nan_subscribe_cfg_t subscribe_cfg = {
.service_name = EXAMPLE_USD_SVC_NAME,
.ttl = EXAMPLE_USD_TTL,
.ssi = NULL,
.ssi_len = 0,
.usd_discovery_flag = 1,
.usd_subscribe_config = esp_wifi_usd_get_default_subscribe_cfg(),
};
subscribe_cfg.usd_subscribe_config.usd_default_channel = EXAMPLE_USD_DEFAULT_SUB_CHANNEL;
g_subscribe_id = esp_wifi_nan_subscribe_service(&subscribe_cfg);
if (g_subscribe_id == 0) {
ESP_LOGE(TAG, "Subscribing to %s failed", subscribe_cfg.service_name);
return;
}
EventBits_t bits = xEventGroupWaitBits(s_nan_event_group, NAN_SRV_MATCH, pdTRUE, pdFALSE, pdMS_TO_TICKS(EXAMPLE_USD_TTL*1000));
if (bits & NAN_SRV_MATCH) {
wifi_nan_followup_params_t fup_params = {
.inst_id = g_subscribe_id,
.peer_inst_id = g_peer_inst_id,
.ssi = (uint8_t *)EXAMPLE_USD_SVC_INFO,
.ssi_len = strlen(EXAMPLE_USD_SVC_INFO),
};
memcpy(fup_params.peer_mac, g_peer_mac, MAC_ADDR_LEN);
ESP_LOGI(TAG, "Sending message to the peer with ID %d", g_peer_inst_id);
if (fup_params.ssi_len) {
ESP_LOG_BUFFER_HEXDUMP(TAG, fup_params.ssi, fup_params.ssi_len, ESP_LOG_INFO);
} else {
ESP_LOGI(TAG, "SSI - [NULL]");
}
ESP_RETURN_VOID_ON_ERROR(esp_wifi_nan_send_message(&fup_params), TAG, "Sending message to the peer with ID %d failed!", g_peer_inst_id);
}
return;
}
void initialise_wifi(void)
{
ESP_ERROR_CHECK(esp_event_loop_create_default());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
}
void app_main(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
initialise_wifi();
wifi_usd_subscribe();
return;
}
@@ -0,0 +1,2 @@
CONFIG_ESP_WIFI_NAN_USD_ENABLE=y
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
+30
View File
@@ -624,6 +624,10 @@
re: "error: implicit declaration of function 'esp_wifi_config_espnow_rate'"
hint: "The function 'esp_wifi_config_espnow_rate' has been removed. Use 'esp_now_set_peer_rate_config' instead."
-
re: "(initialization|assignment) of 'wifi_nan_svc_proto_t \\*' from incompatible pointer type 'uint8_t \\*'"
hint: "The field 'proto' in structure 'wifi_nan_wfa_ssi_t' is now declared as 'uint8_t'. Update pointer usage accordingly, for example by using a 'uint8_t *' or copying the enum value into a separate variable."
-
re: "error: too many arguments to function 'esp_wifi_wps_start'"
hint: "The function 'esp_wifi_wps_start' no longer accepts a 'timeout_ms' argument."
@@ -656,10 +660,36 @@
re: "error: 'peer_svc_info' undeclared"
hint: "The field 'peer_svc_info' from structure 'wifi_event_nan_receive_t' has been removed. Please use the equivalent fields 'ssi' and 'ssi_len' instead."
-
re: "error: 'WIFI_EVENT_NAN_STARTED' undeclared"
hint: "The Wi-Fi NAN event 'WIFI_EVENT_NAN_STARTED' has been renamed to 'WIFI_EVENT_NAN_SYNC_STARTED'."
-
re: "error: 'WIFI_EVENT_NAN_STOPPED' undeclared"
hint: "The Wi-Fi NAN event 'WIFI_EVENT_NAN_STOPPED' has been renamed to 'WIFI_EVENT_NAN_SYNC_STOPPED'."
-
re: "error: too few arguments to function 'esp_wifi_nan_publish_service'"
hint: "The function argument 'ndp_resp_needed' of 'esp_wifi_nan_publish_service' has been moved to structure 'wifi_nan_publish_cfg_t'."
-
re: "error: implicit declaration of function '{}'"
hint: "The NAN synchronization API '{}' has been renamed to '{}'."
variables:
-
re_variables: ['esp_wifi_nan_start']
hint_variables: ['esp_wifi_nan_start', 'esp_wifi_nan_sync_start']
-
re_variables: ['esp_wifi_nan_stop']
hint_variables: ['esp_wifi_nan_stop', 'esp_wifi_nan_sync_stop']
-
re_variables: ['WIFI_NAN_CONFIG_DEFAULT']
hint_variables: ['WIFI_NAN_CONFIG_DEFAULT', 'WIFI_NAN_SYNC_CONFIG_DEFAULT']
-
re: "error: unknown type name 'wifi_nan_config_t'"
hint: "The structure 'wifi_nan_config_t' has been renamed to 'wifi_nan_sync_config_t'."
-
re: "error: '(WIFI_REASON_ASSOC_EXPIRE|WIFI_REASON_NOT_AUTHED|WIFI_REASON_NOT_ASSOCED)' undeclared"
hint: "The Wi-Fi disconnection reason codes '{0}' have been removed. Please use '{1}', '{2}', and '{3}' respectively."