[lightning-ln882h] Add support for Lightning LN882H family (#312)

* fix mbedtls bad pointer in function call (prototype mismatch)

* fix issue with weak families functions implemented in static library, it will never be linked. fixed by redefining prototypes inside families

* [ln882x] add support for lightning ln882x & ln882h families

* add i2c (wire) support

* add analog (adc) support

* add watchdog support

* [ln882x] changed default uart 0/1 pins; added board wl2s

* [ln882x] fix IRQ & ADC pins

* [ln882x] boards cosmetic

* [ln882x] wifi sta use otp mac addr by default; re-enabled wifi powersave mode

* [ln882x] clang-format clean code

* [ln882x] clang-format clean code

* Update families.json

* Apply suggestions from code review

* [ln882x] reformat json board files

* [ln882x] os_queue cleanup

* [ln882x] removed Beken auto-download command

* [ln882x] removed personal script file

* [ln882x] removed unusefull pi section in debugging.md

* [ln882x] removed Arduino.h and changed private I2C definition

* [ln882x] updated README.md

* [ln882x] changed pin naming scheme to PA/PB

* [ln882x] clean code

* [ln882x] clean code

* [ln882x] add ota image verification

* Update push-dev.yml

* [ln882x] fix boards ADC missing inputs]

* [ln882x] removed reg_xxx fixup files and use include guards instead

* [ln882x] cleanup code

* [ln882x] cleanup code

* [ln882x] fix lt_init weak functions linking

* [ln882x] revert lt_api.h modification, fixed with previous commit

* [ln882x] setup UF2 firmware for flasher with partitions

* [ln882x] update README.md

* [ln882x] include ln_wifi.h and ln_serial.h to avoid including bad headers on case insensitive systems

* [ln882x] Replace RingBuffer by SerialRingBuffer

* [ln882x] clang-format

* [ln882x] update README.md

* Apply suggestions from code review

* Reformat board JSON files

* Add mkdocs link redirect

* Update ltchiptool to v4.12.0

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
This commit is contained in:
lamauny
2025-03-25 17:26:53 +01:00
committed by GitHub
parent 6083cca72e
commit 69e7e2debe
73 changed files with 4856 additions and 28 deletions

View File

@@ -0,0 +1,59 @@
/* Copyright (c) Etienne Le Cousin 2024-02-18. */
#include "WiFiPrivate.h"
WiFiClass::WiFiClass() {
data = (WiFiData *)calloc(1, sizeof(WiFiData));
DATA->scanSem = xSemaphoreCreateBinary();
}
WiFiClass::~WiFiClass() {
vSemaphoreDelete(DATA->scanSem);
free(data);
data = NULL;
}
WiFiAuthMode securityTypeToAuthMode(uint8_t type) {
switch (type) {
case LN_WIFI_AUTH_OPEN:
return WIFI_AUTH_OPEN;
case LN_WIFI_AUTH_WEP:
return WIFI_AUTH_WEP;
case LN_WIFI_AUTH_WPA_PSK:
return WIFI_AUTH_WPA_PSK;
case LN_WIFI_AUTH_WPA2_PSK:
return WIFI_AUTH_WPA2_PSK;
case LN_WIFI_AUTH_WPA_WPA2_PSK:
return WIFI_AUTH_WPA_WPA2_PSK;
case LN_WIFI_AUTH_WPA2_ENTERPRISE:
return WIFI_AUTH_WPA2_ENTERPRISE;
case LN_WIFI_AUTH_WPA3_SAE:
return WIFI_AUTH_WPA3_PSK;
case LN_WIFI_AUTH_WPA2_PSK_WPA3_SAE:
return WIFI_AUTH_WPA2_WPA3_PSK;
}
return WIFI_AUTH_INVALID;
}
uint8_t authModeToSecurityType(WiFiAuthMode auth) {
switch (auth) {
case WIFI_AUTH_OPEN:
return LN_WIFI_AUTH_OPEN;
case WIFI_AUTH_WEP:
return LN_WIFI_AUTH_WEP;
case WIFI_AUTH_WPA_PSK:
return LN_WIFI_AUTH_WPA_PSK;
case WIFI_AUTH_WPA2_PSK:
return LN_WIFI_AUTH_WPA2_PSK;
case WIFI_AUTH_WPA_WPA2_PSK:
return LN_WIFI_AUTH_WPA_WPA2_PSK;
case WIFI_AUTH_WPA2_ENTERPRISE:
return LN_WIFI_AUTH_WPA2_ENTERPRISE;
case WIFI_AUTH_WPA3_PSK:
return LN_WIFI_AUTH_WPA3_SAE;
case WIFI_AUTH_WPA2_WPA3_PSK:
return LN_WIFI_AUTH_WPA2_PSK_WPA3_SAE;
}
return WIFI_AUTH_INVALID;
}

