From 90c008fe8c4aebbb2cf4162342f5e7a0673578a2 Mon Sep 17 00:00:00 2001 From: akshat Date: Tue, 8 Apr 2025 14:48:46 +0530 Subject: [PATCH] feat(esp_wifi): Add extended SSI support for NAN Services --- .../esp_wifi/include/esp_wifi_types_generic.h | 87 ++++++++++++++--- components/esp_wifi/lib | 2 +- .../esp_wifi/wifi_apps/nan_app/src/nan_app.c | 97 ++++++++++++++----- .../wifi_aware/nan_console/main/nan_main.c | 77 ++++++++++++--- .../nan_publisher/main/publisher_main.c | 36 +++++-- .../nan_subscriber/main/subscriber_main.c | 33 ++++++- 6 files changed, 268 insertions(+), 64 deletions(-) diff --git a/components/esp_wifi/include/esp_wifi_types_generic.h b/components/esp_wifi/include/esp_wifi_types_generic.h index 4e9eea47cc..3204661dc2 100644 --- a/components/esp_wifi/include/esp_wifi_types_generic.h +++ b/components/esp_wifi/include/esp_wifi_types_generic.h @@ -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 */ @@ -799,7 +799,32 @@ typedef struct { #define ESP_WIFI_MAX_SVC_NAME_LEN 256 /**< Maximum length of NAN service name */ #define ESP_WIFI_MAX_FILTER_LEN 256 /**< Maximum length of NAN service filter */ #define ESP_WIFI_MAX_SVC_INFO_LEN 64 /**< Maximum length of NAN service info */ +#define ESP_WIFI_MAX_FUP_SSI_LEN 2048 /**< Maximum length of NAN Service Specific Info in a Follow-up frame */ +#define ESP_WIFI_MAX_SVC_SSI_LEN 512 /**< Maximum length of NAN Service Specific Info in Publish/Subscribe SDF's */ #define ESP_WIFI_MAX_NEIGHBOR_REP_LEN 64 /**< Maximum length of NAN Neighbor Report */ +#define WIFI_OUI_LEN 3 /**< Length of OUI bytes in IE or attributes */ + +/** + * @brief Protocol types in NAN service specific info attribute + * + */ +typedef enum { + WIFI_SVC_PROTO_RESERVED = 0, /**< Value 0 Reserved */ + WIFI_SVC_PROTO_BONJOUR = 1, /**< Bonjour Protocol */ + WIFI_SVC_PROTO_GENERIC = 2, /**< Generic Service Protocol */ + WIFI_SVC_PROTO_CSA_MATTER = 3, /**< CSA Matter specific protocol */ + WIFI_SVC_PROTO_MAX, /**< Values 4-255 Reserved */ +} wifi_nan_svc_proto_t; + +/** + * @brief WFA defined Protocol types in NAN service specific info attribute + * + */ +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 payload[0]; /**< Service Info payload */ +} wifi_nan_wfa_ssi_t; /** * @brief NAN Services types @@ -820,10 +845,14 @@ typedef struct { char service_name[ESP_WIFI_MAX_SVC_NAME_LEN]; /**< Service name identifier */ wifi_nan_service_type_t type; /**< Service type */ char matching_filter[ESP_WIFI_MAX_FILTER_LEN]; /**< Comma separated filters for filtering services */ - char svc_info[ESP_WIFI_MAX_SVC_INFO_LEN]; /**< Service info shared in Publish frame */ + char svc_info[ESP_WIFI_MAX_SVC_INFO_LEN]; /**< To be deprecated in next major release, use ssi instead */ uint8_t single_replied_event: 1; /**< Give single Replied event or every time */ uint8_t datapath_reqd: 1; /**< NAN Datapath required for the service */ - uint8_t reserved: 6; /**< Reserved */ + 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 */ + 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 */ } wifi_nan_publish_cfg_t; /** @@ -834,9 +863,14 @@ typedef struct { char service_name[ESP_WIFI_MAX_SVC_NAME_LEN]; /**< Service name identifier */ wifi_nan_service_type_t type; /**< Service type */ char matching_filter[ESP_WIFI_MAX_FILTER_LEN]; /**< Comma separated filters for filtering services */ - char svc_info[ESP_WIFI_MAX_SVC_INFO_LEN]; /**< Service info shared in Subscribe frame */ - uint8_t single_match_event: 1; /**< Give single Match event or every time */ - uint8_t reserved: 7; /**< Reserved */ + char svc_info[ESP_WIFI_MAX_SVC_INFO_LEN]; /**< To be deprecated in next major release, use ssi instead */ + uint8_t single_match_event: 1; /**< Give single Match event(per SSI update) or every time */ + 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 */ + 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 */ } wifi_nan_subscribe_cfg_t; /** @@ -844,10 +878,12 @@ typedef struct { * */ typedef struct { - uint8_t inst_id; /**< Own service instance id */ - uint8_t peer_inst_id; /**< Peer's service instance id */ - uint8_t peer_mac[6]; /**< Peer's MAC address */ - char svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Service info(or message) to be shared */ + uint8_t inst_id; /**< Own service instance id */ + uint8_t peer_inst_id; /**< Peer's service instance id */ + uint8_t peer_mac[6]; /**< Peer's MAC address */ + char svc_info[ESP_WIFI_MAX_SVC_INFO_LEN]; /**< To be deprecated in next major release, use ssi instead */ + uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_FUP_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 */ } wifi_nan_followup_params_t; /** @@ -1255,6 +1291,15 @@ typedef struct { uint8_t publish_id; /**< Publish Service Identifier */ uint8_t pub_if_mac[6]; /**< NAN Interface MAC of the Publisher */ bool update_pub_id; /**< Indicates whether publisher's service ID needs to be updated */ + 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: 5; /**< Reserved */ + uint32_t reserved_1; /**< Reserved */ + uint32_t reserved_2; /**< Reserved */ + uint8_t ssi_version; /**< Indicates version of SSI in Publish instance, 0 if not available */ + uint16_t ssi_len; /**< Length of service specific info */ + uint8_t ssi[]; /**< Service specific info of Publisher */ } wifi_event_nan_svc_match_t; /** @@ -1264,6 +1309,10 @@ typedef struct { uint8_t publish_id; /**< Publish Service Identifier */ uint8_t subscribe_id; /**< Subscribe Service Identifier */ uint8_t sub_if_mac[6]; /**< NAN Interface MAC of the Subscriber */ + uint32_t reserved_1; /**< Reserved */ + uint32_t reserved_2; /**< Reserved */ + uint16_t ssi_len; /**< Length of service specific info */ + uint8_t ssi[]; /**< Service specific info of Subscriber */ } wifi_event_nan_replied_t; /** @@ -1273,7 +1322,11 @@ typedef struct { uint8_t inst_id; /**< Our Service Identifier */ uint8_t peer_inst_id; /**< Peer's Service Identifier */ uint8_t peer_if_mac[6]; /**< Peer's NAN Interface MAC */ - uint8_t peer_svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Peer Service Info */ + uint8_t peer_svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< To be deprecated in next major release, use ssi instead */ + uint32_t reserved_1; /**< Reserved */ + uint32_t reserved_2; /**< Reserved */ + uint16_t ssi_len; /**< Length of service specific info */ + uint8_t ssi[]; /**< Service specific info from Follow-up */ } wifi_event_nan_receive_t; /** @@ -1284,7 +1337,11 @@ typedef struct { uint8_t ndp_id; /**< NDP instance id */ uint8_t peer_nmi[6]; /**< Peer's NAN Management Interface MAC */ uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface MAC */ - uint8_t svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Service Specific Info */ + uint8_t svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< To be deprecated in next major release, use ssi instead */ + uint32_t reserved_1; /**< Reserved */ + uint32_t reserved_2; /**< Reserved */ + uint16_t ssi_len; /**< Length of service specific info */ + uint8_t ssi[]; /**< Service specific info from NDP/NDPE Attribute */ } wifi_event_ndp_indication_t; /** @@ -1296,7 +1353,11 @@ typedef struct { uint8_t peer_nmi[6]; /**< Peer's NAN Management Interface MAC */ uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface MAC */ uint8_t own_ndi[6]; /**< Own NAN Data Interface MAC */ - uint8_t svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< Service Specific Info */ + uint8_t svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];/**< To be deprecated in next major release, use ssi instead */ + uint32_t reserved_1; /**< Reserved */ + uint32_t reserved_2; /**< Reserved */ + uint16_t ssi_len; /**< Length of Service Specific Info */ + uint8_t ssi[]; /**< Service specific info from NDP/NDPE Attribute */ } wifi_event_ndp_confirm_t; /** diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 76ee3bdee6..a69f93dec1 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 76ee3bdee6d7fd13a803ac22bc0b236f0b1f7497 +Subproject commit a69f93dec1f06179caefc9e0f89f1fa7280fe002 diff --git a/components/esp_wifi/wifi_apps/nan_app/src/nan_app.c b/components/esp_wifi/wifi_apps/nan_app/src/nan_app.c index e30038c083..c4f62fba2c 100644 --- a/components/esp_wifi/wifi_apps/nan_app/src/nan_app.c +++ b/components/esp_wifi/wifi_apps/nan_app/src/nan_app.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,7 @@ #include "esp_mac.h" #include "os.h" #include "esp_nan.h" +#include "utils/common.h" /* NAN States */ #define NAN_STARTED_BIT BIT0 @@ -42,6 +43,7 @@ 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}; #define NAN_DATA_LOCK() os_mutex_lock(s_nan_data_lock) #define NAN_DATA_UNLOCK() os_mutex_unlock(s_nan_data_lock) @@ -371,19 +373,6 @@ static bool nan_is_datapath_active(void) return false; } -static void nan_update_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[]) -{ - struct peer_svc_info *peer_info = nan_find_peer_svc(own_svc_id, 0, peer_nmi); - if (peer_info) { - peer_info->svc_id = peer_svc_id; - } - - struct ndl_info *ndl = nan_find_ndl(0, peer_nmi); - if (ndl) { - ndl->publisher_id = peer_svc_id; - } -} - static void nan_fill_params_from_event(void *evt_data, uint8_t event) { switch (event) { @@ -421,12 +410,16 @@ static void nan_fill_params_from_event(void *evt_data, uint8_t event) } case WIFI_EVENT_NAN_SVC_MATCH: { wifi_event_nan_svc_match_t *evt = (wifi_event_nan_svc_match_t *)evt_data; + struct peer_svc_info *peer_info = nan_find_peer_svc(evt->subscribe_id, 0, evt->pub_if_mac); - if (evt->update_pub_id) { - nan_update_peer_svc(evt->subscribe_id, evt->publish_id, evt->pub_if_mac); - } + if (peer_info && peer_info->svc_id != evt->publish_id) { + struct ndl_info *ndl = nan_find_ndl(0, evt->pub_if_mac); - if (!nan_find_peer_svc(evt->subscribe_id, evt->publish_id, evt->pub_if_mac)) { + peer_info->svc_id = evt->publish_id; + if (ndl) { + ndl->publisher_id = evt->publish_id; + } + } else { nan_record_peer_svc(evt->subscribe_id, evt->publish_id, evt->pub_if_mac); } break; @@ -446,6 +439,9 @@ static void nan_app_action_service_match(void *arg, esp_event_base_t event_base, ESP_LOGI(TAG, "Service matched with "MACSTR" [Peer Publish id - %d]", MAC2STR(evt->pub_if_mac), evt->publish_id); + if (evt->ssi_len) { + ESP_LOG_BUFFER_HEXDUMP(TAG, evt->ssi, evt->ssi_len, ESP_LOG_DEBUG); + } NAN_DATA_LOCK(); nan_fill_params_from_event(evt, WIFI_EVENT_NAN_SVC_MATCH); NAN_DATA_UNLOCK(); @@ -458,9 +454,12 @@ static void nan_app_action_replied(void *arg, esp_event_base_t event_base, int32 } wifi_event_nan_replied_t *evt = (wifi_event_nan_replied_t *)data; - ESP_LOGD(TAG, "Sent Publish to Peer "MACSTR" [Peer Subscribe id - %d]", + ESP_LOGI(TAG, "Sent Publish to Peer "MACSTR" [Peer Subscribe id - %d]", MAC2STR(evt->sub_if_mac), evt->subscribe_id); + if (evt->ssi_len) { + ESP_LOG_BUFFER_HEXDUMP(TAG, evt->ssi, evt->ssi_len, ESP_LOG_DEBUG); + } NAN_DATA_LOCK(); nan_fill_params_from_event(evt, WIFI_EVENT_NAN_REPLIED); NAN_DATA_UNLOCK(); @@ -473,8 +472,13 @@ static void nan_app_action_receive(void *arg, esp_event_base_t event_base, int32 } wifi_event_nan_receive_t *evt = (wifi_event_nan_receive_t *)data; - ESP_LOGI(TAG, "Received message '%s' from Peer "MACSTR" [Peer Service id - %d]", - evt->peer_svc_info, MAC2STR(evt->peer_if_mac), evt->peer_inst_id); + if (evt->ssi_len) { + ESP_LOGD(TAG, "Received payload from Peer "MACSTR" [Peer Service id - %d] - ", MAC2STR(evt->peer_if_mac), evt->peer_inst_id); + ESP_LOG_BUFFER_HEXDUMP(TAG, evt->ssi, evt->ssi_len, ESP_LOG_DEBUG); + } else { + ESP_LOGD(TAG, "Received message '%s' from Peer "MACSTR" [Peer Service id - %d]", + evt->peer_svc_info, MAC2STR(evt->peer_if_mac), evt->peer_inst_id); + } NAN_DATA_LOCK(); nan_fill_params_from_event(evt, WIFI_EVENT_NAN_RECEIVE); @@ -841,6 +845,20 @@ uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg, 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) { ESP_LOGE(TAG, "Failed to publish service '%s'", publish_cfg->service_name); goto fail; @@ -875,6 +893,20 @@ 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) { ESP_LOGE(TAG, "Failed to subscribe to service '%s'", subscribe_cfg->service_name); goto fail; @@ -903,6 +935,20 @@ esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params) 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; } @@ -918,8 +964,15 @@ esp_err_t esp_wifi_nan_send_message(wifi_nan_followup_params_t *fup_params) ESP_LOGE(TAG, "Failed to send Follow-up message!"); return ESP_FAIL; } - ESP_LOGI(TAG, "Sent message '%s' to Peer "MACSTR" with Service ID %d", fup_params->svc_info, + + if (fup_params->ssi) { + ESP_LOGD(TAG, "Sent below payload 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 '%s' to Peer "MACSTR" with Service ID %d", fup_params->svc_info, MAC2STR(fup_params->peer_mac), fup_params->peer_inst_id); + } return ESP_OK; } diff --git a/examples/wifi/wifi_aware/nan_console/main/nan_main.c b/examples/wifi/wifi_aware/nan_console/main/nan_main.c index a2734340ce..a3d9f7ef46 100644 --- a/examples/wifi/wifi_aware/nan_console/main/nan_main.c +++ b/examples/wifi/wifi_aware/nan_console/main/nan_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -107,6 +107,19 @@ static esp_netif_t *g_nan_netif; #define NAN_EXAMPLE_SERVICE_NAME "ESP_NAN-Service" +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->ssi_len) { + ESP_LOGI(TAG, "Received payload from Peer "MACSTR" [Peer Service id - %d] - ", MAC2STR(evt->peer_if_mac), evt->peer_inst_id); + ESP_LOG_BUFFER_HEXDUMP(TAG, evt->ssi, evt->ssi_len, ESP_LOG_INFO); + } else { + ESP_LOGI(TAG, "Received message '%s' from Peer "MACSTR" [Peer Service id - %d]", + evt->peer_svc_info, MAC2STR(evt->peer_if_mac), evt->peer_inst_id); + } +} + static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args) { uint8_t ttl; @@ -210,6 +223,7 @@ void initialise_wifi(void) static int wifi_cmd_nan_disc(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **) &nan_args); + static esp_event_handler_instance_t s_instance_nan_receive; esp_err_t ret; if (nerrors != 0) { @@ -241,6 +255,12 @@ static int wifi_cmd_nan_disc(int argc, char **argv) esp_netif_destroy_default_wifi(g_nan_netif); return 1; } + + if (!s_instance_nan_receive) { + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_NAN_RECEIVE, + &nan_receive_event_handler, NULL, &s_instance_nan_receive)); + } + return 0; } @@ -251,6 +271,10 @@ static int wifi_cmd_nan_disc(int argc, char **argv) ESP_LOGI(TAG, "Failed to stop NAN"); return 1; } + + ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, WIFI_EVENT_NAN_RECEIVE, + s_instance_nan_receive)); + s_instance_nan_receive = 0; esp_netif_destroy_default_wifi(g_nan_netif); } @@ -349,38 +373,59 @@ static int wifi_cmd_nan_subscribe(int argc, char **argv) static int wifi_cmd_nan_followup(int argc, char **argv) { int nerrors = arg_parse(argc, argv, (void **) &fup_args); + uint16_t ssi_len = 0; + int ret = 0; if (nerrors != 0) { arg_print_errors(stderr, fup_args.end, argv[0]); return 1; } - wifi_nan_followup_params_t fup = {0}; + if (fup_args.text->count) { + ssi_len = strlen(fup_args.text->sval[0]); + if (ssi_len >= ESP_WIFI_MAX_FUP_SSI_LEN) { + ESP_LOGE(TAG, "Length(%d) too long for Service Specific Info", ssi_len); + return 1; + } + } + wifi_nan_followup_params_t *fup = calloc(1, sizeof(wifi_nan_followup_params_t) + ssi_len); + + if (!fup) { + ESP_LOGE(TAG, "Failed to allocate memory for Follow-up buffer"); + return 1; + } + if (ssi_len) { + fup->ssi = (uint8_t *)(fup + 1); + memcpy(fup->ssi, fup_args.text->sval[0], ssi_len); + fup->ssi_len = ssi_len; + } + if (fup_args.own_id->count) { - fup.inst_id = fup_args.own_id->ival[0]; + fup->inst_id = fup_args.own_id->ival[0]; } if (!fup_args.peer_id->count && !fup_args.mac_addr->count) { - ESP_LOGE(TAG, "Missing peer's service instance id or peer's MAC."); - return 1; + ESP_LOGE(TAG, "Missing peer's service instance id or peer's MAC"); + ret = 1; + goto exit; } if (fup_args.peer_id->count) { - fup.peer_inst_id = fup_args.peer_id->ival[0]; + fup->peer_inst_id = fup_args.peer_id->ival[0]; } if (fup_args.mac_addr->count && - esp_supplicant_str_to_mac((char *)fup_args.mac_addr->sval[0], fup.peer_mac) != ESP_OK) { - return 1; + esp_supplicant_str_to_mac((char *)fup_args.mac_addr->sval[0], fup->peer_mac) != ESP_OK) { + ret = 1; + goto exit; } - if (fup_args.text->count) { - strlcpy(fup.svc_info, fup_args.text->sval[0], ESP_WIFI_MAX_SVC_INFO_LEN); + if (esp_wifi_nan_send_message(fup) != ESP_OK) { + ESP_LOGE(TAG, "Failed to send Follow-up"); + ret = 1; } - if (esp_wifi_nan_send_message(&fup) != ESP_OK) { - return 1; - } - - return 0; +exit: + free(fup); + return ret; } static int wifi_cmd_ndp(int argc, char **argv) @@ -443,7 +488,7 @@ void register_nan(void) nan_args.init = arg_lit0("S", "start", "NAN Start"); nan_args.deinit = arg_lit0("T", "stop", "NAN Stop"); nan_args.master_pref = arg_int0("p", "mast_pref", "<1-254>", "NAN Master Preference"); - nan_args.op_channel = arg_int0("c", "op_chan", "<1-11>", "NAN Operating Channe"); + nan_args.op_channel = arg_int0("c", "op_chan", "<1-11>", "NAN Operating Channel"); nan_args.warmup_time = arg_int0("w", "warmup", "<5-120>", "NAN Warmup Time in Sec"); nan_args.end = arg_end(1); diff --git a/examples/wifi/wifi_aware/nan_publisher/main/publisher_main.c b/examples/wifi/wifi_aware/nan_publisher/main/publisher_main.c index 027b784b8e..95db62eb78 100644 --- a/examples/wifi/wifi_aware/nan_publisher/main/publisher_main.c +++ b/examples/wifi/wifi_aware/nan_publisher/main/publisher_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -30,17 +30,30 @@ #else #define EXAMPLE_NAN_SVC_MSG "Welcome" #endif +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif static EventGroupHandle_t nan_event_group; +static const char *TAG = "publisher"; static int NAN_RECEIVE = BIT0; uint8_t g_peer_inst_id; +static uint8_t g_peer_mac[ETH_ALEN]; 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; g_peer_inst_id = evt->peer_inst_id; + memcpy(g_peer_mac, evt->peer_if_mac, ETH_ALEN); + if (evt->ssi_len) { + ESP_LOGI(TAG, "Received payload from Peer "MACSTR" [Peer Service id - %d] - ", MAC2STR(evt->peer_if_mac), evt->peer_inst_id); + ESP_LOG_BUFFER_HEXDUMP(TAG, evt->ssi, evt->ssi_len, ESP_LOG_INFO); + } else { + ESP_LOGI(TAG, "Received message '%s' from Peer "MACSTR" [Peer Service id - %d]", + evt->peer_svc_info, MAC2STR(evt->peer_if_mac), evt->peer_inst_id); + } xEventGroupSetBits(nan_event_group, NAN_RECEIVE); } @@ -55,7 +68,7 @@ static void nan_ndp_indication_event_handler(void *arg, esp_event_base_t event_b wifi_nan_datapath_resp_t ndp_resp = {0}; ndp_resp.accept = true; /* Accept incoming datapath request */ ndp_resp.ndp_id = evt->ndp_id; - memcpy(ndp_resp.peer_mac, evt->peer_nmi, 6); + memcpy(ndp_resp.peer_mac, evt->peer_nmi, ETH_ALEN); esp_wifi_nan_datapath_resp(&ndp_resp); @@ -106,20 +119,27 @@ void wifi_nan_publish(void) return; } + wifi_nan_followup_params_t fup = {0}; + fup.ssi_len = (strlen(EXAMPLE_NAN_SVC_MSG) < ESP_WIFI_MAX_FUP_SSI_LEN) ? strlen(EXAMPLE_NAN_SVC_MSG) : ESP_WIFI_MAX_FUP_SSI_LEN; + fup.ssi = calloc(1, fup.ssi_len); + if (!fup.ssi) { + ESP_LOGE(TAG, "Failed to allocate for Follow-up"); + return; + } + memcpy((char *)fup.ssi, EXAMPLE_NAN_SVC_MSG, fup.ssi_len); + fup.inst_id = pub_id; + while (1) { EventBits_t bits = xEventGroupWaitBits(nan_event_group, NAN_RECEIVE, pdFALSE, pdFALSE, portMAX_DELAY); if (bits & NAN_RECEIVE) { xEventGroupClearBits(nan_event_group, NAN_RECEIVE); - wifi_nan_followup_params_t fup = {0}; - fup.inst_id = pub_id, - fup.peer_inst_id = g_peer_inst_id, - strlcpy(fup.svc_info, EXAMPLE_NAN_SVC_MSG, ESP_WIFI_MAX_SVC_INFO_LEN); - + fup.peer_inst_id = g_peer_inst_id; + memcpy(fup.peer_mac, g_peer_mac, sizeof(fup.peer_mac)); /* Reply to the message from a subscriber */ esp_wifi_nan_send_message(&fup); } - vTaskDelay(10); } + free(fup.ssi); } void initialise_wifi(void) diff --git a/examples/wifi/wifi_aware/nan_subscriber/main/subscriber_main.c b/examples/wifi/wifi_aware/nan_subscriber/main/subscriber_main.c index c6096516ef..faeac46178 100644 --- a/examples/wifi/wifi_aware/nan_subscriber/main/subscriber_main.c +++ b/examples/wifi/wifi_aware/nan_subscriber/main/subscriber_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -32,7 +32,7 @@ #define EXAMPLE_NAN_SVC_MSG "Hello" #endif -static const char *TAG = "nan_sub"; +static const char *TAG = "subscriber"; static EventGroupHandle_t nan_event_group; @@ -42,8 +42,21 @@ const int NDP_FAILED = BIT2; static wifi_event_nan_svc_match_t g_svc_match_evt; +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->ssi_len) { + ESP_LOGI(TAG, "Received payload from Peer "MACSTR" [Peer Service id - %d] - ", MAC2STR(evt->peer_if_mac), evt->peer_inst_id); + ESP_LOG_BUFFER_HEXDUMP(TAG, evt->ssi, evt->ssi_len, ESP_LOG_INFO); + } else { + ESP_LOGI(TAG, "Received message '%s' from Peer "MACSTR" [Peer Service id - %d]", + evt->peer_svc_info, MAC2STR(evt->peer_if_mac), evt->peer_inst_id); + } +} + #ifdef CONFIG_EXAMPLE_NAN_SEND_PING -static uint8_t g_peer_ndi[6]; +static uint8_t g_peer_ndi[ETH_ALEN]; static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args) { @@ -149,6 +162,11 @@ void wifi_nan_subscribe(void) &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)); #ifdef CONFIG_EXAMPLE_NAN_SEND_PING ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, @@ -189,13 +207,20 @@ void wifi_nan_subscribe(void) wifi_nan_followup_params_t fup = { .inst_id = sub_id, .peer_inst_id = g_svc_match_evt.publish_id, - .svc_info = EXAMPLE_NAN_SVC_MSG, }; memcpy(fup.peer_mac, g_svc_match_evt.pub_if_mac, sizeof(fup.peer_mac)); + fup.ssi_len = (strlen(EXAMPLE_NAN_SVC_MSG) < ESP_WIFI_MAX_FUP_SSI_LEN) ? strlen(EXAMPLE_NAN_SVC_MSG) : ESP_WIFI_MAX_FUP_SSI_LEN; + fup.ssi = calloc(1, fup.ssi_len); + if (!fup.ssi) { + ESP_LOGE(TAG, "Failed to allocate for Follow-up"); + return; + } + memcpy((char *)fup.ssi, EXAMPLE_NAN_SVC_MSG, fup.ssi_len); if (esp_wifi_nan_send_message(&fup) == ESP_OK) ESP_LOGI(TAG, "Sending message '%s' to Publisher "MACSTR" ...", EXAMPLE_NAN_SVC_MSG, MAC2STR(g_svc_match_evt.pub_if_mac)); + free(fup.ssi); #endif #ifdef CONFIG_EXAMPLE_NAN_SEND_PING wifi_nan_datapath_req_t ndp_req = {0};