WiFi: Add WPS softAP registrar example and events

This commit is contained in:
Kapil Gupta 2022-06-08 13:53:59 +05:30
parent a6982a92fe
commit 924c709efe
19 changed files with 446 additions and 127 deletions

View File

@ -646,6 +646,12 @@ typedef enum {
WIFI_EVENT_CONNECTIONLESS_MODULE_WAKE_INTERVAL_START, /**< ESP32 connectionless module wake interval start */
WIFI_EVENT_AP_WPS_RG_SUCCESS, /**< Soft-AP wps succeeds in registrar mode */
WIFI_EVENT_AP_WPS_RG_FAILED, /**< Soft-AP wps fails in registrar mode */
WIFI_EVENT_AP_WPS_RG_TIMEOUT, /**< Soft-AP wps timeout in registrar mode */
WIFI_EVENT_AP_WPS_RG_PIN, /**< Soft-AP wps pin code in registrar mode */
WIFI_EVENT_AP_WPS_RG_PBC_OVERLAP, /**< Soft-AP wps overlap in registrar mode */
WIFI_EVENT_MAX, /**< Invalid WiFi event ID */
} wifi_event_t;
@ -789,6 +795,29 @@ typedef struct {
uint32_t context; /**< Context to identify the request */
} wifi_event_roc_done_t;
/** Argument structure for WIFI_EVENT_AP_WPS_RG_PIN event */
typedef struct {
uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */
} wifi_event_ap_wps_rg_pin_t;
typedef enum {
WPS_AP_FAIL_REASON_NORMAL = 0, /**< WPS normal fail reason */
WPS_AP_FAIL_REASON_CONFIG, /**< WPS failed due to incorrect config */
WPS_AP_FAIL_REASON_AUTH, /**< WPS failed during auth */
WPS_AP_FAIL_REASON_MAX,
} wps_fail_reason_t;
/** Argument structure for WIFI_EVENT_AP_WPS_RG_FAILED event */
typedef struct {
wps_fail_reason_t reason; /**< WPS failure reason wps_fail_reason_t */
uint8_t peer_macaddr[6]; /**< Enrollee mac address */
} wifi_event_ap_wps_rg_fail_reason_t;
/** Argument structure for WIFI_EVENT_AP_WPS_RG_SUCCESS event */
typedef struct {
uint8_t peer_macaddr[6]; /**< Enrollee mac address */
} wifi_event_ap_wps_rg_success_t;
#ifdef __cplusplus
}
#endif

@ -1 +1 @@
Subproject commit 9e81af17476302dbf053242a9a0a9b81a3cd2949
Subproject commit 2fae5b132437907691d51ac4b3c31227b7b7ab33

View File

@ -119,7 +119,7 @@ esp_err_t esp_wifi_wps_start(int timeout_ms);
*
* @attention WPS can only be used when softAP is enabled.
*
* @param wps_type_t wps_type : WPS type, so far only WPS_TYPE_PBC and WPS_TYPE_PIN is supported
* @param esp_wps_config_t config: wps configuration to be used.
*
* @return
* - ESP_OK : succeed
@ -145,6 +145,10 @@ esp_err_t esp_wifi_ap_wps_disable(void);
*
* @attention WPS can only be used when softAP is enabled.
*
* @param pin : Pin to be used in case of WPS mode is pin.
* If Pin is not provided, device will use the pin generated/provided
* during esp_wifi_ap_wps_enable() and reported in WIFI_EVENT_AP_WPS_RG_PIN
*
* @return
* - ESP_OK : succeed
* - ESP_ERR_WIFI_WPS_TYPE : wps type is invalid

View File

