Skip to content

gl-e750-oled: add new package - #30695

Open
ServPol wants to merge 1 commit into
openwrt:masterfrom
ServPol:gl-e750-mcu
Open

ServPol wants to merge 1 commit into
openwrt:masterfrom
ServPol:gl-e750-mcu

Conversation

@ServPol

@ServPol ServPol commented Oct 4, 2026 •

Copy link
Copy Markdown

📦 Package Details

Maintainer: @ServPol

Description:
Reworked after review: this is now only the OLED service for the GL.iNet GL-E750 (Mudi). The MCU transport, the battery (power_supply) and the console handling moved to the kernel/board side in openwrt/openwrt#25649 (kmod-gl-e750-mcu), which this package depends on.

gl-e750-oled is a small ucode service that builds the screen content (Wi-Fi SSIDs/keys per band, client count, uplink type, cellular state, VPN state, clock) and writes it as JSON to /dev/gl-e750-mcu.

  • reacts to netifd interface events and hostapd notifications instead of polling; only the clock and the cellular signal (uqmi, QMI only) are refreshed once a minute
  • JSON comes from ucode's encoder, no hand-made escaping
  • uplink type from the protocol of the interface holding the default route and the Wi-Fi mode of its network; VPN state from interfaces with a VPN protocol; nothing hardcoded
  • no /etc/inittab changes and no direct UART access anymore

Known issue: with the ucode currently in main, stopping the service occasionally crashes ucode on exit after hostapd notifications were received. That is ucode-lang/ucode#438, fixed upstream; the running service is not affected.


🧪 Run Testing Details

The screen shows the clock, Wi-Fi bands, SIM state and follows clients joining and leaving within a second; battery data comes from /sys/class/power_supply/gl-e750-battery.


✅ Formalities

  • I have reviewed the CONTRIBUTING.md file for detailed contributing guidelines.

# ttyS0 is wired to the status MCU, not to a user console. A login prompt on
# it reads the MCU replies, so turn it off as the vendor firmware does.
# procd reads /etc/inittab at boot, so this takes effect after a reboot.
sed -i 's|^::askconsole:|#::askconsole:|' /etc/inittab

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing reverts this edit: there is no postrm/prerm that restores ::askconsole:, and /etc/inittab is in base-files' keep list, so the serial console stays disabled after apk del, and after sysupgrades too. Add a Package/gl-e750-mcu/postrm that runs the reverse sed (guarded by IPKG_INSTROOT and board name).


Generated by Claude Code

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks


Generated by Claude Code

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BKPepe thanks for the review, reworked along those lines:

  • kernel side: ath79: gl-e750: add status MCU driver (OLED, battery) openwrt#25649 adds kmod-gl-e750-mcu, a serdev driver bound from the DTS. It owns the MCU UART, exposes the battery as a power_supply (gl-e750-battery), turns the MCU's power-switch event into an orderly poweroff and takes screen updates through /dev/gl-e750-mcu. The board DTS sets console=ttynull, so /etc/inittab is no longer touched.
  • this package is now only gl-e750-oled, a small event-driven ucode service (netifd/hostapd ubus events, JSON via ucode's encoder). It depends on kmod-gl-e750-mcu, so it can only be merged after adblock-fast: Makefile bugfixes and hijack rework #25649.

Tested on GL-E750 V1 and V2 with OpenWrt main. Marking ready for review.

[ "$enabled" -eq 1 ] || return 0

procd_open_instance
procd_set_param command /usr/sbin/gl-e750-mcu

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reload trigger never restarts the daemon. With no reload_service, reload just runs start again, and procd keeps the instance because its params are unchanged. A changed interval/hide_psk/modem_every therefore only takes effect after a manual restart. Let procd track the config file:

Suggested change
procd_set_param command /usr/sbin/gl-e750-mcu
procd_set_param command /usr/sbin/gl-e750-mcu
procd_set_param file /etc/config/gl-e750-mcu

Generated by Claude Code

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks


Generated by Claude Code

Comment thread utils/gl-e750-mcu/files/gl-e750-mcu.sh Outdated
# Keep kernel messages off the MCU uart, like the vendor firmware does.
echo "1 4 1 7" > /proc/sys/kernel/printk
stty -F "$TTY" 115200 raw -echo -echoe -echok -echoctl -echoke \
-icrnl -opost -onlcr -isig -icanon -iexten min 0 time 1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With min 0 time 1, a read() that sees no data for 100 ms returns 0. The cat "$TTY" in mcu_query (line 46) treats that as EOF and exits, so a reply is only caught if the MCU answers within about 100 ms, and the sleep 2/kill never comes into play. min 1 time 0 keeps cat blocking until it is killed, which seems to be the intent:

Suggested change
-icrnl -opost -onlcr -isig -icanon -iexten min 0 time 1
-icrnl -opost -onlcr -isig -icanon -iexten min 1 time 0

Generated by Claude Code

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks


Generated by Claude Code

@ServPol
ServPol force-pushed the gl-e750-mcu branch 2 times, most recently from 83774f7 to b2ea3b9 Compare October 4, 2026 19:09
@ServPol

ServPol commented Oct 4, 2026

Copy link
Copy Markdown
Author

Thanks, all three addressed in b2ea3b9 and re-tested on a GL-E750 V2 (25.12.5):

  • postrm restores ::askconsole: on removal (board-guarded, skipped in IPKG_INSTROOT)
  • procd_set_param file /etc/config/gl-e750-mcu: a config change now restarts the daemon, a plain reload with no change keeps it
  • tty set to min 1 time 0, so cat blocks until killed; battery data is read as before

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 new commits; no new issues found.


Generated by Claude Code

@ServPol

ServPol commented Oct 5, 2026

Copy link
Copy Markdown
Author

Relaxed DEPENDS from @TARGET_ath79_nand to @TARGET_ath79 (34a90e6): with the nand-only dependency the CI skipped the package on every arch ("unsupported architecture"), while the mips_24kc job uses the ath79/generic SDK, so it is now actually built and tested there. On other boards the service and uci-defaults still do nothing (board_name check). The earlier powerpc_464fp failure was a SDK download checksum mismatch, unrelated.

@BKPepe BKPepe left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be merged in its current form.

The GL-E750 MCU support itself is useful, but this package mixes two different responsibilities:

  1. hardware/MCU transport and battery telemetry
  2. userspace collection of network/UI state for the OLED

The first part should not be implemented as a polling shell daemon talking directly to /dev/ttyS0. The MCU is a real hardware controller connected through UART, and Linux already provides the appropriate serial/serdev infrastructure for protocol devices. Battery telemetry should also be exposed through the standard power_supply interface rather than a private /var/run/gl-e750-mcu/battery file.

The userspace part can then remain small and only handle the OLED presentation. It can consume normal OpenWrt/kernel/network state and send the resulting JSON to the MCU.

There are also several problems with the current implementation itself: it rebuilds JSON with destructive "escaping", polls UCI/ubus/hostapd/QMI periodically instead of reacting to state changes, uses heuristics for uplink/VPN state, hardcodes vpn_status=off, and modifies /etc/inittab to disable the serial console.

In particular, changing /etc/inittab from a package is a strong indication that the UART/MCU relationship should be handled as part of board/kernel support rather than by an application installed later.

I would therefore suggest splitting this into:

  • an OpenWrt/kernel change for the GL-E750 MCU device and UART/serdev driver
  • standard power_supply exposure for the battery state
  • a small userspace OLED service/package on top of that.

The OLED functionality itself is useful and worth keeping, but I don't think the current shell daemon is the right abstraction for upstream OpenWrt.

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 new commits; no new issues found.


Generated by Claude Code

@ServPol

ServPol commented Oct 5, 2026

Copy link
Copy Markdown
Author

Thanks for the thorough review, agreed. I will rework it along those lines:

  • a serdev driver for the GL-E750 MCU (kmod in openwrt/openwrt, DT node under the UART), exposing the battery via power_supply and a small interface for the OLED payload
  • moving the console away from ttyS0 as part of the GL-E750 board support instead of editing /etc/inittab
  • a small event-driven OLED service on top (proper JSON encoding, no uplink/VPN heuristics)

Converting this to draft until the kernel side is up and tested on V1/V2; I will link the openwrt/openwrt PR here.

Show the router state on the OLED of the GL.iNet GL-E750 (Mudi): Wi-Fi
SSIDs/keys per band, client count, uplink type, cellular state, VPN state
and the clock.

The MCU transport and the battery are handled by kmod-gl-e750-mcu in
openwrt/openwrt; this service only builds the screen content and writes
it to /dev/gl-e750-mcu. It is a ucode program that reacts to netifd
interface events and hostapd notifications instead of polling; only the
clock (once a minute) and the cellular signal via uqmi (once a minute,
QMI only) are refreshed periodically. JSON is produced with ucode's
encoder. The uplink type comes from the protocol of the interface that
holds the default route and the Wi-Fi mode of its network, the VPN state
from interfaces with a VPN protocol.

Tested on a GL-E750 V1 and V2 with a main build that includes
kmod-gl-e750-mcu: the screen follows clients joining and leaving within a
second, Wi-Fi changes, and shows the clock and SIM state.

With the ucode currently in main, stopping the service occasionally
crashes ucode on exit after hostapd notifications were received; that is
ucode-lang/ucode#438 (fixed upstream), it does not affect the running
service.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Serv Pol <servpol@w420.ru>
@ServPol ServPol changed the title gl-e750-mcu: add new package gl-e750-oled: add new package Oct 5, 2026
@ServPol
ServPol marked this pull request as ready for review October 5, 2026 20:43
@ServPol

ServPol commented Oct 5, 2026

Copy link
Copy Markdown
Author

@BKPepe reworked as you suggested, see the reply in the review thread above. The kernel side (serdev driver, power_supply, power switch, console=ttynull in the DTS) is in openwrt/openwrt#25649; this package is now only the gl-e750-oled userspace service on top of it. Ready for another look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants