Repository navigation
Conversation
setup() called esp_wifi_set_country() and esp_wifi_set_max_tx_power() before Wi-Fi was ever initialized, so both returned ESP_ERR_WIFI_NOT_INIT (return codes were ignored) and the driver kept its default "01" country (channels 1-11). Every module that walks channels 1-14 (deauther, karma, sniffers, sdr...) silently failed on 12-14: esp_wifi_set_channel() returned ESP_ERR_INVALID_ARG. Wi-Fi is brought up on demand via WiFi.mode() in many places, so set the country from an ARDUINO_EVENT_WIFI_READY handler, which runs every time the driver is (re)initialized. The early esp_wifi_set_max_tx_power(80) is dropped: it never took effect, the driver already defaults to 78 (19.5 dBm), and re-applying it on every start could override modules that set their own TX power (sdr.cpp).
There was a problem hiding this comment.
🟡 Changes recommended
Direct ESP-IDF Wi-Fi initialization bypasses the callback that applies country settings, leaving channels 12–14 unavailable when sniffer, pwngrid, or SDR initializes Wi-Fi first.
1 open issue
What changed in this PR
This PR moves Wi-Fi country configuration out of early startup and into the Arduino driver-ready callback, aiming to enable channels 12–14 for Wi-Fi features.
Changes:
- Applies the existing country settings on
ARDUINO_EVENT_WIFI_READY. - Logs country-configuration failures.
- Removes the ineffective early transmit-power setting.
| File | Description |
|---|---|
src/main.cpp |
Adds and registers applyWifiCountry(), replacing premature Wi-Fi configuration calls. |
Review effort: Balanced
| // Wi-Fi is initialized on demand (WiFi.mode() all over the code), so at this point the driver | ||
| // doesn't exist yet and esp_wifi_set_country() would fail with ESP_ERR_WIFI_NOT_INIT. | ||
| // Apply the country every time the driver is (re)initialized instead. | ||
| WiFi.onEvent(applyWifiCountry, ARDUINO_EVENT_WIFI_READY); |
There was a problem hiding this comment.
Confirmed on hardware and fixed in aaee325. With the NVS partition erased, the sniffer path (direct esp_wifi_init()) came up with cc=01 nchan=11 and set_channel(13)=ESP_ERR_INVALID_ARG on the previous commit. With applyWifiCountry() now called right after each direct esp_wifi_init() (sniffer, pwngrid, spam, sdr, channel_analyzer, jam_detect), it comes up with cc=US nchan=14 and set_channel(13)=ESP_OK. Before, it only looked fine when an earlier WiFi.mode() had persisted the country to NVS. Details are in the PR description.
…irectly sniffer, pwngrid, spam, sdr, channel_analyzer and jam_detect bring Wi-Fi up with esp_wifi_init() instead of the Arduino core, so ARDUINO_EVENT_WIFI_READY never fires for them. They only got the right country when an earlier WiFi.mode() had persisted it to NVS; on a clean NVS they ran with the default "01" country and channels 12-14 failed. Move the setup into applyWifiCountry() in wifi_common and call it right after each direct esp_wifi_init(), keeping the WIFI_READY handler for the Arduino path.

Proposed Changes
setup()sets the Wi-Fi country (US, channels 1–14, manual policy) and the max TX power right afterbefore-wifi-init. At that point the Wi-Fi driver hasn't been initialized yet: Bruce brings Wi-Fi up on demand. Both calls returnESP_ERR_WIFI_NOT_INIT, and since the return codes are ignored, this goes unnoticed. The driver then keeps its default country01(world safe, channels 1–11).Result: features that walk channels 1–14 (deauther, karma, sniffers, sdr,
wifi_atks…) fail on channels 12–14, becauseesp_wifi_set_channel(12..14)returnsESP_ERR_INVALID_ARG.Wi-Fi is brought up in two ways:
WiFi.mode()in many places. The core postsARDUINO_EVENT_WIFI_READYright afteresp_wifi_init(), so a handler registered insetup()applies the country every time the driver is (re)initialized.esp_wifi_init()called directly, which never fires that event. This happens insniffer.cpp,pwngrid.cpp,spam.cpp,sdr.cpp,channel_analyzer.cppandjam_detect.cpp. Each of them now callsapplyWifiCountry()right afteresp_wifi_init(). Thanks to the Copilot review for pointing out this path.Changes:
applyWifiCountry()added tocore/wifi/wifi_common.{h,cpp}. The country config is unchanged from whatsetup()already defined.setup()registers it forARDUINO_EVENT_WIFI_READYinstead of calling it too early.applyWifiCountry()call after each of the six directesp_wifi_init()calls.esp_wifi_set_max_tx_power(80)is removed:esp_wifi_set_max_tx_power()only works afteresp_wifi_start(). Re-applying it on every start could override modules that set their own TX power, such assdr.cpp.Why the direct path sometimes looked fine: the Arduino core initializes Wi-Fi with persistent storage, which is the default and is never disabled in Bruce. Once any
WiFi.mode()path had applied the country, it was saved to NVS, and later directesp_wifi_init()calls loaded it from there. On a clean NVS (fresh flash, NVS erased, or when the first Wi-Fi feature used is one of those six modules), they ran with01.Types of Changes
Bugfix.
Verification
Measured on an M5StickC Plus2 (
m5stack-cplus2) with a temporary diagnostic task, which is not part of this PR. After Wi-Fi came up, the task printed the active country and the result ofesp_wifi_set_channel(13).Current
dev,wifi onover serial:Direct
esp_wifi_init()path (serialsniffercommand, NVS partition erased before each run):cc=01 nchan=11,set_channel(13)=ESP_ERR_INVALID_ARGcc=US nchan=14,set_channel(13)=ESP_OKArduino path with this PR (serial
wifi on, NVS erased):cc=US nchan=14,set_channel(13)=ESP_OKonce it fell back to AP mode. Across repeatedwifi on/wifi offcycles, the country was re-applied on every init and channels 11–14 were accepted.Testing
pio run -e m5stack-cplus2builds. The added lines follow.clang-format.wifi on/wifi offandsnifferwork, with noesp_wifi_set_countryerrors and no crashes.WiFi.onEvent(),ARDUINO_EVENT_WIFI_READYandesp_wifi_set_country();main.cppalready called the last one for every board.Linked Issues
None found.
User-Facing Change
Further Comments
This only makes the existing, intended country config (
US, 1–14, manual) take effect. Regional rules differ (channel 14, and in some regions 12–13, aren't allowed everywhere). If maintainers would rather make the country configurable,applyWifiCountry()is now the single place to do it.