What is a Plugin?
SignalRGB uses custom USB plugins, authored in JavaScript, to support third-party RGB devices. If you have a device that isn’t yet supported you can write your own plugin for it. If you have an Arduino or other open-source microcontroller, you can also create a plugin for SignalRGB to communicate with it for fully DIY RGB solutions.
Our currently released plugins are all open-source and available on the public SignalRGB plugins repository. If you’ve created something that others can use, feel free to issue a pull request or reach out to our official support!
How a Plugin Works
Section titled “How a Plugin Works”A plugin is a single JavaScript file that SignalRGB loads for a specific USB device. It does two things:
- Describes the device — exports that tell SignalRGB the device’s name, IDs, LED layout, and communication protocol.
- Drives the device — lifecycle functions that SignalRGB calls to initialize the device, send colors each frame, and clean up on exit.
Plugin Structure
Section titled “Plugin Structure”Every plugin follows the same basic shape:
// ── Device identity ──────────────────────────────────────export function Name() { return "My Device"; }export function Publisher() { return "Your Name"; }export function VendorId() { return 0x1234; }export function ProductId() { return 0x5678; }export function Type() { return "hid"; }
// ── Canvas size and LED layout ────────────────────────────export function Size() { return [7, 3]; }export function LedNames() { return ["Logo", "Left", "Right"]; }export function LedPositions() { return [[3,1], [0,1], [6,1]]; }
// ── Lifecycle ─────────────────────────────────────────────export function Initialize() { // Called once when the device connects or streaming is enabled. // Send any initialization packets the device needs here. SendInitPacket();}
export function Render() { // Called every frame (~30ms by default). // Read colors from the canvas and send them to the device. SendColors();}
export function Shutdown() { // Called when SignalRGB exits or streaming is disabled. // Return the device to hardware mode here if needed. SetHardwareControl();}Lifecycle
Section titled “Lifecycle”Initialize
Section titled “Initialize”Called once when a device connects or reconnects, and whenever the streaming toggle is enabled on the device’s config page. Use it for any startup work: switching the device into software control mode, sending firmware handshakes, reading saved configuration, etc.
If any conflicting processes are running, initialization waits until they close or the user bypasses the check.
Render
Section titled “Render”The render loop is the core of the plugin. SignalRGB calls Render() every frame. The sequence each frame is:
- User settings are updated
- Colors are pulled from the canvas into the device’s pixel buffer
- Any
on*Changedcallbacks fire (in the order changes occurred) Render()is called
Inside Render() you call device.color(x, y) to read pixel colors and send them to the hardware. The default frame interval is 30ms.
Shutdown
Section titled “Shutdown”Called when SignalRGB exits gracefully or the streaming toggle is disabled. If your device has a hardware lighting mode, restore it here so the user’s LEDs don’t go dark when SignalRGB isn’t running.
on*Changed Callbacks
Section titled “on*Changed Callbacks”User-facing controls (see ControllableParameters) can each have a matching callback that fires before Render() whenever the user changes that setting. Name the function on[propertyName]Changed() — it’s case-sensitive.
// ControllableParameters entry:{ "property": "dpi1", "label": "DPI", "type": "number", "min": "200", "max": "18000", "default": "800" }
// Matching callback:export function ondpi1Changed() { setDpi(dpi1);}The built-in onBrightnessChanged() callback fires when the device’s main brightness slider is moved.
Defining the Device
Section titled “Defining the Device”These exports tell SignalRGB everything it needs to know about the device before it connects.
Name and Publisher
Section titled “Name and Publisher”Displayed in the SignalRGB UI.
export function Name() { return "Corsair K70 RGB"; }export function Publisher() { return "YourName"; }VendorId and ProductId
Section titled “VendorId and ProductId”The USB IDs SignalRGB uses to find the device on the system. Must be exact hex values. If your plugin isn’t appearing, a mismatched ID is the most likely cause.
export function VendorId() { return 0x1B1C; }export function ProductId() { return 0x1B49; }Sets the USB communication protocol. Defaults to "hid" if not exported. See Determining Device Type for the full list and how to choose.
export function Type() { return "hid"; } // HID (most devices)export function Type() { return "rawusb"; } // Raw USB / libusbexport function Type() { return "hybrid"; } // Both simultaneouslyexport function Type() { return "serial"; } // COM portSize, LedNames, and LedPositions
Section titled “Size, LedNames, and LedPositions”These three exports together define how the device appears on the canvas.
Size()— the bounding box[width, height]of the device’s pixel grid.device.color()can only sample coordinates within this box.LedNames()— an ordered array of LED names. Names should follow the supported key names list to enable keypress effects and LED painting.LedPositions()— an ordered array of[x, y]positions within the Size grid, one per LED, matching the order of LedNames.
export function Size() { return [7, 3]; }export function LedNames() { return ["Logo", "Left Side", "Right Side"]; }export function LedPositions() { return [[3, 1], [0, 1], [6, 1]]; }Validate
Section titled “Validate”Controls which USB endpoints SignalRGB opens. Every discovered endpoint is passed to Validate() — return true to open it, false to skip it. You can open multiple endpoints and switch between them at runtime with device.set_endpoint().
export function Validate(endpoint) { return endpoint.interface === 2 && endpoint.usage_page === 0xFF00;}See Selecting Endpoints for how to find the right values.
ControllableParameters
Section titled “ControllableParameters”Returns an array of user-facing settings that appear on the device’s config page. See User Controls for the full schema.
export function ControllableParameters() { return [ { "property": "LightingMode", "label": "Lighting Mode", "type": "combobox", "values": ["Software", "Hardware"], "default": "Software" }, { "property": "DPILevel", "label": "DPI", "type": "number", "min": "200", "max": "18000", "step": "50", "default": "800" } ];}ConflictingProcesses
Section titled “ConflictingProcesses”A list of exe names that conflict with this plugin. SignalRGB will not initialize while any of these are running. Names must match exactly.
export function ConflictingProcesses() { return ["iCUE.exe", "CorsairHID.exe"];}ImageUrl
Section titled “ImageUrl”The URL of the device’s image shown in the SignalRGB UI. Standard size is 1024×1024 with a live area of 920×920.
export function ImageUrl() { return "https://..."; }Next Steps
Section titled “Next Steps”- Plugin Template — a ready-to-edit starting point
- Writes and Reads — sending data to the device
- Determining Device Type — choosing the right protocol
- Selecting Endpoints — finding the right USB endpoint
- User Controls — adding settings to the device config page
- Modules and Features — battery, keyboard/mouse injection, network, and more