View File

@@ -0,0 +1,134 @@
/* Copyright (c) Etienne Le Cousin 2024-02-18. */
#include "WiFiPrivate.h"
static uint8_t psk_value[40] = {0x0};
static uint8_t mac_addr[6] = {0x00, 0x50, 0xC2, 0x7F, 0xBC, 0x01};
bool WiFiClass::softAP(const char *ssid, const char *passphrase, int channel, bool ssidHidden, int maxClients) {
if (!enableAP(true))
return false;
if (!validate(ssid, passphrase))
return false;
LT_HEAP_I();
WiFiNetworkInfo &info = DATA->ap;
if (info.ssid != ssid)
// free network info, if not called from restoreAPConfig()
resetNetworkInfo(info);
if (info.ssid != ssid)
info.ssid = strdup(ssid);
if (info.password != passphrase)
info.password = strdup(passphrase);
info.ssidHidden = ssidHidden;
info.bssid = softAPmacAddress(mac_addr);
info.channel = channel;
info.auth = passphrase ? LN_WIFI_AUTH_WPA2_PSK : LN_WIFI_AUTH_OPEN;
LT_IM(WIFI, "Creating SoftAP %s", ssid);
// clang-format off
wifi_softap_cfg_t ap_cfg = {
.ssid = info.ssid,
.pwd = info.password,
.bssid = info.bssid,
.ext_cfg = {
.channel = (uint8_t)info.channel,
.authmode = (ln_wifi_auth_mode_t)info.auth,
.ssid_hidden = info.ssidHidden,
.beacon_interval = 100,
.psk_value = NULL,
}
};
// clang-format on
if ((strlen(ap_cfg.pwd) != 0) && (ap_cfg.ext_cfg.authmode != LN_WIFI_AUTH_OPEN) &&
(ap_cfg.ext_cfg.authmode != LN_WIFI_AUTH_WEP)) {
memset(psk_value, 0, sizeof(psk_value));
if (0 == ln_psk_calc(ap_cfg.ssid, ap_cfg.pwd, psk_value, sizeof(psk_value))) {
ap_cfg.ext_cfg.psk_value = psk_value;
hexdump(psk_value, sizeof(psk_value));
}
}
// wifi start
__wrap_ln_printf_disable();
int ret = wifi_softap_start(&ap_cfg);
__wrap_ln_printf_enable();
if (ret != 0) {
LT_EM(WIFI, "SoftAP failed; ret=%d", ret);
return false;
}
return true;
}
bool WiFiClass::softAPConfig(IPAddress localIP, IPAddress gateway, IPAddress subnet) {
if (!enableAP(true))
return false;
WiFiNetworkInfo &info = DATA->ap;
// dhcp server config
server_config_t server_config;
server_config.server.addr = localIP;
server_config.port = 67;
server_config.lease = 2880;
server_config.renew = 2880;
server_config.ip_start.addr = IPAddress(localIP[0], localIP[1], localIP[2], 100);
server_config.ip_end.addr = IPAddress(localIP[0], localIP[1], localIP[2], 150);
server_config.client_max = 3;
dhcpd_curr_config_set(&server_config);
// net device config
tcpip_ip_info_t ip_info;
ip_info.ip.addr = info.localIP = localIP;
ip_info.netmask.addr = info.subnet = subnet;
ip_info.gw.addr = info.gateway = gateway;
netdev_set_ip_info(NETIF_IDX_AP, &ip_info);
netdev_set_active(NETIF_IDX_AP);
return true;
}
bool WiFiClass::softAPdisconnect(bool wifiOff) {
return enableAP(false);
}
uint8_t WiFiClass::softAPgetStationNum() {
return 0;
}
IPAddress WiFiClass::softAPIP() {
return netif_ip_addr4(netdev_get_netif(NETIF_IDX_AP))->addr;
}
IPAddress WiFiClass::softAPSubnetMask() {
return netif_ip_netmask4(netdev_get_netif(NETIF_IDX_AP))->addr;
}
const char *WiFiClass::softAPgetHostname() {
return netif_get_hostname(netdev_get_netif(NETIF_IDX_AP));
}
bool WiFiClass::softAPsetHostname(const char *hostname) {
netif_set_hostname(netdev_get_netif(NETIF_IDX_AP), (char *)hostname);
return true;
}
uint8_t *WiFiClass::softAPmacAddress(uint8_t *mac) {
memcpy(mac, netdev_get_netif(NETIF_IDX_AP)->hwaddr, MAC_ADDRESS_LEN);
return mac;
}
String WiFiClass::softAPmacAddress(void) {
uint8_t mac[MAC_ADDRESS_LEN];
softAPmacAddress(mac);
return macToString(mac);
}
const String WiFiClass::softAPSSID(void) {
WiFiNetworkInfo &info = DATA->ap;
return (char *)info.ssid;
}

