Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Prism

RGB control for ASUS Aura motherboards that does not need Armoury Crate, does not install a driver, and does not put an executable on disk.

Prism

Built on a PRIME A620AM-K with Smart App Control enforcing. Prism talks to the Aura controller over the HID stack Windows already ships, so there is nothing to install, nothing for Smart App Control to block, and nothing to go stale on an update.


Why

Armoury Crate runs fifteen processes to change the colour of some fans, and it breaks. Prism does the same job from a single process that you can close, because most of the time the lighting is not running in Prism at all — it is running on the controller.


What it found on this machine

Aura controller   VID_0B05  PID_1BED   firmware AULA3-AR36-0104
Transport         USB HID, usage page 0xFF72, 65-byte reports
Channels          3 addressable ARGB headers, up to 120 LEDs each
Onboard LEDs      none (config_table[0x1B] = 0)

Prism reads the controller's config table at startup, so it adapts to whatever board it finds rather than hard-coding this one.


Running it

Double-click Prism.vbs.

That is the whole thing. wscript.exe starts powershell.exe, which compiles src\*.cs into memory using the C# compiler already inside Windows and runs the app in-process. No .exe is written, no SDK is needed, nothing is installed. Startup costs about a second.

powershell -ExecutionPolicy Bypass -File .\Prism.ps1 does the same with a console window, which is useful when something has gone wrong.

Settings live in %APPDATA%\Prism\config.json.

Why not just build an exe?

Smart App Control is on and enforcing here (VerifiedAndReputablePolicyState = 1, UsermodeCodeIntegrityPolicyEnforcementStatus = 2). It blocks unsigned locally-built binaries on sight, there is no per-app exception, and self-signing does not help — it trusts Microsoft's certificate list and reputation service, not your certificate store.

It does not block powershell.exe, and it is not forcing PowerShell into Constrained Language Mode here ($ExecutionContext.SessionState.LanguageMode reports FullLanguage, and Add-Type works). So the in-memory route produces the identical app with nothing for the policy to reject.

Turning Smart App Control off is one-way — it cannot be switched back on without resetting Windows. There is no reason to spend that here.

build.ps1 will still produce bin\Prism.exe if your machine has no such policy.

Starting with Windows

Prism registers a shortcut in the Startup folder, not an HKCU\...\Run key.

Both launch reliably, but Windows' own startup enumeration — Task Manager's Startup apps tab and Settings → Apps → Startup — did not list the Run entry when its command was a script host, so there was no way to see or turn it off from the UI. A Startup shortcut shows up by name:

Name    Command      Location
Prism   Prism.lnk    Startup

The shortcut is re-pointed at every launch, so moving the Prism folder does not leave a dead entry behind. Start hidden at login only affects that automatic launch — opening Prism yourself always shows the window.


The one idea worth understanding

Every effect is either on the controller or rendered by Prism, and the UI labels which.

Controller effects Prism effects
Runs on The Aura chip itself The app, ~30 fps over USB
Prism closed Keeps running Stops at the last frame
App crashes Keeps running Stops
Survives reboot Yes, before Windows even loads No
Looks like Static, Breathing, Chase, Rainbow… Fire, Comet, Twinkle, Scanner…

Pick a controller effect and Prism becomes optional. It sets the mode, commits it to the chip, and the engine then goes completely idle — no frame loop, no USB traffic, nothing to fail. Kill the process and your lights carry on.

Pick a Prism effect when you want something the firmware cannot do.

Mixing is fine: run Fire on the header with your AIO and a committed Static on the other two.


Scenes

The home page applies a whole look in one click. Each tile says whether it will keep running without Prism.

Scene What it is Runs on
Spectrum Every hue, laid along each header Controller
Breathe A slow fade, easy to sit next to Controller
Steady One clean colour that never moves Controller
Aurora Cold greens and violets, drifting Prism
Ember Banked coals, warm and restless Prism
Glacier Pale ice, breathing slowly Prism
Nightfall Deep indigo bleeding into rose Prism
Pursuit A cyan comet on a dark field Prism

Channels

Channels

Per header, independently:

  • Effect — ten controller effects, eight Prism ones
  • Colours — up to four, with an HSV picker; Gradient and Pulse blend across the whole set
  • Speed, Brightness, Reverse direction
  • LED count — how many LEDs are actually wired to that header, up to 120
  • Enabled — off means off, committed, so it stays off

Apply this look to every header copies the current channel onto the others.

The preview strip is the real renderer running the real effect, so what you see is what the LEDs do.

Getting the LED count right

Set it to the number of LEDs physically on that header — three fans with eight LEDs each is 24. Too low and the far end of the strip stays dark; too high and Prism wastes USB bandwidth on LEDs that are not there. Keeping a channel at 20 or under also halves the packets per frame, which noticeably helps the frame rate of Prism-rendered effects.


