diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 45dabd2ab0..a483ff34b3 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1950,6 +1950,10 @@ msgstr "" msgid "Stereo right must be on PWM channel B" msgstr "" +#: ports/raspberrypi/common-hal/wifi/Radio.c +msgid "Stopping AP is not supported." +msgstr "" + #: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "Supply at least one UART pin" msgstr "" @@ -2340,6 +2344,18 @@ msgstr "" msgid "Wi-Fi: " msgstr "" +#: ports/raspberrypi/common-hal/wifi/Radio.c +msgid "Wifi is in access point mode." +msgstr "" + +#: ports/raspberrypi/common-hal/wifi/Radio.c +msgid "Wifi is in station mode." +msgstr "" + +#: ports/raspberrypi/common-hal/wifi/Radio.c +msgid "Wifi is not enabled" +msgstr "" + #: main.c msgid "Woken up by alarm.\n" msgstr "" diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index acecd68c58..d72d59bcf6 100644 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -36,7 +36,7 @@ INC_CYW43 := \ -isystem sdk/src/rp2_common/pico_cyw43_arch/include/ \ -isystem sdk/src/rp2_common/pico_lwip/include/ \ -CFLAGS_CYW43 := -DCYW43_LWIP=1 -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_USE_SPI -DIGNORE_GPIO25 -DIGNORE_GPIO23 -DIGNORE_GPIO24 -DCYW43_LOGIC_DEBUG=0 +CFLAGS_CYW43 := -DCYW43_LWIP=1 -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_USE_SPI -DIGNORE_GPIO25 -DIGNORE_GPIO23 -DIGNORE_GPIO24 -DCYW43_LOGIC_DEBUG=0 -DCYW43_NETUTILS=1 SRC_SDK_CYW43 := \ src/common/pico_sync/sem.c \ src/rp2_common/cyw43_driver/cyw43_bus_pio_spi.c \ @@ -47,6 +47,8 @@ SRC_SDK_CYW43 := \ SRC_LWIP := \ shared/netutils/netutils.c \ + shared/netutils/trace.c \ + shared/netutils/dhcpserver.c \ $(wildcard lib/lwip/src/apps/mdns/*.c) \ $(wildcard lib/lwip/src/core/*.c) \ $(wildcard lib/lwip/src/core/ipv4/*.c) \ diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 7fe03024f2..313363dd32 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -133,7 +133,7 @@ mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self, u mp_raise_RuntimeError(translate("Already scanning for wifi networks")); } if (!common_hal_wifi_radio_get_enabled(self)) { - mp_raise_RuntimeError(translate("wifi is not enabled")); + mp_raise_RuntimeError(translate("Wifi is not enabled")); } wifi_scannednetworks_obj_t *scan = m_new_obj(wifi_scannednetworks_obj_t); scan->base.type = &wifi_scannednetworks_type; @@ -154,35 +154,78 @@ void common_hal_wifi_radio_start_station(wifi_radio_obj_t *self) { } void common_hal_wifi_radio_stop_station(wifi_radio_obj_t *self) { + cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); // This is wrong, but without this call the state of ITF_STA is still // reported as CYW43_LINK_JOIN (by wifi_link_status) and CYW43_LINK_UP - // (by tcpip_link_status). Until AP support is added, we can ignore the - // problem. + // (by tcpip_link_status). However since ap disconnection isn't working + // either, this is not an issue. cyw43_wifi_leave(&cyw43_state, CYW43_ITF_AP); + bindings_cyw43_wifi_enforce_pm(); } void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, uint32_t authmodes, uint8_t max_connections) { - mp_raise_NotImplementedError(NULL); + if (!common_hal_wifi_radio_get_enabled(self)) { + mp_raise_RuntimeError(translate("Wifi is not enabled")); + } + + if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) != CYW43_LINK_DOWN) { + mp_raise_RuntimeError(translate("Wifi is in station mode.")); + } + + common_hal_wifi_radio_stop_ap(self); + + // Channel can only be changed after inital powerup and config of ap. + // Defaults to 1 if not set or invalid (i.e. 13) + cyw43_wifi_ap_set_channel(&cyw43_state, (const uint32_t)channel); + + cyw43_arch_enable_ap_mode((const char *)ssid, (const char *)password, CYW43_AUTH_WPA2_AES_PSK); + + // TODO: Implement authmode check like in espressif bindings_cyw43_wifi_enforce_pm(); } void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) { - mp_raise_NotImplementedError(NULL); + if (!common_hal_wifi_radio_get_enabled(self)) { + mp_raise_RuntimeError(translate("wifi is not enabled")); + } + + if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_AP) != CYW43_LINK_DOWN) { + mp_raise_NotImplementedError(translate("Stopping AP is not supported.")); + } + + /* + * AP cannot be disconnected. cyw43_wifi_leave is broken. + * This code snippet should work, but doesn't. + * + * cyw43_wifi_leave(&cyw43_state, CYW43_ITF_AP); + * cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); + * + * bindings_cyw43_wifi_enforce_pm(); + */ } wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, mp_float_t timeout, uint8_t *bssid, size_t bssid_len) { if (!common_hal_wifi_radio_get_enabled(self)) { - mp_raise_RuntimeError(translate("wifi is not enabled")); + mp_raise_RuntimeError(translate("Wifi is not enabled")); } + if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_AP) != CYW43_LINK_DOWN) { + mp_raise_RuntimeError(translate("Wifi is in access point mode.")); + } + + size_t timeout_ms = timeout <= 0 ? 8000 : (size_t)MICROPY_FLOAT_C_FUN(ceil)(timeout * 1000); uint64_t start = port_get_raw_ticks(NULL); uint64_t deadline = start + timeout_ms; + // disconnect + common_hal_wifi_radio_stop_station(self); + // connect cyw43_arch_wifi_connect_async((const char *)ssid, (const char *)password, CYW43_AUTH_WPA2_AES_PSK); + // TODO: Implement authmode check like in espressif while (port_get_raw_ticks(NULL) < deadline) { RUN_BACKGROUND_TASKS; diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c index 89e451a3b0..f6ddab2c12 100644 --- a/ports/raspberrypi/supervisor/port.c +++ b/ports/raspberrypi/supervisor/port.c @@ -143,7 +143,9 @@ safe_mode_t port_init(void) { never_reset_pin_number(24); never_reset_pin_number(25); never_reset_pin_number(29); - if (cyw43_arch_init()) { + // Change this as a placeholder as to how to init with country code. + // Default country code is CYW43_COUNTRY_WORLDWIDE) + if (cyw43_arch_init_with_country(PICO_CYW43_ARCH_DEFAULT_COUNTRY_CODE)) { serial_write("WiFi init failed\n"); } else { cyw_ever_init = true; diff --git a/shared/netutils/dhcpserver.c b/shared/netutils/dhcpserver.c index 9db42b3fd9..d396a2ba56 100644 --- a/shared/netutils/dhcpserver.c +++ b/shared/netutils/dhcpserver.c @@ -33,7 +33,7 @@ #include "py/mperrno.h" #include "py/mphal.h" -#if MICROPY_PY_LWIP +#if LWIP_UDP #include "shared/netutils/dhcpserver.h" #include "lwip/udp.h" @@ -265,9 +265,9 @@ static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, d->lease[yi].expiry = (mp_hal_ticks_ms() + DEFAULT_LEASE_TIME_S * 1000) >> 16; dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi; opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPACK); - printf("DHCPS: client connected: MAC=%02x:%02x:%02x:%02x:%02x:%02x IP=%u.%u.%u.%u\n", + LWIP_DEBUGF(DHCP_DEBUG, ("DHCPS: client connected: MAC=%02x:%02x:%02x:%02x:%02x:%02x IP=%u.%u.%u.%u\n", dhcp_msg.chaddr[0], dhcp_msg.chaddr[1], dhcp_msg.chaddr[2], dhcp_msg.chaddr[3], dhcp_msg.chaddr[4], dhcp_msg.chaddr[5], - dhcp_msg.yiaddr[0], dhcp_msg.yiaddr[1], dhcp_msg.yiaddr[2], dhcp_msg.yiaddr[3]); + dhcp_msg.yiaddr[0], dhcp_msg.yiaddr[1], dhcp_msg.yiaddr[2], dhcp_msg.yiaddr[3])); break; } diff --git a/shared/netutils/netutils.h b/shared/netutils/netutils.h index b23a78e5b8..3bb9212800 100644 --- a/shared/netutils/netutils.h +++ b/shared/netutils/netutils.h @@ -33,6 +33,8 @@ #define NETUTILS_TRACE_PAYLOAD (0x0002) #define NETUTILS_TRACE_NEWLINE (0x0004) +#include "py/runtime.h" + typedef enum _netutils_endian_t { NETUTILS_LITTLE, NETUTILS_BIG,