View File

@@ -0,0 +1,122 @@
/* Copyright (c) Etienne Le Cousin 2024-03-10. */
#include "WiFiPrivate.h"
void wifiEventSendArduino(EventId event) {
EventInfo eventInfo;
memset(&eventInfo, 0, sizeof(EventInfo));
if (!pWiFi)
return; // failsafe
pWiFi->postEvent(event, eventInfo);
}
static void wifiEventStaStartup(void *arg) {
wifiEventSendArduino(ARDUINO_EVENT_WIFI_STA_START);
}
static void wifiEventStaConnected(void *arg) {
EventInfo eventInfo;
memset(&eventInfo, 0, sizeof(EventInfo));
if (!pWiFi)
return; // failsafe
String ssid = pWiFi->SSID();
eventInfo.wifi_sta_connected.ssid_len = ssid.length();
eventInfo.wifi_sta_connected.channel = pWiFi->channel();
eventInfo.wifi_sta_connected.authmode = pWiFi->getEncryption();
memcpy(eventInfo.wifi_sta_connected.ssid, ssid.c_str(), eventInfo.wifi_sta_connected.ssid_len + 1);
memcpy(eventInfo.wifi_sta_connected.bssid, pWiFi->BSSID(), 6);
pWiFi->postEvent(ARDUINO_EVENT_WIFI_STA_CONNECTED, eventInfo);
}
static void wifiEventStaDisconnected(void *arg) {
EventInfo eventInfo;
memset(&eventInfo, 0, sizeof(EventInfo));
if (!pWiFi)
return; // failsafe
eventInfo.wifi_sta_disconnected.ssid_len = 0;
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_ASSOC_LEAVE;
pWiFi->postEvent(ARDUINO_EVENT_WIFI_STA_DISCONNECTED, eventInfo);
}
static void wifiEventStaConnectFailed(void *arg) {
wifi_sta_connect_failed_reason_t reason = *(wifi_sta_connect_failed_reason_t *)arg;
EventInfo eventInfo;
memset(&eventInfo, 0, sizeof(EventInfo));
if (!pWiFi)
return; // failsafe
eventInfo.wifi_sta_disconnected.ssid_len = 0;
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_UNSPECIFIED;
switch (reason) {
case WIFI_STA_CONN_WRONG_PWD:
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_AUTH_FAIL;
break;
case WIFI_STA_CONN_TARGET_AP_NOT_FOUND:
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_NO_AP_FOUND;
break;
case WIFI_STA_CONN_TIMEOUT:
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_BEACON_TIMEOUT;
break;
case WIFI_STA_CONN_REFUSED:
eventInfo.wifi_sta_disconnected.reason = WIFI_REASON_CONNECTION_FAIL;
break;
}
pWiFi->postEvent(ARDUINO_EVENT_WIFI_STA_DISCONNECTED, eventInfo);
}
static void wifiEventSoftAPStartup(void *arg) {
netdev_set_state(NETIF_IDX_AP, NETDEV_UP);
wifiEventSendArduino(ARDUINO_EVENT_WIFI_AP_START);
}
static void wifiEventSoftAPAssociated(void *arg) {
const uint8_t *mac_addr = (const uint8_t *)arg;
EventInfo eventInfo;
memset(&eventInfo, 0, sizeof(EventInfo));
if (!pWiFi)
return; // failsafe
memcpy(eventInfo.wifi_ap_staconnected.mac, mac_addr, 6);
pWiFi->postEvent(ARDUINO_EVENT_WIFI_AP_STACONNECTED, eventInfo);
}
static void wifiEventSoftAPDisassociated(void *arg) {
const uint8_t *mac_addr = (const uint8_t *)arg;
EventInfo eventInfo;
memset(&eventInfo, 0, sizeof(EventInfo));
if (!pWiFi)
return; // failsafe
memcpy(eventInfo.wifi_ap_staconnected.mac, mac_addr, 6);
pWiFi->postEvent(ARDUINO_EVENT_WIFI_AP_STADISCONNECTED, eventInfo);
}
static void wifiEventIpReceived(struct netif *nif) {
EventInfo eventInfo;
memset(&eventInfo, 0, sizeof(EventInfo));
if (!pWiFi || !nif)
return; // failsafe
eventInfo.got_ip.if_index = 0;
eventInfo.got_ip.ip_changed = true;
eventInfo.got_ip.ip_info.ip.addr = nif->ip_addr.addr;
eventInfo.got_ip.ip_info.gw.addr = nif->gw.addr;
eventInfo.got_ip.ip_info.netmask.addr = nif->netmask.addr;
pWiFi->postEvent(ARDUINO_EVENT_WIFI_STA_GOT_IP, eventInfo);
}
void registerWifiHandlers() {
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_STARTUP, &wifiEventStaStartup);
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_CONNECTED, &wifiEventStaConnected);
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_DISCONNECTED, &wifiEventStaDisconnected);
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_CONNECT_FAILED, &wifiEventStaConnectFailed);
netdev_get_ip_cb_set(&wifiEventIpReceived);
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_SOFTAP_STARTUP, &wifiEventSoftAPStartup);
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_SOFTAP_ASSOCIATED, &wifiEventSoftAPAssociated);
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_SOFTAP_DISASSOCIATED, &wifiEventSoftAPDisassociated);
}