@ -32,7 +32,7 @@ extern void *s_wps_api_lock;
extern void *s_wps_api_sem;
extern bool s_wps_enabled;
static int wifi_ap_wps_init(void)
static int wifi_ap_wps_init(const esp_wps_config_t *config)
{
struct wps_sm *sm = NULL;
uint8_t mac[ETH_ALEN];
@ -69,6 +69,7 @@ static int wifi_ap_wps_init(void)
cfg.registrar = 1;
cfg.wps = sm->wps_ctx;
os_memcpy((void *)cfg.pin, config->pin, 8);
wps_init_cfg_pin(&cfg);
os_memcpy(cfg.wps->uuid, sm->uuid, WPS_UUID_LEN);
if ((sm->wps = wps_init(&cfg)) == NULL) { /* alloc wps_data */
@ -76,6 +77,14 @@ static int wifi_ap_wps_init(void)
}
hostapd_init_wps(hostapd_get_hapd_data(), sm->wps, sm->wps_ctx);
/* Report PIN */
if (wps_get_type() == WPS_TYPE_PIN) {
wifi_event_sta_wps_er_pin_t evt;
os_memcpy(evt.pin_code, sm->wps->dev_password, 8);
esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_PIN, &evt, sizeof(evt), OS_BLOCK);
}
return ESP_OK;
_err:
@ -102,23 +111,26 @@ int wifi_ap_wps_deinit(void)
{
struct wps_sm *sm = gWpsSm;
hostapd_deinit_wps(hostapd_get_hapd_data());
if (gWpsSm == NULL) {
return ESP_FAIL;
}
hostapd_deinit_wps(hostapd_get_hapd_data());
if (sm->wps) {
sm->wps->registrar = 0;
wps_deinit(sm->wps);
sm->wps = NULL;
}
if (sm->dev) {
wps_dev_deinit(sm->dev);
sm->dev = NULL;
}
if (sm->wps_ctx) {
os_free(sm->wps_ctx);
sm->wps_ctx = NULL;
}
if (sm->wps) {
wps_deinit(sm->wps);
sm->wps = NULL;
}
os_free(gWpsSm);
gWpsSm = NULL;
@ -146,7 +158,7 @@ int wifi_ap_wps_enable_internal(const esp_wps_config_t *config)
wps_set_type(config->wps_type);
wps_set_status(WPS_STATUS_DISABLE);
ret = wifi_ap_wps_init();
ret = wifi_ap_wps_init(config);
if (ret != 0) {
wps_set_type(WPS_STATUS_DISABLE);
@ -199,8 +211,8 @@ int esp_wifi_ap_wps_disable(void)
}
wpa_printf(MSG_INFO, "wifi_wps_disable");
wps_set_status(WPS_STATUS_DISABLE);
wps_set_type(WPS_TYPE_DISABLE);
wps_set_status(WPS_STATUS_DISABLE);
wifi_ap_wps_deinit();
@ -232,15 +244,20 @@ int esp_wifi_ap_wps_start(const unsigned char *pin)
}
if (wps_get_type() == WPS_TYPE_DISABLE || (wps_get_status() != WPS_STATUS_DISABLE && wps_get_status() != WPS_STATUS_SCANNING)) {
wpa_printf(MSG_ERROR, "wps start: wps_get_type=%d wps_get_status=%d", wps_get_type(), wps_get_status());
API_MUTEX_GIVE();
return ESP_ERR_WIFI_WPS_TYPE;
}
if (esp_wifi_get_user_init_flag_internal() == 0) {
wpa_printf(MSG_ERROR, "wps start: esp_wifi_get_user_init_flag_internal=%d", esp_wifi_get_user_init_flag_internal());
API_MUTEX_GIVE();
return ESP_ERR_WIFI_STATE;
}
if (!pin) {
pin = gWpsSm->wps->dev_password;
}
/* TODO ideally SoftAP mode should also do a single scan in PBC mode
* however softAP scanning is not available at the moment */
wps_set_status(WPS_STATUS_PENDING);

View File

