Skip to content

Commit 5e594f8

Browse files
committed
src/cyw43_ctrl.c: Add bounded retry for failed auth.
A Pico W connecting to a wireless network may fail to authenticate with a transient error and - in MicroPython at least - this failure surfaces to the user and requires a manual retry. Handle auth failures internally with a bounded retry. Turns the almost 100% failure to connect on first try (with my specific wireless network) to an almost 100% success rate. Signed-off-by: Phil Howard <github@gadgetoid.com>
1 parent 055d642 commit 5e594f8

2 files changed

Lines changed: 31 additions & 4 deletions

File tree

src/cyw43.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ typedef struct _cyw43_t {
122122
bool pend_rejoin;
123123
bool pend_rejoin_wpa;
124124

125+
// Number of automatic rejoins remaining after a transient join failure.
126+
uint8_t wifi_join_retries;
127+
125128
// AP settings
126129
uint32_t ap_auth;
127130
uint8_t ap_channel;

src/cyw43_ctrl.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@
6464
#define WIFI_JOIN_STATE_KEYED (0x0800)
6565
#define WIFI_JOIN_STATE_ALL (0x0e01)
6666

67+
// The cyw43 firmware not-uncommonly reports a transient authentication or WPA
68+
// handshake failure on the first association to an AP, even when the supplied
69+
// credentials are correct; a plain rejoin then succeeds. Automatically rejoin
70+
// this many times before reporting a bad-auth failure to the caller. A
71+
// genuinely wrong password still fails once the retries are exhausted.
72+
#ifndef CYW43_WIFI_JOIN_AUTH_RETRIES
73+
#define CYW43_WIFI_JOIN_AUTH_RETRIES (4)
74+
#endif
75+
6776
#define CYW43_STA_IS_ACTIVE(self) (((self)->itf_state >> CYW43_ITF_STA) & 1)
6877
#define CYW43_AP_IS_ACTIVE(self) (((self)->itf_state >> CYW43_ITF_AP) & 1)
6978

@@ -390,8 +399,15 @@ void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev)
390399
} else if (ev->status == 6) {
391400
// Unsolicited auth packet, ignore it
392401
} else {
393-
// Cannot authenticate
394-
self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH;
402+
// Cannot authenticate. This is often transient on a first
403+
// association, so rejoin a few times before reporting a bad-auth.
404+
if (self->wifi_join_retries > 0) {
405+
self->wifi_join_retries -= 1;
406+
self->pend_rejoin = true;
407+
cyw43_schedule_internal_poll_dispatch(cyw43_poll_func);
408+
} else {
409+
self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH;
410+
}
395411
}
396412
} else if (ev->event_type == CYW43_EV_DEAUTH_IND) {
397413
if (ev->status == 0 && ev->reason == 2) {
@@ -422,8 +438,15 @@ void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev)
422438
self->pend_rejoin = true;
423439
cyw43_schedule_internal_poll_dispatch(cyw43_poll_func);
424440
} else {
425-
// PSK_SUP failure
426-
self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH;
441+
// PSK_SUP failure. As with EV_AUTH this is often transient, so
442+
// rejoin a few times before reporting a bad-auth.
443+
if (self->wifi_join_retries > 0) {
444+
self->wifi_join_retries -= 1;
445+
self->pend_rejoin = true;
446+
cyw43_schedule_internal_poll_dispatch(cyw43_poll_func);
447+
} else {
448+
self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH;
449+
}
427450
}
428451
} else if (ev->event_type == CYW43_EV_ICV_ERROR) {
429452
self->pend_rejoin = true;
@@ -651,6 +674,7 @@ int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t
651674
// Wait for responses: EV_AUTH, EV_LINK, EV_SET_SSID, EV_PSK_SUP
652675
// Will get EV_DEAUTH_IND if password is invalid
653676
self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE;
677+
self->wifi_join_retries = CYW43_WIFI_JOIN_AUTH_RETRIES;
654678

655679
if (auth_type == CYW43_AUTH_OPEN) {
656680
// For open security we don't need EV_PSK_SUP, so set that flag indicator now

0 commit comments

Comments
 (0)