View File

@@ -0,0 +1,144 @@
/* Copyright (c) Etienne Le Cousin 2024-03-10. */
#include "WiFiPrivate.h"
static uint8_t psk_value[40] = {0x0};
bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
__wrap_ln_printf_disable();
if (!DATA->initialized) {
// rf preprocess,img cal
wifi_rf_calibration();
// Init wifi stack.
wifi_init();
// Init lwip stack.
LT_IM(WIFI, "Initializing LwIP");
lwip_tcpip_init();
// Init wifi manager
wifi_manager_init();
// Register event handlers
registerWifiHandlers();
DATA->mode = WIFI_MODE_NULL;
DATA->initialized = true;
}
LT_HEAP_I();
WiFiMode currentMode = DATA->mode;
WiFiNetworkInfo &staInfo = DATA->sta;
WiFiNetworkInfo &apInfo = DATA->ap;
if (mode == WIFI_MODE_APSTA) {
LT_EM(WIFI, "AP+STA mode not supported!");
goto error;
}
if (sta == WLMODE_ENABLE) {
LT_DM(WIFI, "Enabling STA");
// 1. sta mac get
uint8_t mac_addr[6];
setMacAddress(macAddress(mac_addr));
// 2. net device(lwip)
netdev_set_active(NETIF_IDX_STA);
// 3. wifi start
wifi_sta_start(mac_addr, WIFI_NO_POWERSAVE);
wifiEventSendArduino(ARDUINO_EVENT_WIFI_STA_START);
} else if (sta == WLMODE_DISABLE) {
LT_DM(WIFI, "Disabling STA");
wifi_sta_disconnect();
netdev_set_state(NETIF_IDX_STA, NETDEV_DOWN);
wifiEventSendArduino(ARDUINO_EVENT_WIFI_STA_STOP);
}
LT_HEAP_I();
if (ap == WLMODE_ENABLE) {
LT_DM(WIFI, "Enabling AP");
// 1. ap mac get
uint8_t mac_addr[6];
sysparam_softap_mac_get(mac_addr);
netdev_set_mac_addr(NETIF_IDX_AP, mac_addr);
// 2. net device(lwip)
netdev_set_active(NETIF_IDX_AP);
wifiEventSendArduino(ARDUINO_EVENT_WIFI_AP_START);
} else if (ap == WLMODE_DISABLE) {
LT_DM(WIFI, "Disabling AP");
wifi_softap_deauth_all();
netdev_set_state(NETIF_IDX_AP, NETDEV_DOWN);
wifiEventSendArduino(ARDUINO_EVENT_WIFI_AP_STOP);
}
DATA->mode = mode;
LT_HEAP_I();
__wrap_ln_printf_enable();
return true;
error:
__wrap_ln_printf_enable();
return false;
}
WiFiMode WiFiClass::getMode() {
if (!DATA->initialized)
return WIFI_MODE_NULL;
// return fake value because the chip doesn't report the mode before it is started
return DATA->mode;
/*switch (wifi_current_mode_get()) {
case LN_WIFI_MODE_STATION:
return WIFI_MODE_STA;
case LN_WIFI_MODE_AP:
return WIFI_MODE_AP;
case LN_WIFI_MODE_AP_STATION:
return WIFI_MODE_APSTA;
}
return WIFI_MODE_NULL;*/
}
WiFiStatus WiFiClass::status() {
wifi_sta_status_t status = WIFI_STA_STATUS_STARTUP;
wifi_get_sta_status(&status);
if (status == WIFI_STA_STATUS_CONNECTED) {
return WL_CONNECTED;
} else {
return WL_DISCONNECTED;
}
}
bool WiFiClass::setSleep(bool enable) {
LT_DM(WIFI, "WiFi sleep mode %u", enable);
if (enable) {
if (wifi_sta_set_powersave(WIFI_MAX_POWERSAVE))
return false;
} else {
if (wifi_sta_set_powersave(WIFI_NO_POWERSAVE))
return false;
}
DATA->sleep = enable;
return true;
}
bool WiFiClass::getSleep() {
return DATA->sleep;
}
IPAddress WiFiClass::hostByName(const char *hostname) {
ip_addr_t ip;
int ret = netconn_gethostbyname(hostname, &ip);
if (ret == ERR_OK) {
return ip.addr;
}
return IPAddress();
}

