Fix build + HTTP + mDNS so the firmware actually serves out of the box#1
Merged
Merged
Conversation
main/hal/storage/hal_storage.cpp:151,156 use TINYUSB_EVENT_SUSPENDED and
TINYUSB_EVENT_RESUMED unconditionally:
case TINYUSB_EVENT_SUSPENDED: ...
case TINYUSB_EVENT_RESUMED: ...
In espressif/esp_tinyusb >= 2.x those enum values are gated by
CONFIG_TINYUSB_SUSPEND_CALLBACK and CONFIG_TINYUSB_RESUME_CALLBACK
(see managed_components/espressif__esp_tinyusb/include/tinyusb.h).
dependencies.lock does not pin esp_tinyusb, so the component manager
resolves to the latest version and a fresh `idf.py build` from a clean
clone fails with:
error: 'TINYUSB_EVENT_SUSPENDED' was not declared in this scope
error: 'TINYUSB_EVENT_RESUMED' was not declared in this scope
Enable both Kconfigs in sdkconfig.defaults so the source matches the
component's API surface again.
apps/app_server/app_server.cpp:1418 sets:
hc.max_open_sockets = 13;
ESP-IDF's httpd validates this against LWIP_MAX_SOCKETS minus 3 (three
sockets are reserved internally). With the IDF default LWIP_MAX_SOCKETS=10
only 7 sockets are available, so httpd_start() fails at boot:
E (...) httpd: Config option max_open_sockets is too large
(max allowed 7, 3 sockets used by HTTP server internally)
Either decrease this or configure LWIP_MAX_SOCKETS to a larger value
E (...) app_server: httpd start fail
The HTTP server then never binds port 80. Devices flashed from a clean
build of this repo present an open AP that accepts associations and hands
out DHCP leases, but nothing answers on 192.168.4.1 — the captive portal
and the entire web UI are unreachable. The same applies on STA / LAN.
The error is logged to UART (GPIO 5/4 per the current console config),
which makes the symptom invisible to anyone debugging over USB-CDC.
Set CONFIG_LWIP_MAX_SOCKETS=16 so the configured 13 + 3 internal fits.
…lient The mdns_init() / mdns_hostname_set() / mdns_instance_name_set() calls were inside the WiFiEvent::AP_STA_CONNECTED event handler — i.e. mDNS was only initialized when a phone joined the device's softAP. Consequences: * In STA-only operation (or any boot where no station ever joins the softAP), mDNS is never initialized and <device_name>.local does not resolve on the LAN. Users get an IP from their router's DHCP but the documented papercolor.local hostname doesn't work. * The behavior is timing-dependent: as soon as one phone briefly joins the AP, mDNS comes up retroactively and starts working on STA too. This makes the bug intermittent and easy to miss. Move the init to app_server_init, right after the URI handlers are registered. The mdns component watches netif up/down events itself, so a single init at boot covers both STA and AP transitions cleanly. The existing rename path in h_wifi_config already re-calls mdns_hostname_set() when device_name changes, so renaming still works. Also add an _http._tcp service advertisement so the device shows up in Finder's Network sidebar and other Bonjour browsers without needing to know the hostname in advance. The event handler now only logs the AP_STA_CONNECTED transition.
pmokbel
added a commit
to pmokbel/M5PaperColor-album
that referenced
this pull request
May 27, 2026
…stream README is rewritten from the upstream's terse build-and-flash instructions into a description of what this fork actually is: a single-purpose LAN photo frame. Covers: - The one-line pitch (upload photos via http://papercolor.local from any LAN browser, no app or cloud) - Hardware target, build/flash, with the TinyUSB-MSC flashing caveat spelled out (esptool can only catch the device during the brief pre-MSC boot window) - First-run onboarding via the open AP, and how to re-onboard later via long-press - A 'differences from upstream' section split into 'bugs we fixed and pushed upstream' (PR m5stack#1 against m5stack/M5PaperColor-UserDemo) and 'opinionated changes' (no cloud, STA-first, LAN-accessible upload, single-mode UI) - Known caveats: open AP during onboarding, EzData .cpp still compiled in, factory-guide boot flow, console on UART CHANGES is a complete file-by-file accounting of how the fork diverges from m5stack/M5PaperColor-UserDemo@0b3d5ef, structured around the commit topology so the upstream-PR-worthy fixes stay clearly separable from the opinionated changes. sdkconfig.defaults: small inline comment in the Console UART section explaining the USB-Serial-JTAG / TinyUSB MSC interaction so anyone reading the config understands why the flashing workflow needs power-cycling.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three small fixes that get the published source building and serving HTTP correctly out of the box. Each fix is its own commit with a detailed message; this PR is intended to be safe to merge as-is with no behavioral change beyond "the device works."
1. Enable TinyUSB suspend/resume Kconfigs (
bf7d6ff)main/hal/storage/hal_storage.cpp:151,156usesTINYUSB_EVENT_SUSPENDEDandTINYUSB_EVENT_RESUMEDunconditionally. Inespressif/esp_tinyusb >= 2.xthose enum values are gated behindCONFIG_TINYUSB_SUSPEND_CALLBACK/CONFIG_TINYUSB_RESUME_CALLBACK.dependencies.lockdoesn't pinesp_tinyusb, so the component manager resolves the latest and a freshidf.py buildfrom a clean clone fails with:Fix: enable both Kconfigs in
sdkconfig.defaults.2. Bump
LWIP_MAX_SOCKETSsohttpd_startcan bind (e87a2cb)apps/app_server/app_server.cpp:1418setshc.max_open_sockets = 13. ESP-IDF'shttpd_start()validates this againstLWIP_MAX_SOCKETS - 3(three sockets reserved internally). The IDF defaultLWIP_MAX_SOCKETS=10leaves only 7 available, sohttpd_start()returnsESP_ERR_INVALID_ARG:The HTTP server then never binds port 80. Devices flashed from a clean build of this repo accept Wi-Fi associations and DHCP, but nothing answers on
192.168.4.1— captive portal and LAN UI are both unreachable. The error logs to UART (GPIO 5/4 per the current console config), so the symptom is invisible to anyone debugging over USB-CDC.Fix: set
CONFIG_LWIP_MAX_SOCKETS=16so the configured 13 + 3 internal fits.3. Initialize mDNS at boot instead of on first AP client (
f61f77e)mdns_init()/mdns_hostname_set()/mdns_instance_name_set()lived inside theWiFiEvent::AP_STA_CONNECTEDevent handler — i.e. mDNS was only initialized when a phone joined the device's softAP.Consequences:
<device_name>.localdoesn't resolve on the LAN.Fix: move the init to
app_server_init, right after URI handlers are registered. Themdnscomponent watches netif up/down events itself, so one init at boot covers both STA and AP cleanly. The existing rename path inh_wifi_configalready re-callsmdns_hostname_set()so renaming still works.Also adds an
_http._tcpservice advertisement so the device shows up in Finder's Network sidebar anddns-sd -B _http._tcpwithout needing to know the hostname.The event handler is reduced to just logging the transition.
Test plan
Built clean against ESP-IDF v5.5.1 with
idf.py build. Before the LWIP fix:httpd start failat boot. After:papercolor server ready, 18 routesandhttp://192.168.4.1/serves the captive portal. After the mDNS fix:papercolor.localresolves on STA without needing a phone to ever associate to the AP.No behavioral change beyond "the documented behavior actually happens."