mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(wifi): Add support for Wi-Fi Aware: Unsynchronized Service Discover (USD)
1. Remove redundant fixes in upstream wpa_supplicant for USD
- Upstream supplicant has mostly fixed the issues regarding the
unnecessary resetting pauseStateTimeout.
- Upstream supplicant still needs one fix to avoid resetting the
pauseStateTimeout when subscribe message is received from the peer
which had triggered the pauseStateTimeout previously.
2. Replace array-based channel list with bitmap for NaN-USD
Use `wifi_scan_channel_bitmap_t` to represent the channel list for NaN-USD
publisher and subscriber configurations. This replaces the previous approach
that used a large array to store allowed channels.
Also aligns with internal scan bitmap conventions across Wi-Fi stack.
3. call esp_wifi_nan_stop() after USD exchange or STA stop
Ensure esp_wifi_nan_stop() is called after publish/subscribe activity
completes or when WIFI_EVENT_STA_STOP is received. This prevents NAN stop
errors due to inactive interface. NaN-USD currently uses STA interface
for Tx/Rx.
4. Fix task watchdog timer triggered in active USD subscriber:
As both USD supplicant and offchan TX component gets executed
in the wifi task, it created a deadlock like scenario where offchan TX
done callback was never getting executed and supplicant 'nan_de_timer'
keeps running but failing to send any subscribe frame.
5. Make sure that device is able to recieve action management frames
of size more than 1400 bytes.
6. Update proto field in SSI to match Wi-Fi Aware (NaN) spec format
The 'proto' field in the 'wifi_nan_wfa_ssi_t' structure previously used an
enum (wifi_nan_svc_proto_t), resulting in a 32-bit field. According to
the Wi-Fi NAN Specification (Table 5.7), this field must be a single
octet (8 bits). This commit updates the type to uint8_t to ensure
compliance with the specification.
This mismatch previously triggered warnings but did not cause functional
errors.
7. Set `allow_broadcast` to true in USD Remain on channel
This enables the peer discovery as USD uses NAN-Network Multicast BSSID
as A3 address in publish frames.
8. Implement custom channel<->frequency conversion for NAN-USD
NaN-USD only permits 20 MHz bandwidth channels in the 2.4 GHz and 5 GHz bands
(as per section 4.5.3 of the Wi-Fi Aware Specification v4.0). To avoid linking
a large portion of upstream supplicant code for frequency-to-channel and
channel-to-frequency conversion, implement minimal custom helper functions.
9. Limit NAN_DE_MAX_SERVICE to 2 for ESP_SUPPLICANT
10. Note: Upstream clamps negative `os_reltime` deltas to zero in `nan_de_srv_time_to_next()`,
but our ESP_SUPPLICANT port keeps `os_time_t` unsigned, so that guard just provokes a
compiler warning. We skip it for now because the scheduling loop validates past timestamps
before computing the diff.
Co-authored-by: Shyamal Khachane <shyamal.khachane@espressif.com>
This commit is contained in:
@@ -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_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)
|
||||
|
||||
@@ -584,6 +584,12 @@ menu "Wi-Fi"
|
||||
help
|
||||
Enable WiFi Aware (NAN) feature.
|
||||
|
||||
config ESP_WIFI_NAN_USD_ENABLE
|
||||
bool "Enable NAN USD"
|
||||
default n
|
||||
help
|
||||
Enable NAN(WiFi Aware) Unsynchronized service discovery
|
||||
|
||||
config ESP_WIFI_MBEDTLS_CRYPTO
|
||||
bool "Use MbedTLS crypto APIs"
|
||||
default y
|
||||
|
||||
@@ -592,6 +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 */
|
||||
bool discovery_flag; /**< False in case of NAN Synchronization, True in case of Unsynchronized service discovery (USD)*/
|
||||
} wifi_nan_config_t;
|
||||
|
||||
/**
|
||||
@@ -830,7 +831,7 @@ 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 will be received
|
||||
@@ -850,7 +851,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 */
|
||||
@@ -882,7 +883,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;
|
||||
|
||||
@@ -897,6 +898,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
|
||||
*
|
||||
@@ -910,9 +924,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;
|
||||
|
||||
/**
|
||||
@@ -927,9 +945,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;
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
Submodule components/esp_wifi/lib updated: 37a69947e1...21eacc3229
@@ -20,6 +20,12 @@ extern "C" {
|
||||
.master_pref = 2, \
|
||||
.scan_time = 3, \
|
||||
.warm_up_sec = 5, \
|
||||
.discovery_flag = 0, \
|
||||
};
|
||||
|
||||
/* For USD, all parameters other than discovery_flag are ignored */
|
||||
#define WIFI_USD_NAN_CONFIG_DEFAULT() { \
|
||||
.discovery_flag = 1, \
|
||||
};
|
||||
|
||||
#define NDP_STATUS_ACCEPTED 1
|
||||
@@ -40,7 +46,7 @@ struct nan_peer_record {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Start NAN Discovery with provided configuration
|
||||
* @brief Start NAN Discovery or Unsynchronized service discovery (USD) with provided configuration
|
||||
*
|
||||
* @attention This API should be called after esp_wifi_init().
|
||||
*
|
||||
@@ -53,7 +59,10 @@ struct nan_peer_record {
|
||||
esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg);
|
||||
|
||||
/**
|
||||
* @brief Stop NAN Discovery, end NAN Services and Datapaths
|
||||
* @brief Stop NAN Discovery or USD and end publish/subscribe services
|
||||
*
|
||||
* @attention This API will end datapaths if any in NAN synchronization
|
||||
* @attention This API will stop USD if discovery_flag is set to true, else it will stop NAN Discovery
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
@@ -62,9 +71,13 @@ esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg);
|
||||
esp_err_t esp_wifi_nan_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Start Publishing a service to the NAN Peers in vicinity
|
||||
* @brief Start Publishing a service to the NAN/USD Peers in vicinity
|
||||
*
|
||||
* @attention This API should be called after esp_wifi_nan_start().
|
||||
* @attention This API will start a publisher in USD if discovery_flag is true
|
||||
* @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.
|
||||
*
|
||||
@@ -75,9 +88,13 @@ esp_err_t esp_wifi_nan_stop(void);
|
||||
uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg);
|
||||
|
||||
/**
|
||||
* @brief Subscribe for a service within the NAN cluster
|
||||
* @brief Subscribe to a service published by a NAN peer within a cluster or a USD peer
|
||||
*
|
||||
* @attention This API should be called after esp_wifi_nan_start().
|
||||
* @attention This API will start a subscriber in USD if discovery_flag is true
|
||||
* @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.
|
||||
*
|
||||
@@ -88,9 +105,9 @@ uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg);
|
||||
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
|
||||
* @brief Send a follow-up message to a matched peer in NAN synchronization or USD
|
||||
*
|
||||
* @attention This API should be called after a NAN service is discovered due to a match.
|
||||
* @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.
|
||||
*
|
||||
@@ -101,7 +118,7 @@ uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe
|
||||
esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params);
|
||||
|
||||
/**
|
||||
* @brief Cancel a NAN service
|
||||
* @brief Cancel a NAN synchronization or NAN-USD service
|
||||
*
|
||||
* @param service_id Publish/Subscribe service id to be cancelled.
|
||||
*
|
||||
@@ -198,6 +215,41 @@ esp_err_t esp_wifi_nan_get_peer_records(int *num_peer_records, uint8_t own_svc_i
|
||||
*/
|
||||
esp_err_t esp_wifi_nan_get_peer_info(char *svc_name, uint8_t *peer_mac, struct nan_peer_record *peer_info);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
#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_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_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_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 */
|
||||
@@ -782,11 +794,13 @@ void esp_nan_action_stop(void)
|
||||
os_event_group_set_bits(nan_event_group, NAN_STOPPED_BIT);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_ENABLE */
|
||||
|
||||
esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg)
|
||||
{
|
||||
wifi_mode_t mode;
|
||||
esp_err_t ret;
|
||||
wifi_config_t config = {0};
|
||||
s_usd_in_progress = false;
|
||||
|
||||
ret = esp_wifi_get_mode(&mode);
|
||||
if (ret == ESP_ERR_WIFI_NOT_INIT) {
|
||||
@@ -797,44 +811,89 @@ esp_err_t esp_wifi_nan_start(const wifi_nan_config_t *nan_cfg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!s_nan_data_lock) {
|
||||
ESP_LOGE(TAG, "NAN Data lock doesn't exist");
|
||||
#if (!CONFIG_ESP_WIFI_NAN_ENABLE)
|
||||
if (!nan_cfg->discovery_flag) {
|
||||
ESP_LOGE(TAG, "discovery_flag must be set when"
|
||||
"ESP_WIFI_NAN_USD_ENABLE is enabled");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
NAN_DATA_LOCK();
|
||||
if (s_nan_ctx.state & NAN_STARTED_BIT) {
|
||||
ESP_LOGI(TAG, "NAN already started");
|
||||
NAN_DATA_UNLOCK();
|
||||
/* XXX: For now, NAN-USD and NAN-Sync can not coexist. */
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
|
||||
if (nan_cfg->discovery_flag) {
|
||||
/* NAN-USD Only */
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_set_mode(WIFI_MODE_STA), "NAN-USD", "Setting STA mode failed");
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_start(), "NAN-USD", "Starting WiFi 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;
|
||||
}
|
||||
NAN_DATA_UNLOCK();
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
|
||||
else {
|
||||
if (nan_cfg->discovery_flag) {
|
||||
/* Should reach here only if ESP_WIFI_NAN_USD_ENABLE is disabled */
|
||||
ESP_LOGE(TAG, "Can not set discovery_flag without "
|
||||
"ESP_WIFI_NAN_USD_ENABLE enabled");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_set_mode(WIFI_MODE_NAN), TAG, "Set mode NAN failed");
|
||||
/* 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;
|
||||
}
|
||||
|
||||
memcpy(&config.nan, nan_cfg, sizeof(wifi_nan_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) {
|
||||
ESP_LOGE(TAG, "Starting wifi failed");
|
||||
NAN_DATA_LOCK();
|
||||
s_nan_ctx.nan_netif = NULL;
|
||||
if (s_nan_ctx.state & NAN_STARTED_BIT) {
|
||||
ESP_LOGI(TAG, "NAN already started");
|
||||
NAN_DATA_UNLOCK();
|
||||
return ESP_OK;
|
||||
}
|
||||
NAN_DATA_UNLOCK();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
EventBits_t bits = os_event_group_wait_bits(nan_event_group, NAN_STARTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
if (!(bits & NAN_STARTED_BIT)) {
|
||||
NAN_DATA_LOCK();
|
||||
s_nan_ctx.nan_netif = NULL;
|
||||
NAN_DATA_UNLOCK();
|
||||
return ESP_FAIL;
|
||||
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));
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_set_config(WIFI_IF_NAN, &config), TAG, "Setting NAN config failed");
|
||||
|
||||
if (esp_wifi_start() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Starting wifi failed");
|
||||
NAN_DATA_LOCK();
|
||||
s_nan_ctx.nan_netif = NULL;
|
||||
NAN_DATA_UNLOCK();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
EventBits_t bits = os_event_group_wait_bits(nan_event_group, NAN_STARTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
if (!(bits & NAN_STARTED_BIT)) {
|
||||
NAN_DATA_LOCK();
|
||||
s_nan_ctx.nan_netif = NULL;
|
||||
NAN_DATA_UNLOCK();
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
return ESP_OK;
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_ENABLE */
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_wifi_nan_stop(void)
|
||||
{
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
|
||||
if (s_usd_in_progress) {
|
||||
s_usd_in_progress = false;
|
||||
esp_nan_usd_deinit();
|
||||
ESP_RETURN_ON_ERROR(esp_wifi_stop(), TAG, "Stopping NAN-USD failed");
|
||||
ESP_LOGI(TAG, "NaN-USD Stopped");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
|
||||
NAN_DATA_LOCK();
|
||||
if (!(s_nan_ctx.state & NAN_STARTED_BIT)) {
|
||||
ESP_LOGE(TAG, "NAN isn't started");
|
||||
@@ -871,43 +930,79 @@ esp_err_t esp_wifi_nan_stop(void)
|
||||
NAN_DATA_LOCK();
|
||||
memset(&s_nan_ctx, 0, sizeof(nan_ctx_t));
|
||||
NAN_DATA_UNLOCK();
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_ENABLE */
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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_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 +1015,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_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_ENABLE
|
||||
NAN_DATA_LOCK();
|
||||
if (!(s_nan_ctx.state & NAN_STARTED_BIT)) {
|
||||
ESP_LOGE(TAG, "NAN not started!");
|
||||
@@ -941,63 +1079,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_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_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 +1163,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 +1178,20 @@ 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_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);
|
||||
}
|
||||
else
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
|
||||
NAN_DATA_LOCK();
|
||||
struct own_svc_info *p_own_svc = nan_find_own_svc(service_id);
|
||||
|
||||
@@ -1067,8 +1223,12 @@ fail:
|
||||
done:
|
||||
NAN_DATA_UNLOCK();
|
||||
return ESP_OK;
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_ENABLE */
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_ENABLE
|
||||
uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req)
|
||||
{
|
||||
uint8_t ndp_id = 0;
|
||||
@@ -1337,3 +1497,58 @@ 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_ENABLE */
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_USD_ENABLE
|
||||
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 */
|
||||
|
||||
@@ -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,678 @@
|
||||
/*
|
||||
* 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_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 36–64
|
||||
(freq >= 5500 && freq <= 5720) || // Channels 100–144
|
||||
(freq >= 5745 && freq <= 5825)) { // Channels 149–165
|
||||
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);
|
||||
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;
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "ieee802_11_defs.h"
|
||||
#include "nan.h"
|
||||
#include "nan_de.h"
|
||||
#include "ctype.h"
|
||||
|
||||
static const u8 nan_network_id[ETH_ALEN] =
|
||||
{ 0x51, 0x6f, 0x9a, 0x01, 0x00, 0x00 };
|
||||
@@ -282,6 +283,12 @@ static void nan_de_tx_sdf(struct nan_de *de, struct nan_de_service *srv,
|
||||
wpabuf_put_le16(buf, sdea_ctrl);
|
||||
if (ssi) {
|
||||
#ifdef ESP_SUPPLICANT
|
||||
/* Note: In our NaN-USD implementation, the user-provided SSI value must
|
||||
* include both the OUI and the Service Protocol Type.
|
||||
* This differs from the upstream wpa_supplicant implementation, where
|
||||
* the USD supplicant driver constructs the SSI internally using the
|
||||
* Wi-Fi OUI and a separately provided srv_proto_type.
|
||||
*/
|
||||
wpabuf_put_le16(buf, wpabuf_len(ssi));
|
||||
wpabuf_put_buf(buf, ssi);
|
||||
#else
|
||||
@@ -544,9 +551,11 @@ static int nan_de_srv_time_to_next(struct nan_de *de,
|
||||
|
||||
if (os_reltime_initialized(&srv->next_publish_state)) {
|
||||
os_reltime_sub(&srv->next_publish_state, now, &diff);
|
||||
#ifndef ESP_SUPPLICANT
|
||||
if (diff.sec < 0 || (diff.sec == 0 && diff.usec < 0))
|
||||
tmp = 0;
|
||||
else
|
||||
#endif /* ESP_SUPPLICANT */
|
||||
tmp = os_reltime_in_ms(&diff);
|
||||
if (next == -1 || tmp < next)
|
||||
next = tmp;
|
||||
@@ -656,7 +665,9 @@ static void nan_de_timer(void *eloop_ctx, void *timeout_ctx)
|
||||
|
||||
if (srv_next == 0 && !started && !de->offload &&
|
||||
de->listen_freq == 0 && de->ext_listen_freq == 0 &&
|
||||
#ifndef ESP_SUPPLICANT
|
||||
de->tx_wait_end_freq == 0 &&
|
||||
#endif
|
||||
nan_de_next_multicast(de, srv, &now) == 0) {
|
||||
started = true;
|
||||
nan_de_tx_multicast(de, srv, 0);
|
||||
@@ -1001,6 +1012,12 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
|
||||
wpabuf_put_le16(buf, sdea_ctrl);
|
||||
if (srv->ssi) {
|
||||
#ifdef ESP_SUPPLICANT
|
||||
/* Note: In our NaN-USD implementation, the SSI value must
|
||||
* include both the OUI and the Service Protocol Type.
|
||||
* This differs from the upstream wpa_supplicant implementation, where
|
||||
* the USD supplicant driver constructs the SSI internally using the
|
||||
* Wi-Fi OUI and a separately provided srv_proto_type.
|
||||
*/
|
||||
wpabuf_put_le16(buf, wpabuf_len(srv->ssi));
|
||||
wpabuf_put_buf(buf, srv->ssi);
|
||||
#else
|
||||
@@ -1038,7 +1055,18 @@ static void nan_de_rx_subscribe(struct nan_de *de, struct nan_de_service *srv,
|
||||
de->nmi, a3, buf);
|
||||
wpabuf_free(buf);
|
||||
|
||||
nan_de_pause_state(srv, peer_addr, instance_id);
|
||||
if (!srv->is_p2p) {
|
||||
#ifdef ESP_SUPPLICANT
|
||||
if (os_reltime_initialized(&srv->pause_state_end) &&
|
||||
ether_addr_equal(peer_addr, srv->sel_peer_addr) &&
|
||||
instance_id == srv->sel_peer_id) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"NAN: In pauseState - skipping pauseStateTimeout reset for"
|
||||
" Subscribe message from selected peer");
|
||||
} else
|
||||
#endif /* ESP_SUPPLICANT */
|
||||
nan_de_pause_state(srv, peer_addr, instance_id);
|
||||
}
|
||||
|
||||
offload:
|
||||
if (!srv->publish.disable_events && de->cb.replied)
|
||||
@@ -1540,3 +1568,20 @@ int nan_de_transmit(struct nan_de *de, int handle,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ESP_SUPPLICANT
|
||||
void nan_de_cancel_service(struct nan_de *de, int service_id)
|
||||
{
|
||||
struct nan_de_service *srv;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "NAN: CancelService(service_id=%d)", service_id);
|
||||
|
||||
if (service_id < 1 || service_id > NAN_DE_MAX_SERVICE)
|
||||
return;
|
||||
|
||||
srv = de->service[service_id - 1];
|
||||
if (!srv)
|
||||
return;
|
||||
nan_de_del_srv(de, srv, NAN_DE_REASON_USER_REQUEST);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -10,10 +10,15 @@
|
||||
#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;
|
||||
@@ -149,4 +154,7 @@ 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"
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
----------------------------
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,127 @@
|
||||
/*
|
||||
* 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));
|
||||
|
||||
/* Start USD-NAN Discovery */
|
||||
wifi_nan_config_t usd_nan_cfg = WIFI_USD_NAN_CONFIG_DEFAULT();
|
||||
ESP_RETURN_VOID_ON_ERROR(esp_wifi_nan_start(&usd_nan_cfg), 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_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) );
|
||||
}
|
||||
|
||||
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 @@
|
||||
CONFIG_ESP_WIFI_NAN_USD_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_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,151 @@
|
||||
/*
|
||||
* 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));
|
||||
|
||||
/* Start NAN-USD Discovery */
|
||||
wifi_nan_config_t nan_usd_cfg = WIFI_USD_NAN_CONFIG_DEFAULT();
|
||||
esp_wifi_nan_start(&nan_usd_cfg);
|
||||
|
||||
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) );
|
||||
}
|
||||
|
||||
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 @@
|
||||
CONFIG_ESP_WIFI_NAN_USD_ENABLE=y
|
||||
Reference in New Issue
Block a user