View File

@@ -0,0 +1,47 @@
/* Copyright (c) Etienne Le Cousin 2024-02-10. */
#pragma once
#include <WiFi.h>
#include <sdk_private.h>
extern "C" {
// copy defines from PIO builder (for IDE to understand)
#define LWIP_TIMEVAL_PRIVATE 0
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_SO_RCVBUF 1
#include <lwip/api.h>
#include <lwip/dns.h>
#include <lwip/ip_addr.h>
#include <lwip/netif.h>
#include <lwip/netifapi.h>
#include <netif/ethernetif.h>
#include <FreeRTOS.h>
#include <semphr.h>
} // extern "C"
// WiFi.cpp
extern WiFiAuthMode securityTypeToAuthMode(uint8_t type);
uint8_t authModeToSecurityType(WiFiAuthMode auth);
// WiFiEvents.cpp
extern void wifiEventSendArduino(EventId event);
extern void registerWifiHandlers();
typedef struct {
bool initialized;
bool sleep;
WiFiMode mode;
SemaphoreHandle_t scanSem;
WiFiNetworkInfo sta;
WiFiNetworkInfo ap;
} WiFiData;
#define DATA ((WiFiData *)data)
#define pDATA ((WiFiData *)pWiFi->data)
#define cDATA ((WiFiData *)cls->data)
#define IP_FMT "%u.%u.%u.%u"