@ -1188,22 +1188,7 @@ int wps_dev_deinit(struct wps_device_data *dev)
if (!dev) {
return ESP_FAIL;
}
if (dev->manufacturer) {
os_free(dev->manufacturer);
}
if (dev->model_name) {
os_free(dev->model_name);
}
if (dev->model_number) {
os_free(dev->model_number);
}
if (dev->device_name) {
os_free(dev->device_name);
}
if (dev->serial_number) {
os_free(dev->serial_number);
}
wps_device_data_free(dev);
if (s_factory_info) {
os_free(s_factory_info);
@ -1358,21 +1343,23 @@ int wps_init_cfg_pin(struct wps_config *cfg)
}
cfg->pbc = 0;
if (os_strncmp((char *)cfg->pin, "00000000", 8) != 0) {
if ((os_strncmp((char *)cfg->pin, "00000000", 8) == 0) || !wps_pin_str_valid((char *)cfg->pin)) {
unsigned int spin = 0;
cfg->dev_pw_id = DEV_PW_DEFAULT;
cfg->pin_len = 8;
if (wps_generate_pin(&spin) < 0) {
return -1;
}
wpa_printf(MSG_INFO, "Provided PIN %s is not valid, generated a new PIN %08d", (char *)cfg->pin, spin);
os_snprintf((char *)cfg->pin, 9, "%08d", spin);
}
return 0;
}
int
wifi_station_wps_init(void)
static int wifi_station_wps_init(const esp_wps_config_t *config)
{
struct wps_funcs *wps_cb;
struct wps_sm *sm = NULL;
@ -1408,6 +1395,7 @@ wifi_station_wps_init(void)
cfg.wps = sm->wps_ctx;
os_memcpy((void *)cfg.pin, config->pin, 8);
if (wps_init_cfg_pin(&cfg) < 0) {
goto _err;
}
@ -1858,7 +1846,7 @@ int wifi_wps_enable_internal(const esp_wps_config_t *config)
wps_set_type(config->wps_type);
wps_set_status(WPS_STATUS_DISABLE);
ret = wifi_station_wps_init();
ret = wifi_station_wps_init(config);
if (ret != 0) {
wps_set_type(WPS_STATUS_DISABLE);

View File

@ -17,6 +17,7 @@
#include "wpa_auth.h"
#include "ap_config.h"
#include "sta_info.h"
#include "esp_wps_i.h"
static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
void hostapd_wps_eap_completed(struct hostapd_data *hapd);
@ -167,7 +168,6 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
{
struct hostapd_data *hapd = eloop_ctx;
struct sta_info *sta = timeout_ctx;
u16 reason;
@ -177,14 +177,21 @@ static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED;
esp_wifi_ap_deauth_internal(sta->addr, reason);
if (sta->flags & WLAN_STA_WPS)
hostapd_wps_eap_completed(hapd);
}
void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
struct sta_info *sta)
{
#ifdef ESP_SUPPLICANT
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
"IEEE 802.1X: Scheduled disconnection of " MACSTR
" after EAP-Failure", MAC2STR(sta->addr));
esp_wifi_ap_deauth_internal(sta->addr, WLAN_REASON_IEEE_802_1X_AUTH_FAILED);
if (wps_get_status() == WPS_STATUS_PENDING)
wps_set_status(WPS_STATUS_DISABLE);
#else
wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
"IEEE 802.1X: Force disconnection of " MACSTR
" after EAP-Failure in 10 ms", MAC2STR(sta->addr));
@ -197,6 +204,7 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
eloop_register_timeout(0, 10000, ap_sta_delayed_1x_auth_fail_cb,
hapd, sta);
#endif
}

View File

