diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index e0e3149866..8f55044e81 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -447,6 +447,10 @@ msgstr "" msgid "ADC2 is being used by WiFi" msgstr "" +#: ports/raspberrypi/common-hal/wifi/Radio.c +msgid "AP could not be started" +msgstr "" + #: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" @@ -1959,10 +1963,6 @@ 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 "" - #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" msgstr "" @@ -2337,14 +2337,6 @@ 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 "" diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 7ccb41c0d6..1508b764a2 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -157,11 +157,6 @@ 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). However since ap disconnection isn't working - // either, this is not an issue. - cyw43_wifi_leave(&cyw43_state, CYW43_ITF_AP); const size_t timeout_ms = 500; uint64_t start = port_get_raw_ticks(NULL); uint64_t deadline = start + timeout_ms; @@ -179,9 +174,15 @@ void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_ 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.")); - } + /* TODO: If the AP is stopped once it cannot be restarted. + * This means that if if the user does: + * + * wifi.radio.start_ap(...) + * wifi.radio.stop_ap() + * wifi.radio.start_ap(...) + * + * The second start_ap will fail. + */ common_hal_wifi_radio_stop_ap(self); @@ -189,10 +190,29 @@ void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_ // 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); + if (password_len) { + cyw43_arch_enable_ap_mode((const char *)ssid, (const char *)password, CYW43_AUTH_WPA2_AES_PSK); + } else { + cyw43_arch_enable_ap_mode((const char *)ssid, NULL, CYW43_AUTH_OPEN); + } // TODO: Implement authmode check like in espressif bindings_cyw43_wifi_enforce_pm(); + + const size_t timeout_ms = 500; + uint64_t start = port_get_raw_ticks(NULL); + uint64_t deadline = start + timeout_ms; + while (port_get_raw_ticks(NULL) < deadline && (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_AP) != CYW43_LINK_UP)) { + RUN_BACKGROUND_TASKS; + if (mp_hal_is_interrupted()) { + break; + } + } + if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_AP) != CYW43_LINK_UP) { + common_hal_wifi_radio_stop_ap(self); + // This is needed since it leaves a broken AP up. + mp_raise_RuntimeError(translate("AP could not be started")); + } } bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self) { @@ -204,19 +224,19 @@ void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *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.")); + cyw43_arch_disable_ap_mode(); + + const size_t timeout_ms = 500; + uint64_t start = port_get_raw_ticks(NULL); + uint64_t deadline = start + timeout_ms; + while (port_get_raw_ticks(NULL) < deadline && (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_AP) != CYW43_LINK_DOWN)) { + RUN_BACKGROUND_TASKS; + if (mp_hal_is_interrupted()) { + break; + } } - /* - * 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(); - */ + bindings_cyw43_wifi_enforce_pm(); } static bool connection_unchanged(wifi_radio_obj_t *self, const uint8_t *ssid, size_t ssid_len) { @@ -237,10 +257,6 @@ wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t 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.")); - } - if (ssid_len > 32) { return WIFI_RADIO_ERROR_CONNECTION_FAIL; } diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index 495e7fd13b..798c7c6d2e 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -332,8 +332,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_station_obj, wifi_radio_stop_station); //| //| **Limitations:** On Espressif, ``authmode`` with a non-empty password must include //| `wifi.AuthMode.PSK`, and one or both of `wifi.AuthMode.WPA` and `wifi.AuthMode.WPA2`. -//| On Pi Pico W, ``authmode`` is ignored; it is always ``(wifi.AuthMode.WPA2, wifi.AuthMode.PSK)` -//| with a non-empty password, or ``(wifi.AuthMode.OPEN,)`` when no password is given. +//| On Pi Pico W, ``authmode`` is ignored; it is always ``(wifi.AuthMode.WPA2, wifi.AuthMode.PSK)`` +//| with a non-empty password, or ``(wifi.AuthMode.OPEN)``, when no password is given. +//| On Pi Pico W, the AP can be started and stopped only once per reboot. //| //| The length of ``password`` must be 8-63 characters if it is ASCII, //| or exactly 64 hexadecimal characters if it is the hex form of the 256-bit key.