View File

@@ -0,0 +1,213 @@
/* Copyright (c) Etienne Le Cousin 2024-03-10. */
#include "WiFiPrivate.h"
WiFiStatus WiFiClass::begin(
const char *ssid,
const char *passphrase,
int32_t channel,
const uint8_t *bssid,
bool connect
) {
if (!enableSTA(true))
return WL_CONNECT_FAILED;
if (!validate(ssid, passphrase))
return WL_CONNECT_FAILED;
LT_HEAP_I();
WiFiNetworkInfo &info = DATA->sta;
if (info.ssid != ssid)
// free network info, if not called from restoreSTAConfig()
resetNetworkInfo(info);
if (info.ssid != ssid)
info.ssid = strdup(ssid);
info.channel = channel;
info.auth = LN_WIFI_AUTH_OPEN;
if (passphrase) {
if (info.password != passphrase)
info.password = strdup(passphrase);
info.auth = LN_WIFI_AUTH_WPA_WPA2_PSK;
}
if (reconnect(bssid))
return WL_CONNECTED;
else
return WL_CONNECT_FAILED;
}
bool WiFiClass::config(IPAddress localIP, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) {
if (!enableSTA(true))
return false;
WiFiNetworkInfo &info = DATA->sta;
struct netif *ifs = netdev_get_netif(NETIF_IDX_STA);
ip4_addr_t d1, d2;
d1.addr = info.dns1 = dns1;
d2.addr = info.dns2 = dns2;
if (d1.addr)
dns_setserver(0, &d1);
if (d2.addr)
dns_setserver(0, &d2);
if (!localIP[0]) {
info.localIP = 0;
netifapi_dhcp_start(ifs);
return true;
}
ip4_addr_t ipaddr, netmask, gw;
ipaddr.addr = info.localIP = localIP;
netmask.addr = info.subnet = subnet;
gw.addr = info.gateway = gateway;
netif_set_addr(ifs, &ipaddr, &netmask, &gw);
netifapi_dhcp_release_and_stop(ifs);
return true;
}
bool WiFiClass::reconnect(const uint8_t *bssid) {
WiFiNetworkInfo &info = DATA->sta;
LT_IM(WIFI, "Connecting to %s (bssid=%p)", info.ssid, bssid);
if (bssid != info.bssid) {
if (!info.bssid)
info.bssid = (uint8_t *)malloc(BSSID_LEN);
memcpy(info.bssid, bssid, BSSID_LEN);
}
uint8_t psk_value[40] = {0x0};
wifi_sta_connect_t connect = {
.ssid = info.ssid,
.pwd = info.password,
.bssid = NULL, // info.bssid,
.psk_value = NULL,
};
wifi_scan_cfg_t scan_cfg = {
.channel = (uint8_t)info.channel,
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
.scan_time = 5,
};
if (0 == ln_psk_calc(connect.ssid, connect.pwd, psk_value, sizeof(psk_value)))
connect.psk_value = psk_value;
LT_DM(WIFI, "Starting WiFi...");
__wrap_ln_printf_disable();
int ret = wifi_sta_connect(&connect, &scan_cfg);
// int ret = wifi_sta_connect_v2(&connect, &scan_cfg, 10);
__wrap_ln_printf_enable();
LT_DM(WIFI, "Start OK (%d)", ret);
return true;
}
bool WiFiClass::disconnect(bool wifiOff) {
free(DATA->sta.ssid);
DATA->sta.ssid = NULL;
int ret = wifi_sta_disconnect();
if (wifiOff)
enableSTA(false);
return ret == 0;
}
bool WiFiClass::setAutoReconnect(bool autoReconnect) {
return false;
}
bool WiFiClass::getAutoReconnect() {
return false;
}
IPAddress WiFiClass::localIP() {
tcpip_ip_info_t ip_info;
netdev_get_ip_info(NETIF_IDX_STA, &ip_info);
return IPAddress(ip_info.ip.addr);
}
IPAddress WiFiClass::subnetMask() {
tcpip_ip_info_t ip_info;
netdev_get_ip_info(NETIF_IDX_STA, &ip_info);
return IPAddress(ip_info.netmask.addr);
}
IPAddress WiFiClass::gatewayIP() {
tcpip_ip_info_t ip_info;
netdev_get_ip_info(NETIF_IDX_STA, &ip_info);
return IPAddress(ip_info.gw.addr);
}
IPAddress WiFiClass::dnsIP(uint8_t dns_no) {
return dns_getserver(dns_no)->addr;
}
IPAddress WiFiClass::broadcastIP() {
return calculateBroadcast(localIP(), subnetMask());
}
const char *WiFiClass::getHostname() {
struct netif *ifs = netdev_get_netif(NETIF_IDX_STA);
return netif_get_hostname(ifs);
}
bool WiFiClass::setHostname(const char *hostname) {
struct netif *ifs = netdev_get_netif(NETIF_IDX_STA);
netif_set_hostname(ifs, (char *)hostname);
return true;
}
uint8_t *WiFiClass::macAddress(uint8_t *mac) {
if (SYSPARAM_ERR_NONE == sysparam_sta_mac_get(mac))
return mac;
else
LT_WM(WIFI, "sysparam sta mac get failed!");
lt_get_device_mac(mac);
return mac;
}
bool WiFiClass::setMacAddress(const uint8_t *mac) {
sysparam_sta_mac_update(mac);
return netdev_set_mac_addr(NETIF_IDX_STA, (uint8_t *)mac) == 0;
}
const String WiFiClass::SSID() {
const char *ssid = NULL;
const uint8_t *bssid = NULL;
wifi_get_sta_conn_info(&ssid, &bssid);
return ssid;
}
const String WiFiClass::psk() {
if (!isConnected() || !DATA->sta.password)
return "";
return DATA->sta.password;
}
uint8_t *WiFiClass::BSSID() {
const char *ssid = NULL;
const uint8_t *bssid = NULL;
wifi_get_sta_conn_info(&ssid, &bssid);
return (uint8_t *)bssid;
}
int32_t WiFiClass::channel() {
uint8_t channel = 0;
wifi_get_channel(&channel);
return (int32_t)channel;
}
int8_t WiFiClass::RSSI() {
int8_t rssi = 0;
wifi_sta_get_rssi(&rssi);
return rssi;
}
WiFiAuthMode WiFiClass::getEncryption() {
ln_wifi_auth_mode_t mode;
wifi_sta_get_connected_ap_security(&mode);
return securityTypeToAuthMode(mode);
}

