Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions libraries/WiFi/examples/WiFiWebClient/WiFiWebClient.ino
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ void setup() {
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 3 seconds for connection:
delay(3000);
// wait 6 seconds for connection:
delay(6000);
}
Serial.println("Connected to wifi");
printWifiStatus();
Expand Down
267 changes: 190 additions & 77 deletions libraries/WiFi/src/WiFi.cpp
Original file line number Diff line number Diff line change
@@ -1,97 +1,210 @@
#include "WiFi.h"

WiFiClass WiFi;
// Static Wi-Fi state instance
struct WiFiState {
struct net_if *sta_iface = nullptr;
struct net_if *ap_iface = nullptr;
struct wifi_connect_req_params ap_config;
struct wifi_connect_req_params sta_config;
struct wifi_iface_status sta_state = {0};
struct wifi_scan_result scanResults[MAX_SCAN_RESULTS];
uint8_t resultCount = 0;
struct net_mgmt_event_callback wifiCb;
bool soughtNetworkFound = false;
bool scanSequenceFinished = false;
};

String WiFiClass::firmwareVersion() {
#if defined(ARDUINO_PORTENTA_C33)
return "v1.5.0";
#else
return "v0.0.0";
#endif
}
WiFiClass::WiFiClass() {}
WiFiClass::~WiFiClass() {}

// Static instance of Wi-Fi state
struct WiFiState WiFiClass::wifiState;

int WiFiClass::begin(const char *ssid, const char *passphrase,
wl_enc_type security, bool blocking) {
wifi_security_type wifi_security = convert_enc_type_to_security_type(security);

wifiState.sta_iface = net_if_get_wifi_sta();
netif = wifiState.sta_iface;
wifiState.sta_config.ssid = (const uint8_t *)ssid;
wifiState.sta_config.ssid_length = strlen(ssid);
wifiState.sta_config.psk = (const uint8_t *)passphrase;
wifiState.sta_config.psk_length = strlen(passphrase);

// Set Wi-Fi security type if specified
if (wifi_security != WIFI_SECURITY_TYPE_NONE) {
wifiState.sta_config.security = wifi_security;
} else {
wifiState.sta_config.security = WIFI_SECURITY_TYPE_PSK;
}

wifiState.sta_config.channel = WIFI_CHANNEL_ANY;
wifiState.sta_config.band = WIFI_FREQ_BAND_2_4_GHZ;
wifiState.sta_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;

int WiFiClass::begin(const char *ssid, const char *passphrase, wl_enc_type security,
bool blocking) {
sta_iface = net_if_get_wifi_sta();
netif = sta_iface;
sta_config.ssid = (const uint8_t *)ssid;
sta_config.ssid_length = strlen(ssid);
sta_config.psk = (const uint8_t *)passphrase;
sta_config.psk_length = strlen(passphrase);
// TODO: change these fields with scan() results
sta_config.security = WIFI_SECURITY_TYPE_PSK;
sta_config.channel = WIFI_CHANNEL_ANY;
sta_config.band = WIFI_FREQ_BAND_2_4_GHZ;
sta_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
int ret = net_mgmt(NET_REQUEST_WIFI_CONNECT, sta_iface, &sta_config,
sizeof(struct wifi_connect_req_params));
if (ret) {
return false;
}
NetworkInterface::begin(false, NET_EVENT_WIFI_MASK);
if (blocking) {
net_mgmt_event_wait_on_iface(sta_iface, NET_EVENT_WIFI_CONNECT_RESULT, NULL, NULL, NULL,
K_FOREVER);
}
return status();
// Register the Wi-Fi event callback
net_mgmt_init_event_callback(&wifiState.wifiCb, scanEventDispatcher,
NET_EVENT_WIFI_SCAN_RESULT | NET_EVENT_WIFI_SCAN_DONE);
net_mgmt_add_event_callback(&wifiState.wifiCb);

// Trigger a network scan
(void)scanNetworks(); // Blocking call

// Attempt to connect to the network if configuration is valid
if (wifiState.sta_config.ssid && wifiState.sta_config.psk) {
int ret = net_mgmt(NET_REQUEST_WIFI_CONNECT, wifiState.sta_iface, &wifiState.sta_config,
sizeof(struct wifi_connect_req_params));
if (ret) {
return false;
}

NetworkInterface::begin(false, NET_EVENT_WIFI_MASK);
if (blocking) {
net_mgmt_event_wait_on_iface(wifiState.sta_iface, NET_EVENT_WIFI_CONNECT_RESULT, NULL, NULL, NULL, K_FOREVER);
}
}

return status();
}

bool WiFiClass::beginAP(char *ssid, char *passphrase, int channel, bool blocking) {
if (ap_iface != NULL) {
return false;
}
ap_iface = net_if_get_wifi_sap();
netif = ap_iface;
ap_config.ssid = (const uint8_t *)ssid;
ap_config.ssid_length = strlen(ssid);
ap_config.psk = (const uint8_t *)passphrase;
ap_config.psk_length = strlen(passphrase);
ap_config.security = WIFI_SECURITY_TYPE_PSK;
ap_config.channel = channel;
ap_config.band = WIFI_FREQ_BAND_2_4_GHZ;
ap_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;
int ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, ap_iface, &ap_config,
sizeof(struct wifi_connect_req_params));
if (ret) {
return false;
}
enable_dhcpv4_server(ap_iface);
if (blocking) {
net_mgmt_event_wait_on_iface(ap_iface, NET_EVENT_WIFI_AP_ENABLE_RESULT, NULL, NULL, NULL,
K_FOREVER);
}
return true;
if (wifiState.ap_iface != nullptr) {
return false; // AP already initialized
}

wifiState.ap_iface = net_if_get_wifi_sap();
netif = wifiState.ap_iface;
wifiState.ap_config.ssid = (const uint8_t *)ssid;
wifiState.ap_config.ssid_length = strlen(ssid);
wifiState.ap_config.psk = (const uint8_t *)passphrase;
wifiState.ap_config.psk_length = strlen(passphrase);
wifiState.ap_config.security = WIFI_SECURITY_TYPE_PSK;
wifiState.ap_config.channel = channel;
wifiState.ap_config.band = WIFI_FREQ_BAND_2_4_GHZ;
wifiState.ap_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;

int ret = net_mgmt(NET_REQUEST_WIFI_AP_ENABLE, wifiState.ap_iface, &wifiState.ap_config,
sizeof(struct wifi_connect_req_params));
if (ret) {
return false;
}

enable_dhcpv4_server(wifiState.ap_iface);

if (blocking) {
net_mgmt_event_wait_on_iface(wifiState.ap_iface, NET_EVENT_WIFI_AP_ENABLE_RESULT, NULL, NULL, NULL, K_FOREVER);
}

return true;
}

