21#include "lwip/ip_addr.h"
22#include "lwip/netif.h"
30#include "lwip/ip6_addr.h"
35 WiFi.begin(ssid, password);
41 return WiFi.isConnected();
51 esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
58 WiFi.mode(WIFI_AP_STA);
59 return WiFi.softAP(ssid, password);
65#if defined(PC_ETH_W5500) && PC_ETH_W5500 && ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
78 return ETH.linkUp() && (uint32_t)ETH.localIP() != 0;
97#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
98 return WiFi.enableIPv6(
true);
100 return WiFi.enableIpV6();
106 if (!out || !netif_default)
110 for (int8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
112 if (!ip6_addr_isvalid(netif_ip6_addr_state(netif_default, i)))
116 const ip6_addr_t *a6 = netif_ip6_addr(netif_default, i);
117 if (!ip6_addr_isglobal(a6))
122 memcpy(out->
bytes, a6->addr, 16);
151 return netif_default ? ip4_addr_get_u32(ip_2_ip4(&netif_default->ip_addr)) : 0;
161 uint32_t sta = WiFi.isConnected() ? (uint32_t)WiFi.localIP() : 0;
168 return (WiFi.getMode() & WIFI_AP) ? (uint32_t)WiFi.softAPIP() : 0;
173 return WiFi.isConnected() ? (int8_t)WiFi.RSSI() : 0;
182 WiFi.macAddress(out);
190 if (!out || !netif_default || netif_default->hwaddr_len < 6)
194 memcpy(out, netif_default->hwaddr, 6);
200 if (!out || cap == 0)
204 wifi_ap_record_t info;
205 if (esp_wifi_sta_get_ap_info(&info) != ESP_OK)
210 size_t n = strnlen((
const char *)info.ssid,
sizeof(info.ssid));
215 memcpy(out, info.ssid, n);
222 return (uint8_t)WiFi.channel();
237 return WIFI_PS_MIN_MODEM;
241 return WIFI_PS_MAX_MODEM;
251PhyMonitorCtx s_phy_monitor = {
nullptr};
254void phy_monitor_trampoline(
void *buf, wifi_promiscuous_pkt_type_t)
256 if (!s_phy_monitor.sink || !buf)
260 const wifi_promiscuous_pkt_t *pkt = (
const wifi_promiscuous_pkt_t *)buf;
261 uint16_t len = (uint16_t)pkt->rx_ctrl.sig_len;
266 s_phy_monitor.sink(pkt->payload, (uint16_t)(len - 4), (int8_t)pkt->rx_ctrl.rssi, (uint8_t)pkt->rx_ctrl.channel);
272 return esp_wifi_set_ps(to_esp_ps(mode)) == ESP_OK;
277 wifi_ps_type_t m = WIFI_PS_NONE;
278 if (esp_wifi_get_ps(&m) != ESP_OK)
282 if (m == WIFI_PS_MIN_MODEM)
286 if (m == WIFI_PS_MAX_MODEM)
296 return esp_wifi_set_max_tx_power((int8_t)(dbm * 4)) == ESP_OK;
305 s_phy_monitor.sink = cb;
306 esp_wifi_set_promiscuous(
true);
307 esp_wifi_set_promiscuous_rx_cb(&phy_monitor_trampoline);
308 esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
314 esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
319 esp_wifi_set_promiscuous(
false);
320 s_phy_monitor.sink =
nullptr;
@ PC_IP_V6
IPv6 (bytes[0..15])
bool init_wifi_physical(const char *, const char *)
Connect to a WiFi access point.
bool pc_ipv6_ready(void)
True once the interface has a global IPv6 address (see net_global_ipv6()).
pc_iface pc_net_classify_ip(uint32_t egress_ip, uint32_t sta_ip, uint32_t ap_ip)
Classify an egress IPv4 against the WiFi station / softAP IPs (pure helper, exposed for unit testing)...
uint32_t pc_net_egress_ip(void)
IPv4 (network byte order) of the current egress interface, or 0 if none.
pc_phy_ps pc_phy_ps_get(void)
Read the active power-save mode (PC_PHY_PS_NONE when unsupported).
bool eth_ready(void)
True if the Ethernet link is up and an IP is assigned.
bool pc_phy_monitor_begin(uint8_t, pc_phy_frame_fn)
Enter monitor mode on channel, delivering frames to cb.
bool pc_net_egress_mac(uint8_t *)
bool init_wifi_ap_physical(const char *, const char *)
Bring up a softAP, enabling AP+STA coexistence so a station link can run alongside it.
bool net_global_ipv6(pc_ip *)
The interface's global (routable) IPv6 address, if it has one.
bool pc_phy_tx_power_set(int8_t)
Cap transmit power.
size_t pc_net_ssid(char *out, size_t cap)
Copy the associated SSID (null-terminated) into out.
bool wifi_ready()
True if the WiFi station link is up (associated + an IP is assigned).
int8_t pc_net_rssi(void)
Station link RSSI in dBm, or 0 if not associated (and on host builds).
void pc_phy_monitor_end(void)
Leave monitor mode.
uint32_t pc_net_ap_ip(void)
softAP IPv4 (network byte order), or 0 if the softAP is not up (and on host builds).
bool init_ipv6_physical(void)
Enable IPv6 (dual-stack) on the Wi-Fi interface (PC_ENABLE_IPV6).
bool init_eth_physical(void)
Bring up a wired Ethernet link (PC_ENABLE_ETHERNET).
pc_iface pc_net_egress(void)
Which interface currently carries outbound traffic.
void pc_phy_monitor_set_channel(uint8_t)
Retune monitor mode to channel.
uint8_t pc_net_channel(void)
Station WiFi channel (1..14), or 0 if not associated (and on host builds).
bool pc_phy_ps_set(pc_phy_ps)
Apply a power-save mode.
bool init_wifi_radio_physical(uint8_t)
Bring the WiFi radio up in station mode WITHOUT associating to an AP.
bool pc_net_mac(uint8_t *)
Layer 1 (Physical) - link bring-up and live egress-interface reporting.
void(* pc_phy_frame_fn)(const uint8_t *frame, uint16_t len, int8_t rssi, uint8_t channel)
One received frame, delivered in neutral terms.
pc_phy_ps
Radio power-save mode, in the library's own vocabulary.
@ PC_PHY_PS_MIN_MODEM
Wake on every DTIM beacon.
@ PC_PHY_PS_NONE
Radio always on: lowest latency, highest average draw.
@ PC_PHY_PS_MAX_MODEM
Wake on a longer listen interval: lowest draw, highest latency.
#define PC_ETH_W5500_SCK
HSPI clock (S3-DevKitC default)
#define PC_ETH_W5500_CS
chip select
#define PC_ETH_W5500_SPI_MHZ
W5500 SPI clock (MHz); raise for throughput on clean wiring.
#define PC_ETH_W5500_MISO
HSPI MISO (S3-DevKitC default)
#define PC_ETH_W5500_MOSI
HSPI MOSI (S3-DevKitC default)
#define PC_ETH_W5500_INT
interrupt
#define PC_ETH_W5500_RST
reset
pc_iface
Network interface a connection arrived on (for per-route filtering).
@ PC_IFACE_ANY
Unknown / no filter (matches any interface).
A v4 or v6 address in network (big-endian) byte order.
pc_ip_family family
address family tag
uint8_t bytes[16]
network order; v4 uses the first 4