mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 22:08:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			246 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: Unlicense OR CC0-1.0
 | 
						|
 *
 | 
						|
 * This test code is in the Public Domain (or CC0 licensed, at your option.)
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, this
 | 
						|
 * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 | 
						|
 * CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 */
 | 
						|
 | 
						|
#include "string.h"
 | 
						|
#include "esp_system.h"
 | 
						|
#include "unity.h"
 | 
						|
#include "esp_system.h"
 | 
						|
#include "esp_event.h"
 | 
						|
#include "esp_wifi_types.h"
 | 
						|
#include "utils/common.h"
 | 
						|
#include "common/ieee802_11_defs.h"
 | 
						|
#include "../esp_supplicant/src/esp_wifi_driver.h"
 | 
						|
#include "esp_log.h"
 | 
						|
#include "test_utils.h"
 | 
						|
#include "memory_checks.h"
 | 
						|
#include "freertos/event_groups.h"
 | 
						|
 | 
						|
#define WIFI_START_EVENT        0x00000001
 | 
						|
#define WIFI_ROC_DONE_EVENT     0x00000002
 | 
						|
#define WIFI_ACTION_RX_EVENT    0x00000003
 | 
						|
#define WIFI_SCAN_DONE_EVENT    0x00000004
 | 
						|
 | 
						|
#define TEST_LISTEN_CHANNEL     6
 | 
						|
 | 
						|
/* No runners */
 | 
						|
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3, ESP32C2, ESP32C6, ESP32H2)
 | 
						|
//IDF-5046
 | 
						|
static const char *TAG = "test_offchan";
 | 
						|
esp_netif_t *wifi_netif;
 | 
						|