@ -31,6 +31,7 @@
#include "esp_wifi.h"
#include "esp_private/wifi.h"
#include "esp_wpas_glue.h"
#include "esp_wps_i.h"
#define STATE_MACHINE_DATA struct wpa_state_machine
#define STATE_MACHINE_DEBUG_PREFIX "WPA"
@ -2375,13 +2376,42 @@ bool wpa_ap_join(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, uint8_t
return true;
}
#ifdef CONFIG_WPS_REGISTRAR
static void ap_free_sta_timeout(void *ctx, void *data)
{
struct hostapd_data *hapd = (struct hostapd_data *) ctx;
u8 *addr = (u8 *) data;
struct sta_info *sta = ap_get_sta(hapd, addr);
if (sta) {
ap_free_sta(hapd, sta);
}
os_free(addr);
}
#endif
bool wpa_ap_remove(void* sta_info)
{
struct hostapd_data *hapd = hostapd_get_hapd_data();
if (!sta_info || !hapd) {
return false;
}
#ifdef CONFIG_WPS_REGISTRAR
wpa_printf(MSG_DEBUG, "wps_status=%d", wps_get_status());
if (wps_get_status() == WPS_STATUS_PENDING) {
struct sta_info *sta = (struct sta_info *)sta_info;
u8 *addr = os_malloc(ETH_ALEN);
if (!addr) {
return false;
}
os_memcpy(addr, sta->addr, ETH_ALEN);
eloop_register_timeout(0, 10000, ap_free_sta_timeout, hapd, addr);
} else
#endif
ap_free_sta(hapd, sta_info);
return true;

View File

@ -90,7 +90,6 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr,
data.dev_pw = dev_pw;
data.dev_pw_len = dev_pw_len;
wps_stop_registrar(hapd, &data);
wps_set_status(WPS_STATUS_DISABLE);
/* TODO add callback event for freeRTOS */
}
@ -111,68 +110,20 @@ static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
wps_registrar_update_ie(hapd->wps->registrar);
}
static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx)
{
struct wps_event_pwd_auth_fail *data = ctx;
if (!data->enrollee || hapd->conf->ap_pin == NULL || hapd->wps == NULL)
return 0;
/*
* Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
* for some time if this happens multiple times to slow down brute
* force attacks.
*/
hapd->ap_pin_failures++;
hapd->ap_pin_failures_consecutive++;
wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u "
"(%u consecutive)",
hapd->ap_pin_failures, hapd->ap_pin_failures_consecutive);
if (hapd->ap_pin_failures < 3)
return 0;
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
hapd->wps->ap_setup_locked = 1;
wps_registrar_update_ie(hapd->wps->registrar);
if (!hapd->conf->ap_setup_locked &&
hapd->ap_pin_failures_consecutive >= 10) {
/*
* In indefinite lockdown - disable automatic AP PIN
* reenablement.
*/
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
wpa_printf(MSG_DEBUG, "WPS: AP PIN disabled indefinitely");
} else if (!hapd->conf->ap_setup_locked) {
if (hapd->ap_pin_lockout_time == 0)
hapd->ap_pin_lockout_time = 60;
else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 &&
(hapd->ap_pin_failures % 3) == 0)
hapd->ap_pin_lockout_time *= 2;
wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN for %u seconds",
hapd->ap_pin_lockout_time);
eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL);
eloop_register_timeout(hapd->ap_pin_lockout_time, 0,
hostapd_wps_reenable_ap_pin, hapd,
NULL);
}
return 0;
}
static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
struct wps_event_pwd_auth_fail *data)
{
/* Update WPS Status - Authentication Failure */
wifi_event_ap_wps_rg_fail_reason_t evt = {0};
wpa_printf(MSG_DEBUG, "WPS: Authentication failure update");
hapd->wps_stats.status = WPS_FAILURE_STATUS;
os_memcpy(hapd->wps_stats.peer_addr, data->peer_macaddr, ETH_ALEN);
wps_pwd_auth_fail(hapd, data);
os_memcpy(evt.peer_macaddr, data->peer_macaddr, ETH_ALEN);
evt.reason = WPS_AP_FAIL_REASON_AUTH;
esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_FAILED, &evt,
sizeof(evt), OS_BLOCK);
}
@ -193,16 +144,12 @@ static int wps_ap_pin_success(struct hostapd_data *hapd, void *ctx)
}
static void hostapd_wps_ap_pin_success(struct hostapd_data *hapd)
{
wps_ap_pin_success(hapd, NULL);
}
static void hostapd_wps_event_pbc_overlap(struct hostapd_data *hapd)
{
/* Update WPS Status - PBC Overlap */
hapd->wps_stats.pbc_status = WPS_PBC_STATUS_OVERLAP;
esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_PBC_OVERLAP, NULL, 0, OS_BLOCK);
}
@ -210,16 +157,14 @@ static void hostapd_wps_event_pbc_timeout(struct hostapd_data *hapd)
{
/* Update WPS PBC Status:PBC Timeout */
hapd->wps_stats.pbc_status = WPS_PBC_STATUS_TIMEOUT;
esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_TIMEOUT, NULL, 0, OS_BLOCK);
}
static void hostapd_wps_event_pbc_active(struct hostapd_data *hapd)
static void hostapd_wps_event_pin_timeout(struct hostapd_data *hapd)
{
/* Update WPS PBC status - Active */
hapd->wps_stats.pbc_status = WPS_PBC_STATUS_ACTIVE;
esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_TIMEOUT, NULL, 0, OS_BLOCK);
}
static void hostapd_wps_event_pbc_disable(struct hostapd_data *hapd)
{
/* Update WPS PBC status - Active */
@ -230,31 +175,25 @@ static void hostapd_wps_event_pbc_disable(struct hostapd_data *hapd)
static void hostapd_wps_event_success(struct hostapd_data *hapd,
struct wps_event_success *success)
{
/* Update WPS status - Success */
hapd->wps_stats.pbc_status = WPS_PBC_STATUS_DISABLE;
hapd->wps_stats.status = WPS_SUCCESS_STATUS;
os_memcpy(hapd->wps_stats.peer_addr, success->peer_macaddr, ETH_ALEN);
wifi_event_ap_wps_rg_success_t evt;
os_memcpy(evt.peer_macaddr, success->peer_macaddr, ETH_ALEN);
esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_SUCCESS, &evt,
sizeof(evt), OS_BLOCK);
}
static void hostapd_wps_event_fail(struct hostapd_data *hapd,
struct wps_event_fail *fail)
{
/* Update WPS status - Failure */
hapd->wps_stats.status = WPS_FAILURE_STATUS;
os_memcpy(hapd->wps_stats.peer_addr, fail->peer_macaddr, ETH_ALEN);
if (fail->error_indication > 0 &&
fail->error_indication < NUM_WPS_EI_VALUES) {
wpa_msg(hapd->msg_ctx, MSG_INFO,
WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
fail->msg, fail->config_error, fail->error_indication,
wps_ei_str(fail->error_indication));
} else {
wpa_msg(hapd->msg_ctx, MSG_INFO,
WPS_EVENT_FAIL "msg=%d config_error=%d",
fail->msg, fail->config_error);
}
wifi_event_ap_wps_rg_fail_reason_t evt;
if (fail->config_error > WPS_CFG_NO_ERROR)
evt.reason = WPS_AP_FAIL_REASON_CONFIG;
else
evt.reason = WPS_AP_FAIL_REASON_NORMAL;
os_memcpy(evt.peer_macaddr, fail->peer_macaddr, ETH_ALEN);
esp_event_post(WIFI_EVENT, WIFI_EVENT_AP_WPS_RG_FAILED, &evt,
sizeof(evt), OS_BLOCK);
}
@ -264,9 +203,6 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
struct hostapd_data *hapd = ctx;
switch (event) {
case WPS_EV_M2D:
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_M2D);
break;
case WPS_EV_FAIL:
hostapd_wps_event_fail(hapd, &data->fail);
break;
@ -285,8 +221,9 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
hostapd_wps_event_pbc_timeout(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_TIMEOUT);
break;
case WPS_EV_SELECTED_REGISTRAR_TIMEOUT:
hostapd_wps_event_pin_timeout(hapd);
case WPS_EV_PBC_ACTIVE:
hostapd_wps_event_pbc_active(hapd);
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ACTIVE);
break;
case WPS_EV_PBC_DISABLE:
@ -306,7 +243,9 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event,
case WPS_EV_ER_SET_SELECTED_REGISTRAR:
break;
case WPS_EV_AP_PIN_SUCCESS:
hostapd_wps_ap_pin_success(hapd);
wps_ap_pin_success(hapd, NULL);
break;
default:
break;
}
if (hapd->wps_event_cb)
@ -392,7 +331,8 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
return;
}
wps_registrar_deinit(hapd->wps->registrar);
hostapd_free_wps(hapd->wps);
hapd->wps->registrar = NULL;
eap_server_unregister_methods();
hapd->wps = NULL;
hostapd_wps_clear_ies(hapd, 1);
}