int WiFiClass::status() {
sta_iface = net_if_get_wifi_sta();
netif = sta_iface;
if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, netif, &sta_state,
sizeof(struct wifi_iface_status))) {
return WL_NO_SHIELD;
}
if (sta_state.state >= WIFI_STATE_ASSOCIATED) {
return WL_CONNECTED;
} else {
return WL_DISCONNECTED;
}
return WL_NO_SHIELD;
wifiState.sta_iface = net_if_get_wifi_sta();
netif = wifiState.sta_iface;
if (net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, netif, &wifiState.sta_state,
sizeof(struct wifi_iface_status))) {
return WL_NO_SHIELD;
}
if (wifiState.sta_state.state >= WIFI_STATE_ASSOCIATED) {
return WL_CONNECTED;
} else {
return WL_DISCONNECTED;
}
}

int8_t WiFiClass::scanNetworks() {
// TODO: borrow code from mbed core for scan results handling
wifiState.resultCount = 0u;
wifiState.soughtNetworkFound = false;
wifiState.scanSequenceFinished = false;

// Trigger a new scan
net_mgmt(NET_REQUEST_WIFI_SCAN, wifiState.sta_iface, nullptr, 0u);

// Wait for the scan to finish (this is a blocking call)
while (!wifiState.scanSequenceFinished)
;

return wifiState.resultCount;
}

void WiFiClass::scanEventDispatcher(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
struct net_if *iface) {
// Use the global Wi-Fi state instance to handle the event
if (wifiState.sta_iface != nullptr) {
WiFi.handleScanEvent(cb, mgmt_event, iface);
}
}

void WiFiClass::handleScanEvent(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
struct net_if *iface) {
if (mgmt_event == NET_EVENT_WIFI_SCAN_RESULT) {
const struct wifi_scan_result *entry = reinterpret_cast<const struct wifi_scan_result *>(cb->info);
if (wifiState.resultCount < MAX_SCAN_RESULTS) {
memcpy(&wifiState.scanResults[wifiState.resultCount], entry, sizeof(struct wifi_scan_result));
wifiState.resultCount++;

// Compare SSID of the scanned network with the desired network SSID
if (!memcmp(entry->ssid, wifiState.sta_config.ssid, entry->ssid_length)) {
wifiState.sta_config.security = entry->security;
wifiState.sta_config.channel = entry->channel;
wifiState.sta_config.band = entry->band;
wifiState.sta_config.bandwidth = WIFI_FREQ_BANDWIDTH_20MHZ;

wifiState.soughtNetworkFound = true;
}
}
}

if (mgmt_event == NET_EVENT_WIFI_SCAN_DONE) {
wifiState.scanSequenceFinished = true;

if (wifiState.resultCount == 0) {
printk("No networks found.\n");
}
}
}

char *WiFiClass::SSID() {
if (status() == WL_CONNECTED) {
return (char *)sta_state.ssid;
}
return nullptr;
if (status() == WL_CONNECTED) {
return (char *)wifiState.sta_state.ssid;
}
return nullptr;
}

int32_t WiFiClass::RSSI() {
if (status() == WL_CONNECTED) {
return sta_state.rssi;
}
return 0;
if (status() == WL_CONNECTED) {
return wifiState.sta_state.rssi;
}
return 0;
}