View File

@@ -0,0 +1,114 @@
/* Copyright (c) Etienne Le Cousin 2024-03-13. */
#include "WiFiPrivate.h"
static void scanHandler(void *arg) {
WiFiClass *cls = (WiFiClass *)pWiFi;
WiFiScanData *scan = cls->scan;
LT_HEAP_I();
ln_list_t *list;
uint8_t n = 0, node_count = 0;
ap_info_node_t *pnode;
wifi_manager_ap_list_update_enable(LN_FALSE);
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_SCAN_COMPLETE, NULL);
// 1.get ap info list.
if (wifi_manager_get_ap_list(&list, &node_count)) {
LT_EM(WIFI, "Failed to get scan result");
goto end;
}
LT_IM(WIFI, "Found %d APs", node_count);
cls->scanAlloc(node_count);
if (!scan->ap) {
LT_WM(WIFI, "scan->ap alloc failed");
goto end;
}
// 2.get all ap info in the list.
LN_LIST_FOR_EACH_ENTRY(pnode, ap_info_node_t, list, list) {
uint8_t *mac = (uint8_t *)pnode->info.bssid;
ap_info_t *ap_info = &pnode->info;
scan->ap[n].ssid = strdup(ap_info->ssid);
scan->ap[n].auth = securityTypeToAuthMode(ap_info->authmode);
scan->ap[n].rssi = ap_info->rssi;
scan->ap[n].channel = ap_info->channel;
memcpy(scan->ap[n].bssid.addr, mac, 6);
n++;
}
end:
scan->timeout = 0;
if (scan->running) {
// running == false means it was discarded (timeout)
scan->running = false;
xSemaphoreGive(cDATA->scanSem);
// Send event scan finished
EventInfo eventInfo;
memset(&eventInfo, 0, sizeof(EventInfo));
eventInfo.wifi_scan_done.status = 0;
eventInfo.wifi_scan_done.number = scan->count;
pWiFi->postEvent(ARDUINO_EVENT_WIFI_SCAN_DONE, eventInfo);
}
// wifi_manager_ap_list_update_enable(LN_TRUE);
// wifi_sta_disconnect();
LT_HEAP_I();
return;
}
int16_t WiFiClass::scanNetworks(bool async, bool showHidden, bool passive, uint32_t maxMsPerChannel, uint8_t channel) {
if (scan && scan->running) {
if (scan->timeout && millis() > scan->timeout) {
LT_WM(WIFI, "Scan timeout, discarding");
scan->running = false;
} else {
return WIFI_SCAN_RUNNING;
}
}
enableSTA(true);
scanDelete();
scanInit();
LT_IM(WIFI, "Starting WiFi scan");
__wrap_ln_printf_disable();
wifi_manager_reg_event_callback(WIFI_MGR_EVENT_STA_SCAN_COMPLETE, &scanHandler);
wifi_manager_ap_list_update_enable(LN_TRUE);
wifi_manager_cleanup_scan_results();
wifi_scan_cfg_t scan_cfg = {
.channel = 0,
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
.scan_time = 5,
};
wifi_sta_scan(&scan_cfg);
LT_HEAP_I();
scan->running = true;
scan->timeout = millis() + maxMsPerChannel * 20 + 1000;
int16_t ret = WIFI_SCAN_RUNNING;
if (!async) {
LT_IM(WIFI, "Waiting for results");
xSemaphoreTake(DATA->scanSem, 1); // reset the semaphore quickly
xSemaphoreTake(DATA->scanSem, pdMS_TO_TICKS(maxMsPerChannel * 20));
if (scan->running) {
scanDelete();
ret = WIFI_SCAN_FAILED;
goto exit;
}
ret = scan->count;
goto exit;
}
exit:
__wrap_ln_printf_enable();
return ret;
}