View File

@ -101,7 +101,7 @@ static void eap_wsc_reset(struct eap_sm *sm, void *priv)
struct eap_wsc_data *data = priv;
wpabuf_free(data->in_buf);
wpabuf_free(data->out_buf);
wps_deinit(data->wps);
//wps_deinit(data->wps);
os_free(data);
}

View File

@ -521,7 +521,9 @@ enum wps_event {
/**
* WPS_EV_AP_PIN_SUCCESS - External Registrar used correct AP PIN
*/
WPS_EV_AP_PIN_SUCCESS
WPS_EV_AP_PIN_SUCCESS,
WPS_EV_SELECTED_REGISTRAR_TIMEOUT,
};
/**

View File

@ -330,6 +330,14 @@ void wps_pbc_overlap_event(struct wps_context *wps)
}
void wps_selected_registrar_timeout_event(struct wps_context *wps)
{
if (wps->event_cb == NULL)
return;
wps->event_cb(wps->cb_ctx, WPS_EV_SELECTED_REGISTRAR_TIMEOUT, NULL);
}
void wps_pbc_timeout_event(struct wps_context *wps)
{
if (wps->event_cb == NULL)

View File

@ -145,6 +145,7 @@ void wps_success_event(struct wps_context *wps, const u8 *mac_addr);
void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part,
const u8 *mac_addr);
void wps_pbc_overlap_event(struct wps_context *wps);
void wps_selected_registrar_timeout_event(struct wps_context *wps);
void wps_pbc_timeout_event(struct wps_context *wps);
void wps_pbc_active_event(struct wps_context *wps);
void wps_pbc_disable_event(struct wps_context *wps);

View File

@ -852,7 +852,6 @@ static void wps_registrar_remove_pin(struct wps_registrar *reg,
addr = pin->enrollee_addr;
wps_registrar_remove_authorized_mac(reg, addr);
wps_remove_pin(pin);
wps_registrar_selected_registrar_changed(reg, 0);
}
@ -3485,6 +3484,7 @@ static void wps_registrar_set_selected_timeout(void *eloop_ctx,
reg->pbc = 0;
wps_registrar_expire_pins(reg);
wps_registrar_selected_registrar_changed(reg, 0);
wps_selected_registrar_timeout_event(reg->wps);
}

View File

@ -0,0 +1,6 @@
# The following 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(wps_softap_registrar)

View File

@ -0,0 +1,53 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
# Wi-Fi WPS Registrar Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example shows how to use WPS registrar sotAP mode in ESP. The WPS protocol simplifies the process of connecting to a Wi-Fi softAP from a station.
## How to use example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
### Hardware Required
* A development board with ESP32/ESP32-S2/ESP32-C3/ESP32-S3 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
* A USB cable for Power supply and programming
### Configure the project
Open the project configuration menu (`idf.py menuconfig`).
In the `Example Configuration` menu:
* Use `WPS mode` to select the type.
* Select `PBC`, `PIN` or `disable`.
In `PBC` mode, the ESP will wait for the WPS initialization (usually by pressing WPS button on the Wi-Fi station).
In `PIN` mode, the ESP will enter the WPS mode and you'll see a pin code on the terminal(If not given through user config). Enter this pin code in your station and then the ESP will connect to it.
(See your station's manual and configuration for WPS compatibility.)
### Build and Flash
Build the project and flash it to the board, then run the monitor tool to view the serial output:
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for all the steps to configure and use the ESP-IDF to build projects.
* [ESP-IDF Getting Started Guide on ESP32](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html)
* [ESP-IDF Getting Started Guide on ESP32-S2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html)
* [ESP-IDF Getting Started Guide on ESP32-C3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html)
* [ESP-IDF Getting Started Guide on ESP32-S3](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/index.html)
* [ESP-IDF Getting Started Guide on ESP32-C2](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/get-started/index.html)
## Troubleshooting
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.

View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "wps.c"
INCLUDE_DIRS ".")

View File

@ -0,0 +1,50 @@
menu "Example Configuration"
config EXAMPLE_WIFI_SSID
string "WiFi SSID"
default "myssid"
help
SSID (network name) for the example to connect to.
config EXAMPLE_WIFI_PASSWORD
string "WiFi Password"
default "mypassword"
help
WiFi password (WPA or WPA2) for the example to use.
config EXAMPLE_WIFI_CHANNEL
int "WiFi Channel"
range 1 13
default 1
help
WiFi channel (network channel) for the example to use.
config EXAMPLE_MAX_STA_CONN
int "Maximal STA connections"
default 4
help
Max number of the STA connects to AP.
choice EXAMPLE_WPS_TYPE
prompt "WPS mode"
default EXAMPLE_WPS_TYPE_PBC
help
WPS type for the esp32 to use.
config EXAMPLE_WPS_TYPE_PBC
bool "PBC"
config EXAMPLE_WPS_TYPE_PIN
bool "PIN"
config EXAMPLE_WPS_TYPE_DISABLE
bool "disable"
endchoice
if EXAMPLE_WPS_TYPE_PIN
config EXAMPLE_WPS_PIN_VALUE
int "WPS PIN"
default 0
help
WPS PIN to be used for the connection, incase its not give, AP will derive a new one.
endif
endmenu

View File

@ -0,0 +1,179 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* WPS Registrar example in softAP mode
This example 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 "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_mac.h"
#include "esp_log.h"
#include "esp_wps.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include <string.h>
/*set wps mode via project configuration */
#if CONFIG_EXAMPLE_WPS_TYPE_PBC
#define WPS_MODE WPS_TYPE_PBC
#elif CONFIG_EXAMPLE_WPS_TYPE_PIN
#if CONFIG_EXAMPLE_WPS_PIN_VALUE
#define EXAMPLE_WPS_PIN_VALUE CONFIG_EXAMPLE_WPS_PIN_VALUE
#endif
#define WPS_MODE WPS_TYPE_PIN
#else
#define WPS_MODE WPS_TYPE_DISABLE
#endif /*CONFIG_EXAMPLE_WPS_TYPE_PBC*/
#ifndef PIN2STR
#define PIN2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7]
#define PINSTR "%c%c%c%c%c%c%c%c"
#endif
#define EXAMPLE_ESP_WIFI_SSID CONFIG_EXAMPLE_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS CONFIG_EXAMPLE_WIFI_PASSWORD
#define EXAMPLE_ESP_WIFI_CHANNEL CONFIG_EXAMPLE_WIFI_CHANNEL
#define EXAMPLE_MAX_STA_CONN CONFIG_EXAMPLE_MAX_STA_CONN
static const char *TAG = "example_wps_registrar";
static esp_wps_config_t config = WPS_CONFIG_INIT_DEFAULT(WPS_MODE);
static unsigned char pin[9];
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_AP_START:
ESP_LOGI(TAG, "WIFI_EVENT_AP_START");
break;
case WIFI_EVENT_AP_STADISCONNECTED:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_STADISCONNECTED");
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
}
break;
case WIFI_EVENT_AP_STACONNECTED:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_STACONNECTED");
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
}
break;
case WIFI_EVENT_AP_WPS_RG_SUCCESS:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_SUCCESS");
wifi_event_ap_wps_rg_success_t *evt = (wifi_event_ap_wps_rg_success_t *)event_data;
ESP_LOGI(TAG, "station "MACSTR" WPS successful",
MAC2STR(evt->peer_macaddr));
}
break;
case WIFI_EVENT_AP_WPS_RG_FAILED:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_FAILED");
wifi_event_ap_wps_rg_fail_reason_t *evt = (wifi_event_ap_wps_rg_fail_reason_t *)event_data;
ESP_LOGI(TAG, "station "MACSTR" WPS failed, reason=%d",
MAC2STR(evt->peer_macaddr), evt->reason);
ESP_ERROR_CHECK(esp_wifi_ap_wps_disable());
ESP_ERROR_CHECK(esp_wifi_ap_wps_enable(&config));
ESP_ERROR_CHECK(esp_wifi_ap_wps_start(pin));
}
break;
case WIFI_EVENT_AP_WPS_RG_TIMEOUT:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_TIMEOUT");
ESP_ERROR_CHECK(esp_wifi_ap_wps_disable());
ESP_ERROR_CHECK(esp_wifi_ap_wps_enable(&config));
ESP_ERROR_CHECK(esp_wifi_ap_wps_start(pin));
}
break;
case WIFI_EVENT_AP_WPS_RG_PIN:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_WPS_RG_PIN");
/* display the PIN code */
wifi_event_ap_wps_rg_pin_t* event = (wifi_event_ap_wps_rg_pin_t *) event_data;
ESP_LOGI(TAG, "WPS_PIN = " PINSTR, PIN2STR(event->pin_code));
}
break;
default:
break;
}
}
/*init wifi as sta and start wps*/
static void start_wps_registrar(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_ap();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
wifi_config_t wifi_config = {
.ap = {
.ssid = EXAMPLE_ESP_WIFI_SSID,
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
.channel = EXAMPLE_ESP_WIFI_CHANNEL,
.password = EXAMPLE_ESP_WIFI_PASS,
.max_connection = EXAMPLE_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA2_PSK,
.pmf_cfg = {
.required = false,
},
},
};
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI(TAG, "start wps...");
ESP_ERROR_CHECK(esp_wifi_ap_wps_enable(&config));
#if EXAMPLE_WPS_PIN_VALUE
ESP_LOGI(TAG, "Staring WPS registrar with user specified pin %s", pin);
snprintf((char *)pin, 9, "%08d", EXAMPLE_WPS_PIN_VALUE);
ESP_ERROR_CHECK(esp_wifi_ap_wps_start(pin));
#else
if (config.wps_type == WPS_TYPE_PBC) {
ESP_LOGI(TAG, "Staring WPS registrar in PBC mode");
} else {
ESP_LOGI(TAG, "Staring WPS registrar with random generated pin");
}
ESP_ERROR_CHECK(esp_wifi_ap_wps_start(NULL));
#endif
}
void app_main(void)
{
/* Initialize NVS — it is used to store PHY calibration data */
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 );
start_wps_registrar();
}

View File

@ -0,0 +1,2 @@
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y
CONFIG_WPA_WPS_SOFTAP_REGISTRAR=y