From 1faf1662a01a863b7c0483edd940f0c142d4eb98 Mon Sep 17 00:00:00 2001 From: Niel Nielsen Date: Sat, 29 Aug 2026 19:56:20 +0200 Subject: [PATCH 1/5] Handle WiFi actions in CMD_PM5_BWM_WIFI case Signed-off-by: Niel Nielsen --- armsrc/appmain.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index f9138411b..b14b938f0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -3862,6 +3862,7 @@ static void PacketReceived(PacketCommandNG *packet) { reply_ng(CMD_PM5_BWM_CHARGE_EN, ok ? PM3_SUCCESS : PM3_EFAILED, NULL, 0); break; } + case CMD_PM5_BWM_WIFI: { #if defined(WITH_BWM_FORWARD) uint8_t action = packet->data.asBytes[0]; @@ -3869,14 +3870,22 @@ static void PacketReceived(PacketCommandNG *packet) { int res; if (action == BWM_WIFI_ACTION_STOP) { res = bwm_wifi_forward_down(); + reply_ng(CMD_PM5_BWM_WIFI, res, (uint8_t *)&ip, sizeof(ip)); + } else if (action == BWM_WIFI_ACTION_STATUS) { + uint8_t connected = 0; + res = bwm_wifi_forward_status(&connected, &ip); + uint8_t st[5] = { connected, + (uint8_t)(ip & 0xFF), (uint8_t)((ip >> 8) & 0xFF), + (uint8_t)((ip >> 16) & 0xFF), (uint8_t)((ip >> 24) & 0xFF) }; + reply_ng(CMD_PM5_BWM_WIFI, res, st, sizeof(st)); } else { uint16_t port = packet->data.asBytes[1] | (packet->data.asBytes[2] << 8); char *ssid = (char *)&packet->data.asBytes[3]; char *pwd = ssid + strlen(ssid) + 1; char *host = pwd + strlen(pwd) + 1; res = bwm_wifi_forward_up(ssid, pwd, host, port, &ip); + reply_ng(CMD_PM5_BWM_WIFI, res, (uint8_t *)&ip, sizeof(ip)); } - reply_ng(CMD_PM5_BWM_WIFI, res, (uint8_t *)&ip, sizeof(ip)); #else reply_ng(CMD_PM5_BWM_WIFI, PM3_ENOTIMPL, NULL, 0); #endif From 7d6ca7ba915f3d0a215b8a904f9024888fd228d9 Mon Sep 17 00:00:00 2001 From: Niel Nielsen Date: Sat, 29 Aug 2026 19:59:21 +0200 Subject: [PATCH 2/5] Add BWM_WIFI_ACTION_STATUS definition Signed-off-by: Niel Nielsen --- include/pm3_cmd.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index accbb374f..a60d30689 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -860,6 +860,7 @@ typedef struct { // CMD_PM5_BWM_WIFI payload: [action:u8][port:u16 LE][ssid\0][pwd\0][hostname\0] #define BWM_WIFI_ACTION_START 0x00 // join AP + start TCP server #define BWM_WIFI_ACTION_STOP 0x01 // tear down, back to BLE-only +#define BWM_WIFI_ACTION_STATUS 0x02 // query current connection state + IP // For low-frequency tags #define CMD_LF_TI_READ 0x0202 #define CMD_LF_TI_WRITE 0x0203 From 2572326440a51bb7b2e2897ba0294a3e36c745e5 Mon Sep 17 00:00:00 2001 From: Niel Nielsen Date: Sat, 29 Aug 2026 20:00:36 +0200 Subject: [PATCH 3/5] Add bwm_wifi_forward_status function for WiFi status Signed-off-by: Niel Nielsen --- armsrc/bwm_wifi.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/armsrc/bwm_wifi.c b/armsrc/bwm_wifi.c index 9701eee48..abe081699 100644 --- a/armsrc/bwm_wifi.c +++ b/armsrc/bwm_wifi.c @@ -225,6 +225,23 @@ int bwm_wifi_forward_up(const char *ssid, const char *password, return PM3_SUCCESS; } +int bwm_wifi_forward_status(uint8_t *connected, uint32_t *ip_out) { + const uint32_t TO = 2000; + uint32_t ip = 0; + uint8_t ipb[12]; + uint16_t il = sizeof(ipb); + int r = bwm_cmd(BWM_CMD_GET_WIFI_CFG_IP_ADDR, NULL, 0, ipb, &il, TO); + if (r != PM3_SUCCESS) { + return r; // BWM / UART not responding + } + if (il >= 4) { + ip = (uint32_t)ipb[0] | ((uint32_t)ipb[1] << 8) | ((uint32_t)ipb[2] << 16) | ((uint32_t)ipb[3] << 24); + } + *ip_out = ip; + *connected = (ip != 0) ? 1 : 0; // a lease == a usable connection + return PM3_SUCCESS; +} + int bwm_wifi_forward_down(void) { // Single command: the BWM deinits the TCP server + disconnects the STA and // returns to BLE-only. It persists the disable mode to NVS. From 1b92f7e026e55eadbc4a1e67cbca8c0d2211d3db Mon Sep 17 00:00:00 2001 From: Niel Nielsen Date: Sat, 29 Aug 2026 20:01:24 +0200 Subject: [PATCH 4/5] Increase DHCP wait time to 20000 ms Increased the DHCP wait time from 10 seconds to 20 seconds to allow more time for lease acquisition. Signed-off-by: Niel Nielsen --- armsrc/bwm_wifi.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/armsrc/bwm_wifi.h b/armsrc/bwm_wifi.h index da20fdab1..66ca9e924 100644 --- a/armsrc/bwm_wifi.h +++ b/armsrc/bwm_wifi.h @@ -19,7 +19,7 @@ // After association the STA reports "connected" before DHCP completes, so we // poll GET_IP until a non-zero address appears (or give up). #ifndef BWM_WIFI_DHCP_WAIT_MS -#define BWM_WIFI_DHCP_WAIT_MS 10000 // total time to wait for a DHCP lease +#define BWM_WIFI_DHCP_WAIT_MS 20000 // total time to wait for a DHCP lease #endif #ifndef BWM_WIFI_DHCP_POLL_MS #define BWM_WIFI_DHCP_POLL_MS 500 // gap between GET_IP polls @@ -52,4 +52,10 @@ int bwm_wifi_forward_up(const char *ssid, const char *password, // BLE-only). Persisted on the BWM so it stays off across reboots. int bwm_wifi_forward_down(void); +// Query current forward-mode connection state without reconfiguring. Writes the +// BWM IPv4 (host order, a in low byte; 0 if none) to *ip_out and 1/0 to +// *connected (true == has a DHCP lease). Returns PM3_EFAILED if the BWM/UART +// does not answer. +int bwm_wifi_forward_status(uint8_t *connected, uint32_t *ip_out); + #endif From 03bbf292dc67b76044b8ae001e638f97ad0e5aae Mon Sep 17 00:00:00 2001 From: Niel Nielsen Date: Sat, 29 Aug 2026 20:03:12 +0200 Subject: [PATCH 5/5] Enhance CLI with WiFi status check and timeout adjustment Added status option to CLI for checking WiFi connection state and IP address. Updated command timeout for join and DHCP wait. Signed-off-by: Niel Nielsen --- client/src/cmdhw.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index f47e54dd0..0f99c9e16 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -1560,7 +1560,8 @@ static int CmdBWMWifi(const char *Cmd) { "Bring up the BWM in STA + TCP-server mode: join a WiFi network and\n" "start a TCP server so the client can connect over WiFi. PM5 only.", "hw bwmwifi --ssid Home --pwd secret --> port 7777\n" - "hw bwmwifi --ssid Home --pwd secret --port 9000"); + "hw bwmwifi --ssid Home --pwd secret --port 9000\n" + "hw bwmwifi --status --> show connection state + IP"); void *argtable[] = { arg_param_begin, @@ -1569,6 +1570,7 @@ static int CmdBWMWifi(const char *Cmd) { arg_int0(NULL, "port", "", "TCP server listen port (default 7777)"), arg_str0(NULL, "hostname", "", "DHCP hostname (default Proxmark5)"), arg_lit0(NULL, "stop", "tear down WiFi and return to BLE-only"), + arg_lit0(NULL, "status", "show current WiFi connection state + IP"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1591,8 +1593,38 @@ static int CmdBWMWifi(const char *Cmd) { host_len = 9; } bool stop = arg_get_lit(ctx, 5); + bool status = arg_get_lit(ctx, 6); CLIParserFree(ctx); + if (status) { + uint8_t q[1] = { BWM_WIFI_ACTION_STATUS }; + clearCommandBuffer(); + SendCommandNG(CMD_PM5_BWM_WIFI, q, sizeof(q)); + PacketResponseNG r; + if (WaitForResponseTimeout(CMD_PM5_BWM_WIFI, &r, 5000) == false) { + PrintAndLogEx(WARNING, "command timeout (is this a PM5 with a BWM fitted?)"); + return PM3_ETIMEOUT; + } + if (r.status != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "could not query BWM WiFi status (BWM present?)"); + return r.status; + } + uint8_t connected = (r.length >= 1) ? r.data.asBytes[0] : 0; + uint32_t ip = 0; + if (r.length >= 5) { + ip = r.data.asBytes[1] | (r.data.asBytes[2] << 8) | (r.data.asBytes[3] << 16) | ((uint32_t)r.data.asBytes[4] << 24); + } + if (connected && ip) { + PrintAndLogEx(SUCCESS, "BWM WiFi connected, IP " _YELLOW_("%u.%u.%u.%u"), + ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24) & 0xFF); + PrintAndLogEx(HINT, "Connect with: " _YELLOW_("pm3 -p tcp:%u.%u.%u.%u:"), + ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24) & 0xFF); + } else { + PrintAndLogEx(INFO, "BWM WiFi not connected (no IP). If a join is in progress, re-check in a few seconds."); + } + return PM3_SUCCESS; + } + if (stop) { uint8_t off[1] = { BWM_WIFI_ACTION_STOP }; clearCommandBuffer(); @@ -1640,13 +1672,14 @@ static int CmdBWMWifi(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_PM5_BWM_WIFI, data, n); PacketResponseNG resp; - // ARM blocks during the join (WAIT is up to ~15s), so allow a long client timeout - if (WaitForResponseTimeout(CMD_PM5_BWM_WIFI, &resp, 40000) == false) { + // ARM blocks during join + DHCP wait, so allow a long client timeout + if (WaitForResponseTimeout(CMD_PM5_BWM_WIFI, &resp, 60000) == false) { PrintAndLogEx(WARNING, "command timeout (is this a PM5 with a BWM fitted?)"); return PM3_ETIMEOUT; } if (resp.status != PM3_SUCCESS) { PrintAndLogEx(FAILED, "BWM WiFi bring-up failed (check SSID/password and signal)"); + PrintAndLogEx(HINT, "If it may have joined after DHCP, check: " _YELLOW_("hw bwmwifi --status")); return resp.status; }