static EventGroupHandle_t wifi_event;
 | 
						|
 | 
						|
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
 | 
						|
                               int32_t event_id, void *event_data)
 | 
						|
{
 | 
						|
    switch (event_id) {
 | 
						|
    case WIFI_EVENT_STA_START:
 | 
						|
        ESP_LOGI(TAG, "WIFI Started");
 | 
						|
        xEventGroupSetBits(wifi_event, WIFI_START_EVENT);
 | 
						|
        break;
 | 
						|
    case WIFI_EVENT_ACTION_TX_STATUS: {
 | 
						|
        wifi_event_action_tx_status_t *evt =
 | 
						|
            (wifi_event_action_tx_status_t *)event_data;
 | 
						|
 | 
						|
        if (evt->status == 0) {
 | 
						|
            ESP_LOGI(TAG, "Action Tx Successful");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    break;
 | 
						|
    case WIFI_EVENT_ROC_DONE:
 | 
						|
        ESP_LOGI(TAG, "ROC Done");
 | 
						|
        xEventGroupSetBits(wifi_event, WIFI_ROC_DONE_EVENT);
 | 
						|
        break;
 | 
						|
    case WIFI_EVENT_SCAN_DONE:
 | 
						|
        ESP_LOGI(TAG, "Scan Done");
 | 
						|
        xEventGroupSetBits(wifi_event, WIFI_SCAN_DONE_EVENT);
 | 
						|
        break;
 | 
						|
    default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
static esp_err_t event_init(void)
 | 
						|
{
 | 
						|
    ESP_ERROR_CHECK(esp_event_loop_create_default());
 | 
						|
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
 | 
						|
    wifi_netif = esp_netif_create_default_wifi_sta();
 | 
						|
 | 
						|
    return ESP_OK;
 | 
						|
}
 | 
						|
 | 
						|
static void start_wifi_as_sta(void)
 | 
						|
{
 | 
						|
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
 | 
						|
    cfg.nvs_enable = false;
 | 
						|
 | 
						|
    event_init();
 | 
						|
 | 
						|
    // can't deinit event loop, need to reset leak check
 | 
						|
    test_utils_record_free_mem();
 | 
						|
 | 
						|
    if (wifi_event == NULL) {
 | 
						|
        wifi_event = xEventGroupCreate();
 | 
						|
    } else {
 | 
						|
        xEventGroupClearBits(wifi_event, 0x00ffffff);
 | 
						|
    }
 | 
						|
 | 
						|
    TEST_ESP_OK(esp_wifi_init(&cfg));
 | 
						|
    TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_STA));
 | 
						|
    TEST_ESP_OK(esp_wifi_start());
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static void stop_wifi(void)
 | 
						|
{
 | 
						|
    esp_event_loop_delete_default();
 | 
						|
    ESP_LOGI(TAG, "Stop wifi\n");
 | 
						|
    TEST_ESP_OK(esp_wifi_stop());
 | 
						|
    TEST_ESP_OK(esp_wifi_deinit());
 | 
						|
    esp_wifi_clear_default_wifi_driver_and_handlers(wifi_netif);
 | 
						|
    esp_netif_destroy(wifi_netif);
 | 
						|
    if (wifi_event) {
 | 
						|
        vEventGroupDelete(wifi_event);
 | 
						|
        wifi_event = NULL;
 | 
						|
    }
 | 
						|
    vTaskDelay(1000 / portTICK_PERIOD_MS);
 | 
						|
}
 | 
						|
 | 
						|
int dummy_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel)
 | 
						|
{
 | 
						|
    return ESP_OK;
 | 
						|
}
 | 
						|
 | 
						|
static const char *frame_data = "This is a test data";
 | 
						|
 | 
						|
void esp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint32_t len,
 | 
						|
                           uint8_t channel, uint32_t wait_time_ms)
 | 
						|
{
 | 
						|
    wifi_action_tx_req_t *req = os_zalloc(sizeof(*req) + len);;
 | 
						|
    TEST_ASSERT( req != NULL);
 | 
						|
 | 
						|
    req->ifx = WIFI_IF_STA;
 | 
						|
    memcpy(req->dest_mac, dest_mac, ETH_ALEN);
 | 
						|
    req->no_ack = false;
 | 
						|
    req->data_len = len;
 | 
						|
    req->rx_cb = dummy_rx_action;
 | 
						|
    memcpy(req->data, buf, req->data_len);
 | 
						|
 | 
						|
    ESP_LOGI(TAG, "Action Tx - MAC:" MACSTR ", Channel-%d, WaitT-%d",
 | 
						|
             MAC2STR(dest_mac), channel, wait_time_ms);
 | 
						|
 | 
						|
    TEST_ESP_OK(esp_wifi_action_tx_req(WIFI_OFFCHAN_TX_REQ, channel, wait_time_ms, req));
 | 
						|
 | 
						|
    os_free(req);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Test that foreground Scan doesn't pre-empt ROC & vice versa */
 | 
						|
TEST_CASE("Test scan and ROC simultaneously", "[Offchan]")
 | 
						|
{
 | 
						|
    wifi_action_rx_cb_t rx_cb = dummy_rx_action;
 | 
						|
    EventBits_t bits;
 | 
						|
 | 
						|
    test_case_uses_tcpip();
 | 
						|
    start_wifi_as_sta();
 | 
						|
 | 
						|
    xEventGroupWaitBits(wifi_event, WIFI_START_EVENT, 1, 0, 5000 / portTICK_PERIOD_MS);
 | 
						|
 | 
						|
    TEST_ESP_OK(esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_REQ, TEST_LISTEN_CHANNEL,
 | 
						|
                                           100, rx_cb));
 | 
						|
    ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, false));
 | 
						|
    bits = xEventGroupWaitBits(wifi_event, WIFI_ROC_DONE_EVENT | WIFI_SCAN_DONE_EVENT,
 | 
						|
                               pdTRUE, pdFALSE, 5000 / portTICK_PERIOD_MS);
 | 
						|
    TEST_ASSERT_TRUE(bits == WIFI_ROC_DONE_EVENT);
 | 
						|
 | 
						|
    vTaskDelay(1000 / portTICK_PERIOD_MS);
 | 
						|
    ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, false));
 | 
						|
    TEST_ESP_OK(esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_REQ, TEST_LISTEN_CHANNEL,
 | 
						|
                                           100, rx_cb));
 | 
						|
    bits = xEventGroupWaitBits(wifi_event, WIFI_ROC_DONE_EVENT | WIFI_SCAN_DONE_EVENT,
 | 
						|
                               pdTRUE, pdFALSE, 5000 / portTICK_PERIOD_MS);
 | 
						|
    TEST_ASSERT_TRUE(bits == WIFI_SCAN_DONE_EVENT);
 | 
						|
 | 
						|
    stop_wifi();
 | 
						|
}
 | 
						|
 | 
						|
static void test_wifi_offchan_tx(void)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    char mac_str[19];
 | 
						|
    uint8_t mac[6];
 | 
						|
 | 
						|
    test_case_uses_tcpip();
 | 
						|
    start_wifi_as_sta();
 | 
						|
    xEventGroupWaitBits(wifi_event, WIFI_START_EVENT, 1, 0, 5000 / portTICK_PERIOD_MS);
 | 
						|
 | 
						|
    unity_wait_for_signal_param("Listener mac", mac_str, 19);
 | 
						|
 | 
						|
    TEST_ASSERT_TRUE(unity_util_convert_mac_from_string(mac_str, mac));
 | 
						|
 | 
						|
    for (i = 0; i < 3; i++) {
 | 
						|
        esp_send_action_frame(mac, (const uint8_t *)frame_data, strlen(frame_data),
 | 
						|
                              TEST_LISTEN_CHANNEL, 500);
 | 
						|
        vTaskDelay(500 / portTICK_PERIOD_MS);
 | 
						|
    }
 | 
						|
 | 
						|
    stop_wifi();
 | 
						|
}
 | 
						|
 | 
						|
static int test_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel)
 | 
						|
{
 | 
						|
    struct ieee80211_hdr *rx_hdr = (struct ieee80211_hdr *)hdr;
 | 
						|
 | 
						|
    ESP_LOGI(TAG, "Rxd Action Frame from " MACSTR " (Seq-%lu)", MAC2STR(rx_hdr->addr2),
 | 
						|
             WLAN_GET_SEQ_SEQ(rx_hdr->seq_ctrl));
 | 
						|
 | 
						|
    if (!os_memcmp(payload, frame_data, strlen(frame_data))) {
 | 
						|
        xEventGroupSetBits(wifi_event, WIFI_ACTION_RX_EVENT);
 | 
						|
    }
 | 
						|
 | 
						|
    return ESP_OK;
 | 
						|
}
 | 
						|
 | 
						|
static void test_wifi_roc(void)
 | 
						|
{
 | 
						|
    wifi_action_rx_cb_t rx_cb = test_rx_action;
 | 
						|
    char mac_str[19] = {0};
 | 
						|
    EventBits_t bits;
 | 
						|
    uint8_t mac[6];
 | 
						|
 | 
						|
    test_case_uses_tcpip();
 | 
						|
    start_wifi_as_sta();
 | 
						|
 | 
						|
    xEventGroupWaitBits(wifi_event, WIFI_START_EVENT, 1, 0, 5000 / portTICK_PERIOD_MS);
 | 
						|
    TEST_ESP_OK(esp_wifi_get_mac(WIFI_IF_STA, mac));
 | 
						|
    sprintf(mac_str, MACSTR, MAC2STR(mac));
 | 
						|
    unity_send_signal_param("Listener mac", mac_str);
 | 
						|
 | 
						|
    TEST_ESP_OK(esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_REQ, TEST_LISTEN_CHANNEL,
 | 
						|
                                           10000, rx_cb));
 | 
						|
    bits = xEventGroupWaitBits(wifi_event, WIFI_ROC_DONE_EVENT | WIFI_ACTION_RX_EVENT,
 | 
						|
                               pdTRUE, pdFALSE, portMAX_DELAY);
 | 
						|
    /* Confirm that Frame has been received successfully */
 | 
						|
    if (bits == WIFI_ACTION_RX_EVENT) {
 | 
						|
        TEST_ESP_OK(esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_CANCEL, 0, 0, NULL));
 | 
						|
        vTaskDelay(1000 / portTICK_PERIOD_MS);
 | 
						|
        stop_wifi();
 | 
						|
    } else {
 | 
						|
        stop_wifi();
 | 
						|
        TEST_FAIL();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
TEST_CASE_MULTIPLE_DEVICES("test ROC and Offchannel Action Frame Tx", "[Offchan][test_env=UT_T2_1][timeout=90]", test_wifi_roc, test_wifi_offchan_tx);
 | 
						|
 | 
						|
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(...)
 |