Settings

Settings


How it stays up

The failure modes that make Armoury Crate feel unreliable are each handled deliberately:

Nothing owns the device but the engine. One background thread holds the HID handle. Every write goes through it, and every failure path leads back to "try to reconnect", never to a dead app.

Reconnects by itself. If the controller drops off the bus, the engine retries with a backoff up to 8 seconds and re-finds the device by VID/PID — the device path changes across a USB re-enumeration, so reopening the old path would not work.

Comes back from sleep. On resume Prism re-asserts, then re-asserts again four seconds later, because the USB path often is not settled the first time.

A UI bug cannot take the lighting down. The dispatcher exception handler marks exceptions handled and logs them; the lighting thread is independent of the window.

Your settings survive. config.json is never written in place — a save goes to a temp file, is flushed to the physical disk, then swapped in atomically with the old copy kept as config.bak.

Reading it is the harder half. Prism starts at login, where that read races the antivirus and the rest of the boot storm, so it opens the file shared and retries with a backoff out to about nine seconds before falling back to config.bak. If it still cannot be read, Prism:

  • runs on defaults but refuses to save, so your file is never overwritten by them;
  • does not push those defaults to the controller, so your actual lighting is left alone;
  • says so in a banner across the top rather than a status line you might miss;
  • and keeps retrying in the background, adopting your real settings the moment the file becomes readable — unless you have already changed something, in which case what you did wins.

An earlier version retried for only 600ms and then gave up permanently for the session. That was not nearly enough at login: the file read failed, defaults loaded, saving was disabled, and every change made that session went nowhere. It looked exactly like an app that does not save.

The flash is not worn out. Commit writes the controller's own memory, so it only fires when the hardware-side configuration actually changed, not on every slider drag.

Frames that change nothing are not sent. A static software effect costs one USB write, then silence.


ASUS services

LightingService writes to the same controller Prism does. With both running they fight, which is exactly what flaky lighting looks like.

powershell -ExecutionPolicy Bypass -File tools\asus-lighting.ps1 -Status
powershell -ExecutionPolicy Bypass -File tools\asus-lighting.ps1 -Disable

-Disable records the current start mode and run state of every service and scheduled task it touches into %APPDATA%\Prism\asus-services-backup.json before changing anything, then stops and disables LightingService and ArmouryCrateService, disables the tasks that restart them, and closes the lighting processes. It self-elevates, so expect one UAC prompt.

Running -Disable again never overwrites that backup. A second run would otherwise record the already-disabled state over the good one and quietly turn -Restore into a no-op — the first recording is the one worth keeping. Pass -ReRecord if you genuinely want to re-snapshot.

AsusFanControlService is deliberately left alone — that is fan curves, not lighting.

powershell -ExecutionPolicy Bypass -File tools\asus-lighting.ps1 -Restore

-Restore puts every item back to the state it was recorded in, not a guess. Close Prism first or the two will compete again.


What Prism does not do

RGB RAM. DDR5 RGB is not on the Aura USB controller — it sits behind the SMBus, reached through the DIMM's SPD hub, and there is no user-mode path to it. Reaching it needs a kernel driver: OpenRGB used WinRing0 until Microsoft Defender began quarantining it as VulnerableDriver:WinNT/Winring0 (CVE-2020-14979), and now uses PawnIO, which is signed.

So it is possible, but it costs exactly the thing Prism was built to avoid.

The good news: the RGB controller on a DDR5 module stores its mode on the module — that is why RGB RAM lights up in the BIOS before Windows exists. Set the RAM once in Armoury Crate, commit it, and then disable the lighting stack. The sticks keep doing that forever, with nothing running.

Peripherals. Razer, Corsair and friends each speak their own protocol. The backend layer is separate from the UI, so another one can be added without a rewrite.

GPUs. A card's lighting, where the board partner fitted any, is a separate controller.


Config file

%APPDATA%\Prism\config.json. Comments and trailing commas are tolerated, so it is comfortable to hand-edit; Prism reloads it on the next apply.

{
  "app": {
    "startWithWindows": true,
    "startMinimized": true,      // only affects the login launch
    "fps": 40,                   // Prism-rendered effects only
    "reassertOnResume": true,
    "turnOffOnShutdown": false,
    "accent": "#7AA2F7"
  },
  "channels": [
    {
      "index": 0,
      "name": "ARGB header 1",
      "ledCount": 30,
      "enabled": true,
      "effect": "hw.static",     // hw.* = controller, sw.* = Prism
      "colors": ["#00C8B4"],
      "speed": 0.45,
      "brightness": 1,
      "reverse": false
    }
  ]
}

