diff --git a/src/app_main.c b/src/app_main.c index b92ef87..8392ba9 100644 --- a/src/app_main.c +++ b/src/app_main.c @@ -107,6 +107,13 @@ void nl_app_factory_reset(void) nl_state_log_erase(); nl_resetcnt_clear(); store_unlock(); + /* C2: also wipe the SDK's own Wi-Fi params (SSID/key/WPROTOCOL, incl. any leftover + * softap bit) - verified in sdk/Platform/Common/Params/wm_param.c that + * tls_param_to_default() (tls_param_load_factory_default() + param_to_flash()) only + * touches struct tls_sys_param (Wi-Fi/network config); it never touches the MAC + * address or RF calibration data, which live in a separate efuse-backed FT_PARAM_ST + * area (sdk/Platform/Drivers/efuse/wm_efuse.c) that this call never reads or writes. */ + tls_param_to_default(); tls_sys_reset(); } diff --git a/src/net/nl_wifi_w600.c b/src/net/nl_wifi_w600.c index 4f0ac7d..cc8d6e6 100644 --- a/src/net/nl_wifi_w600.c +++ b/src/net/nl_wifi_w600.c @@ -28,6 +28,8 @@ static char s_hostname[24]; static char s_ssid[NL_SSID_LEN], s_pass[NL_PASS_LEN]; static char s_test_ssid[NL_SSID_LEN], s_test_pass[NL_PASS_LEN]; static char s_ap_pass[NL_PASS_LEN]; +static bool s_ap_create_pending; /* M3: tls_wifi_softap_create() failed, retry it */ +static uint32_t s_ap_create_retry_at; static void lock(void) { tls_os_mutex_acquire(s_lock, 0); } static void unlock(void) { tls_os_mutex_release(s_lock); } @@ -38,12 +40,32 @@ static void copy(char *dst, const char *src, size_t size) dst[size - 1] = '\0'; } +static bool due_now(uint32_t now, uint32_t at) { return (int32_t)(now - at) >= 0; } + /* SDK system task context: only hand the event over. */ static void netif_event(u8 status) { tls_os_queue_send(s_queue, (void *)(MSG_NETIF | status), 0); } +/* C2: the SDK sets the SOFTAP bit in TLS_PARAM_ID_WPROTOCOL when tls_wifi_softap_create() + * runs and persists it to flash; tls_wifi_softap_destroy() only sends a supplicant event + * and never clears it. As long as the bit stays set, sys_net_status_changed() in + * sdk/Platform/Sys/tls_sys.c (NETIF_IP_NET_UP case) recreates the AP with the SDK's own + * (public default) softap params on every station IP-up - independent of our auto-connect + * flag. Clear the bit (and persist that) whenever we know the AP should be down. */ +static void clear_softap_param(void) +{ + u8 proto = 0; + + tls_param_get(TLS_PARAM_ID_WPROTOCOL, &proto, TRUE); + if (proto & IEEE80211_MODE_AP) { + proto &= (u8)~IEEE80211_MODE_AP; + tls_param_set(TLS_PARAM_ID_WPROTOCOL, &proto, TRUE); + printf("wifi: cleared stale SDK softap param (wprotocol now %u)\r\n", proto); + } +} + static void start_ap(void) { struct tls_softap_info_t ap; @@ -65,18 +87,24 @@ static void start_ap(void) memcpy(ip.dnsname, "local", 6); r = tls_wifi_softap_create(&ap, &ip); printf("wifi: AP %s %s\r\n", s_hostname, r == WM_SUCCESS ? "up" : "failed"); + /* M3: retry a failed AP create instead of leaving onboarding/fallback without an AP. */ + s_ap_create_pending = r != WM_SUCCESS; + s_ap_create_retry_at = nl_app_now_ms() + 5000u; } static void connect_station(bool test) { char ssid[NL_SSID_LEN], pass[NL_PASS_LEN]; + int r; lock(); copy(ssid, test ? s_test_ssid : s_ssid, sizeof ssid); copy(pass, test ? s_test_pass : s_pass, sizeof pass); unlock(); printf("wifi: connecting to %s\r\n", ssid); - tls_wifi_connect((u8 *)ssid, (u8)strlen(ssid), (u8 *)pass, (u8)strlen(pass)); + r = tls_wifi_connect((u8 *)ssid, (u8)strlen(ssid), (u8 *)pass, (u8)strlen(pass)); + if (r != WM_SUCCESS) /* M2: surface connect-call failures, not just later join events */ + printf("wifi: tls_wifi_connect failed, err=%d\r\n", r); } static void pulse(bool on) @@ -108,6 +136,12 @@ static void execute(nl_wifi_actions_t a) if (a.stop_ap) { printf("wifi: AP down\r\n"); tls_wifi_softap_destroy(); + s_ap_create_pending = false; + clear_softap_param(); /* C2: every softap teardown clears the persisted SOFTAP bit */ + } + if (a.disconnect) { + printf("wifi: dropping stray/failed station attempt\r\n"); + tls_wifi_disconnect(); } if (a.connect) connect_station(a.use_test_creds); @@ -129,7 +163,7 @@ static void net_task(void *arg) void *msg = NULL; nl_wifi_actions_t ev, tick; uint32_t m = 0, now; - bool ip_up = false; + bool got_ip_event = false, connected_now, ap_wanted; memset(&ev, 0, sizeof ev); if (tls_os_queue_receive(s_queue, &msg, 0, HZ / 10) == TLS_OS_SUCCESS) @@ -139,7 +173,7 @@ static void net_task(void *arg) lock(); if (m == (MSG_NETIF | NETIF_IP_NET_UP)) { ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_CONNECTED, NL_WIFI_ERR_NONE, now); - ip_up = true; + got_ip_event = true; } else if (m == (MSG_NETIF | NETIF_WIFI_JOIN_FAILED)) { ev = nl_wifi_sm_event(&s_sm, NL_WIFI_EV_JOIN_FAILED, join_error(), now); } else if (m == (MSG_NETIF | NETIF_WIFI_DISCONNECTED)) { @@ -148,14 +182,31 @@ static void net_task(void *arg) ev = nl_wifi_sm_onboard(&s_sm, now); } tick = nl_wifi_sm_tick(&s_sm, now); + /* I1: a late/stray IP-up must not announce mDNS unless the SM actually settled on STA_CONNECTED. */ + connected_now = s_sm.state == NL_WIFI_ST_STA_CONNECTED; + ap_wanted = s_sm.ap_up; + if (m == (MSG_NETIF | NETIF_WIFI_SOFTAP_SUCCESS) && !ap_wanted) { + /* C2 backstop: the SDK brought its own softap up behind our back (e.g. the + * clear in nl_wifi_start raced a pending sys_net_status_changed()) while our + * state machine does not want an AP. Tear it down and clear the param again. */ + printf("wifi: unexpected SDK softap while AP should be down, destroying it\r\n"); + tls_wifi_softap_destroy(); + clear_softap_param(); + } unlock(); if (m & MSG_NETIF) printf("wifi: netif event %u\r\n", (unsigned)(m & 0xFFu)); execute(ev); execute(tick); - if (ip_up) + if (got_ip_event && connected_now) nl_mdns_on_ip_up(); + + /* M3: retry a softap create that failed, as long as the SM still wants the AP up. */ + if (s_ap_create_pending && ap_wanted && due_now(now, s_ap_create_retry_at)) { + printf("wifi: retrying AP create\r\n"); + start_ap(); + } } } @@ -165,6 +216,8 @@ void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass) nl_wifi_actions_t a; struct netif *nif; + clear_softap_param(); /* C2: drop any softap bit left over from a previous onboarding/fallback */ + tls_get_mac_addr(s_mac); nl_names_hostname(s_mac, s_hostname, sizeof s_hostname); copy(s_ssid, ssid, sizeof s_ssid); @@ -178,6 +231,13 @@ void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass) tls_wifi_auto_connect_flag(WIFI_AUTO_CNT_FLAG_SET, &auto_mode); } tls_wifi_disconnect(); + if (tls_wifi_softap_get_state() != WM_WIFI_DISCONNECTED) { + /* C2: the SDK already brought up its own softap (e.g. from NETIF_IP_NET_UP before + * we got a chance to run) - tear it down, our state machine owns AP lifecycle. */ + printf("wifi: destroying SDK-created softap left over from boot\r\n"); + tls_wifi_softap_destroy(); + clear_softap_param(); + } nif = tls_get_netif(); if (nif) nif->hostname = s_hostname; /* DHCP host name */ @@ -197,12 +257,19 @@ void nl_wifi_start(const char *ssid, const char *pass, const char *ap_pass) int nl_wifi_request_onboard(const char *ssid, const char *pass) { + bool busy; + if (!s_started) return -1; lock(); - copy(s_test_ssid, ssid, sizeof s_test_ssid); - copy(s_test_pass, pass, sizeof s_test_pass); + busy = s_sm.state == NL_WIFI_ST_ONBOARD_TEST; + if (!busy) { + copy(s_test_ssid, ssid, sizeof s_test_ssid); + copy(s_test_pass, pass, sizeof s_test_pass); + } unlock(); + if (busy) /* M1: API returns 503 "wifi busy" instead of queuing on top of a running test */ + return -1; return tls_os_queue_send(s_queue, (void *)MSG_ONBOARD, 0) == TLS_OS_SUCCESS ? 0 : -1; }