String WiFiClass::firmwareVersion() {
#if defined(ARDUINO_PORTENTA_C33)
return "v1.5.0";
#else
return "v0.0.0";
#endif
}

wifi_security_type WiFiClass::convert_enc_type_to_security_type(wl_enc_type enc_type) {
switch (enc_type) {
case ENC_TYPE_WEP:
return WIFI_SECURITY_TYPE_WEP;
case ENC_TYPE_WPA:
return WIFI_SECURITY_TYPE_WPA_PSK; // Could also map to WPA_AUTO_PERSONAL
case ENC_TYPE_WPA2:
return WIFI_SECURITY_TYPE_PSK; // Could also map to WPA_AUTO_PERSONAL
case ENC_TYPE_WPA3:
return WIFI_SECURITY_TYPE_SAE; // Could also map to SAE_AUTO
case ENC_TYPE_NONE:
return WIFI_SECURITY_TYPE_NONE;
case ENC_TYPE_UNKNOWN:
case ENC_TYPE_AUTO:
return WIFI_SECURITY_TYPE_UNKNOWN;
default:
return WIFI_SECURITY_TYPE_UNKNOWN; // Default case for any undefined or unexpected values
}
}

// Global Wi-Fi object, uses the static wifiState struct
WiFiClass WiFi;
59 changes: 31 additions & 28 deletions libraries/WiFi/src/WiFi.h
Original file line number Diff line number Diff line change
@@ -1,44 +1,47 @@
#include "SocketHelpers.h"
#ifndef WIFI_H
#define WIFI_H

#include "SocketHelpers.h"
#include "utility/wl_definitions.h"
#include <zephyr/net/wifi_mgmt.h>

// Max number of scan results to store
#define MAX_SCAN_RESULTS 20

// Wi-Fi event mask for the various events
#define NET_EVENT_WIFI_MASK \
(NET_EVENT_WIFI_CONNECT_RESULT | NET_EVENT_WIFI_DISCONNECT_RESULT | \
NET_EVENT_WIFI_AP_ENABLE_RESULT | NET_EVENT_WIFI_AP_DISABLE_RESULT | \
NET_EVENT_WIFI_AP_STA_CONNECTED | NET_EVENT_WIFI_AP_STA_DISCONNECTED | \
NET_EVENT_WIFI_SCAN_RESULT)
(NET_EVENT_WIFI_CONNECT_RESULT | NET_EVENT_WIFI_DISCONNECT_RESULT | \
NET_EVENT_WIFI_AP_ENABLE_RESULT | NET_EVENT_WIFI_AP_DISABLE_RESULT | \
NET_EVENT_WIFI_AP_STA_CONNECTED | NET_EVENT_WIFI_AP_STA_DISCONNECTED | \
NET_EVENT_WIFI_SCAN_RESULT)

class WiFiClass : public NetworkInterface {
public:
WiFiClass() {
}

~WiFiClass() {
}
WiFiClass();
~WiFiClass();

int begin(const char *ssid, const char *passphrase, wl_enc_type security = ENC_TYPE_UNKNOWN,
bool blocking = true);
bool beginAP(char *ssid, char *passphrase, int channel = WIFI_CHANNEL_ANY,
bool blocking = false);
int begin(const char *ssid, const char *passphrase,
wl_enc_type security = ENC_TYPE_WPA, bool blocking = true);

int status();
bool beginAP(char *ssid, char *passphrase, int channel = WIFI_CHANNEL_ANY,
bool blocking = false);

int8_t scanNetworks();
int status();
int8_t scanNetworks();
char *SSID();
int32_t RSSI();
String firmwareVersion();
wifi_security_type convert_enc_type_to_security_type(wl_enc_type enc_type);

char *SSID();
int32_t RSSI();

String firmwareVersion();
static struct WiFiState wifiState; // Static instance to hold Wi-Fi state

private:
struct net_if *sta_iface = nullptr;
struct net_if *ap_iface = nullptr;

struct wifi_connect_req_params ap_config;
struct wifi_connect_req_params sta_config;

struct wifi_iface_status sta_state = {0};
static void scanEventDispatcher(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
struct net_if *iface);
void handleScanEvent(struct net_mgmt_event_callback *cb, uint64_t mgmt_event,
struct net_if *iface);
};

extern WiFiClass WiFi;
extern WiFiClass WiFi; // Global Wi-Fi object

#endif // WIFI_H
1 change: 1 addition & 0 deletions loader/llext_exports.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ FORCE_EXPORT_SYM(tls_credential_add);
FORCE_EXPORT_SYM(net_if_get_wifi_sta);
FORCE_EXPORT_SYM(net_if_get_wifi_sap);
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_CONNECT);
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_SCAN);
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_IFACE_STATUS);
FORCE_EXPORT_SYM(net_mgmt_NET_REQUEST_WIFI_AP_ENABLE);
#endif
Expand Down