Effect ids: hw.static hw.breathing hw.flashing hw.spectrum hw.rainbow hw.chase hw.chasefade hw.wave hw.flicker hw.off · sw.solid sw.flow sw.gradient sw.pulse sw.comet sw.fire sw.twinkle sw.scanner


Tools

Command What it does
tools\probe.ps1 Dumps every ASUS HID interface, then asks the controller for its firmware string and config table. Read-only.
tools\test-lights.ps1 Red → green → blue → white → rainbow sweep → committed teal breathing. Proves control end to end.
tools\check.ps1 Compiles the sources and prints errors without launching anything.
tools\shot.ps1 Captures the Prism window to a PNG.
tools\make-icon.ps1 Draws prism.ico from scratch, so no binary asset has to live in the repo.
tools\asus-lighting.ps1 -Status, -Disable, -Restore for the ASUS lighting stack.

How it is put together

File Role
src/Hid.cs SetupAPI + hid.dll: enumerate, open, overlapped read/write with real timeouts
src/Aura.cs The Aura USB protocol — identify, config table, direct mode, effects, commit
src/Effects.cs The effect registry and every renderer
src/Scenes.cs Whole-machine looks applied in one click
src/Engine.cs The lighting thread: device ownership, reconnect, frame loop, dirty checking
src/Config.cs Settings model, atomic save, resilient load
src/MainWindow.cs Shell: title bar, navigation, status strip
src/PageView.cs The page contract and the shared render pipeline
src/HomeView.cs Landing page: controller state, scenes, channel overview
src/ChannelsView.cs Per-header editor
src/SettingsView.cs Settings page
src/Ui.cs Buttons, toggles, sliders, fields, cards, glyphs, dialog shell
src/UiExtra.cs LED strip preview, swatches, palette row, HSV colour picker
src/SlimScroll.cs Scroll region with the stock scrollbar hidden and a thin overlay thumb
src/App.cs Entry point, single instance, tray icon, power and session events
src/Native.cs DWM chrome and the Startup-folder autostart entry
src/Json.cs Small JSON reader/writer

No XAML — every control is built in code, which is why the whole thing compiles with the in-box compiler and has no satellite assemblies. Icons are stroked vector paths rather than an icon font, because Segoe Fluent Icons is not guaranteed to be installed and a missing glyph renders as a box.

The protocol, briefly

Messages are 65 bytes, report ID 0xEC.

Command Bytes
Identify EC 82EC 02 + 16-char firmware string
Config table EC B0EC 30 + 60 bytes from offset 0x04
Direct mode on EC 35 <channel> 00 00 FF
Push colours EC 40 <0x80|channel> <offset> <count> <RGB…> — 20 LEDs per packet, apply bit on the last
Hardware effect EC 35 <channel> 00 <shutdown> <mode>
Effect colour EC 36 <mask hi> <mask lo> <shutdown> <RGB at 5+3×slot>
Commit EC 3F 55

From config_table: [0x02] addressable headers, [0x1B] onboard LEDs, [0x1D] RGB headers, and a 6-byte descriptor per header from 0x03 whose fourth byte is the LED ceiling.


Troubleshooting

The window never appears. Run Prism.ps1 directly instead of the .vbs so you can see the console, and check %APPDATA%\Prism\error.log.

Status says "No Aura controller found". Run tools\probe.ps1. If it lists the device but cannot open it, something is holding it — run tools\asus-lighting.ps1 -Status.

Colours flicker or snap back. LightingService is still running. tools\asus-lighting.ps1 -Disable.

Prism-rendered effects look choppy. Lower the LED count per channel, or drop the frame rate in Settings. Three channels at 30 LEDs is six USB packets a frame, which caps out around 30 fps. Controller effects are unaffected — they cost nothing.

Lights are wrong after waking up. Tray icon → Re-apply now.

It came up with default channels instead of mine, and nothing I change sticks. You will see a banner across the top saying the settings could not be read. Your file is safe — Prism will not overwrite it, and it is still retrying; leave it a moment or press Retry now. Your settings are in config.json with a second copy in config.bak, both under %APPDATA%\Prism. Restarting also works. If it happens at every login, your antivirus is holding the file longer than Prism waits; adding %APPDATA%\Prism as a scan exclusion fixes it at the source.


Licence

GPL-2.0-or-later. See LICENSE.

The Aura USB protocol was worked out from OpenRGB's AsusAuraUSBController, which is GPL-2.0-or-later. Prism is an independent implementation in C# with no code copied, but the protocol knowledge comes from that project, so Prism carries the same licence rather than trying to argue its way out of it.

Protocol notes also from the OpenRGB wiki.

If you fork this, the practical consequence is that your changes stay open too.

About

RGB control for ASUS Aura motherboards over USB HID. No kernel driver, no Armoury Crate, and no executable on disk.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages