The No-Op That Wasn't
The chassis RGB lives in SMM firmware with no Linux driver in existence. A write designed to change nothing turned the lights off — and seven confident beliefs died in 27 hours.
The desktop in this lab is, by manufacture, a gaming machine, and it announces this by colour-cycling its chassis lighting at all hours. Under Linux there is no way to turn that off. No prior art either: every Acer RGB project on Linux is laptop-keyboard only, and the OpenRGB issues for Orion desktops have zero replies.
This is the story of 27 hours across two days: one accidental success, one methodological confession, and seven beliefs held confidently enough to write down — every one of them killed by a cheap, specific test.
Nothing here but a mailbox
The interface hunt worked by elimination, and the negatives are what made the
conclusion solid: no RGB controller on USB, no /sys/class/leds entries, no
EmbeddedControl region (it’s a desktop; there is no EC in the laptop sense), and
zero occurrences of led, rgb, light, or zone in 133,758 lines of ASL.
That leaves one place: all lighting logic lives in SMM firmware, and the DSDT is
a mailbox stub — a WMI method writes a command byte into a buffer at a fixed
physical address and fires an SMI. The method map came from the firmware’s own MOF
blob, decoded with bmfdec, which yielded Acer’s own names: SetGamingLedBehavior,
GetGamingRgbSetting, and friends. Not inferred — theirs.
Two traps surfaced immediately, both worth carrying out of this project:
Method IDs differ from Acer laptops. Mainline acer-wmi and every community
module use method 2 for LED writes; on this board, method 2 is
SetGamingSysConfig. Load a laptop module here and you’re firing LED payloads at a
system-config method.
acpi_call does no arity checking. The handler takes three arguments and
switches on the second. An early probe run passed two — which put the data buffer in
the method selector while the interpreter quietly filled the gap with zero. Every
call appeared to succeed while doing something entirely different. The run was
discarded, but the file is kept, because a silent wrong answer is the most
instructive kind.
The write that changed nothing, except everything
The first deliberate write was designed as a no-op: read a zone’s stored record, write those exact bytes back. Nothing should change — the point was to test the assumed buffer layout. (Logged before execution, always, so a hang leaves a record of what was running.)
The lights went off.
Three facts arrived at once: the layout hypothesis was disproven (a correct no-op reads back identically), the firmware had demonstrably accepted the write, and the actual goal of the whole project — stop the cycling — had been met by accident, via a malformed write.
Then the useful part. Comparing bytes sent against bytes stored gave
stored[i] = input[2i+1], exact on all five values: the buffer is 16-bit fields of
which the firmware keeps the second byte. The failed no-op was the Rosetta stone.
What followed was ninety minutes of proper falsification: the interleave model predicted two writes perfectly, then a third stored values that were never in the input at all. Writes echoing the current state were refused; novel ones were accepted. Two candidate encodings died, a third was wounded, and the log’s low point reads: “black-box guessing has been exhausted at this scale.” That sentence turned out to be the most valuable one in the archive, because it forced the pivot.
Before the pivot, one test mattered more than any model: a full reboot with no OS component at all. The LEDs stayed off. The firmware keeps the record in NVRAM and applies it itself — with the uncomfortable corollary that an accepted-but-wrong record also survives reboots, and only a CMOS clear undoes it.
176 trials, one confound, three wrong beliefs
A structured campaign followed — 176 trials, 89 accepted — which produced a working mode map by eye and one confident, wrong conclusion: “no static mode exists; every mode animates.”
The flaw, named only later: two fields moving together. Every trial of mode 00
also carried enable=00, so the zone went dark and the mode field took the credit.
The same confound produced “records are written globally” (the tool expanded a zone
mask into one write per zone, so every write hit every zone) and hid the real
per-zone off switch. One confound, three separate wrong conclusions, all documented
as unverified at the time — which is why the data got archived rather than
retracted.
Ask something that already speaks the protocol
The pivot: the vendor’s own Windows software knows the correct values, and the firmware stores them where they can be read back. Set a known state in the vendor UI, read the registers, and every capture is a labelled pair — a state a human described, next to the exact bytes that produced it.
The plan budgeted one reboot per capture. Mid-flight, a better discovery: Windows
maps the interface into WMI directly — no driver, no reboot — so 17 captures took
34 minutes instead of 17 reboots. Those 17 captures settled nearly everything:
the zone map (the by-eye assignment had been right), per-zone storage, RGB byte
order pinned on a mixed colour with exact numbers rather than eyeballed pure
channels, and the campaign’s white whale: mode 00 is the static mode. It had
been mislabelled “off” for a full day. The answer was never missing — just filed
under the confound.
Reads back right, displays wrong
The write path still had never been executed — everything so far read states the vendor tool produced. A filmed 23-trial run closed that: on/off by zone worked immediately. Colour did not. All ten test colours displayed an identical blue-white — while every record read back correctly. The firmware stored exactly what it was told and displayed something else. Fifty-five calls, zero refusals.
A four-step probe isolated it:
| sequence | LEDs show |
|---|---|
| behavior write alone | default blue-white |
| colour write alone | red |
| behavior, then colour | green |
| colour, then behavior | default blue-white |
A behavior write resets the live output. Colour must be written last. The stored record keeps your value either way — which is exactly why a read-back can never substitute for a camera.
The claim that didn’t survive the reboot
The tools were published that evening — a PowerShell and a bash implementation emitting byte-identical buffers, asserted by a 26-vector harness that needs no hardware — and the session ended with a handoff note and a reboot into Linux. The note pre-committed to a prediction: colours would reset to the factory default, because that’s what the protocol doc claimed (marked VALIDATED, no less).
The prediction failed. All six colours survived the reboot, including one that matches no default anywhere — not a coincidence of factory values. The handoff had already written down what a contrary result would mean, so the claim died cleanly: withdrawn, split into what each boot path actually showed, discriminating test queued. The tools themselves passed 26/26 natively, then lit five zones one at a time on camera, covering all three colour channels. Zero refusals.
The ledger
| belief | held for | killed by |
|---|---|---|
| assumed buffer layout | one write | the no-op that wasn’t |
| interleave holds universally | ~30 min | a write that invented values |
| getter reports live animation | minutes | two identical reads 3 s apart |
| records written globally | hours, load-bearing | vendor per-zone toggles |
| no static mode exists | hours, load-bearing | it was mode 00, mislabelled |
| colour writes don’t reach LEDs | the whole campaign | the four-step probe |
| colours don’t survive reboot | ~22 h, published as VALIDATED | the first read of the next boot |
Seven beliefs, three load-bearing, every one caught by a test that was cheap and specific. The transferable lessons, in descending order of tuition paid: two fields moving together will fool you three times before you name it; a read-back that confirms your value is not evidence the hardware did it; when black-box inference stalls, find something that already speaks the protocol and make it label your data; and state the prediction before the test — the overturned claim died without argument because its obituary was written in advance.
The lights are off now. It says so in NVRAM.