Skip to main content

USB Extender Node Rename Migration Guide

A guide for third-party integrations (Q-SYS, AMX, Crestron, custom) updating to the new USB_EXTENDER node and its restructured fields.

Summary of changes
  • The USB-extender node type in get device responses is renamed from USB_ICRON to USB_EXTENDER.
  • Several fields inside the node were also restructured, so this is not a pure rename. Notably, the single-peer scalars (peer_mac_address, peer_device_id) became a peers[] array, and configuration.extender_type became configuration.role.
  • The rename is not limited to the node. The usb_icron capability flag, the USB_ICRON routing stream-type literal (used with switch / stop), the usb_icron subscription type, and the icron command were all renamed to their usb_extender / USB_EXTENDER equivalents.
  • Version timeline: API 3.8 added the usb_extender forms and deprecated the usb_icron forms, emitting both nodes in the same get device response during the transition. API 3.9 removed the usb_icron node, capability, stream type, subscription type, and the icron command entirely. A 3.9 Control Server only understands the usb_extender forms.
  • Recommended approach: prefer the usb_extender forms when present, falling back to the usb_icron forms only for Control Servers older than 3.8.

Reason for the change

The SDVoE Control Server has generalized its USB-extender abstraction so that it can describe extenders built on chipsets other than Icron in the future. The historical USB_ICRON node was conceptually tied to one specific extender family; the new USB_EXTENDER node is engine-agnostic.

The underlying hardware behavior on currently shipping DVIGear products is unchanged. This is a schema change in the Control Server's reporting and configuration model.

API 3.8 Control Server builds emit both the legacy USB_ICRON node and the new USB_EXTENDER node side-by-side in every get device response, with the legacy forms deprecated but still present. API 3.9 removed the legacy USB_ICRON forms entirely, so those builds emit only USB_EXTENDER. Builds older than 3.8 emit only USB_ICRON. An integration must tolerate all three states for the life of the deployment: old-only, both, and new-only.

Field-by-field changes

Old (USB_ICRON)New (USB_EXTENDER)Change
type = "USB_ICRON"type = "USB_EXTENDER"Renamed: node type identifier.
configuration.extender_type ("LOCAL" | "REMOTE")configuration.role ("LOCAL" | "REMOTE")Renamed: same values, new key.
configuration.program_modeconfiguration.program_modeUnchanged.
configuration.rs232_portconfiguration.rs232_portUnchanged.
configuration.peers (array)New: configurable peer list (for LEX devices).
status.chip_presentstatus.chip_presentUnchanged.
status.mac_addressstatus.mac_addressUnchanged.
status.reachablestatus.reachableUnchanged.
status.revisionstatus.revisionUnchanged.
status.ip_modestatus.ip_modeUnchanged.
status.ip_addressstatus.ip_addressUnchanged.
status.peer_mac_address (string)(see status.peers[])Removed: read from first entry of status.peers[] for the single-peer case.
status.peer_device_id (string)(see status.peers[])Removed: read from first entry of status.peers[] for the single-peer case.
status.sui_peers (array)status.peers (array)Renamed: each entry still has mac_address and device_id.
status.link_status_supportstatus.link_status_supportUnchanged.
status.linked (boolean)Removed: no direct replacement. Check status.peers[] non-empty plus per-peer state if you relied on this.
status.sui_enabledstatus.sui_enabledUnchanged.
status.chipset_type (e.g. "ICRON")New: identifies the underlying extender chipset ("ICRON" on current hardware).
status.role (duplicates configuration)New: convenience copy of configuration.role.

JSON shape

Before (legacy USB_ICRON node)

{
"type": "USB_ICRON",
"index": 0,
"configuration": {
"extender_type": "LOCAL",
"program_mode": "NONE",
"rs232_port": 0
},
"status": {
"chip_present": true,
"mac_address": "6cdffb011b10",
"reachable": true,
"revision": "1.9.4",
"ip_mode": "DHCP",
"ip_address": "192.168.1.132",
"peer_mac_address": "",
"peer_device_id": "",
"link_status_support": true,
"linked": false,
"sui_enabled": true,
"sui_peers": []
},
"inputs": []
}

After (new USB_EXTENDER node)

{
"type": "USB_EXTENDER",
"index": 0,
"configuration": {
"role": "LOCAL",
"program_mode": "NONE",
"rs232_port": 0,
"peers": []
},
"status": {
"chipset_type": "ICRON",
"chip_present": true,
"mac_address": "6cdffb011b10",
"reachable": true,
"revision": "1.9.4",
"ip_mode": "DHCP",
"ip_address": "192.168.1.132",
"link_status_support": true,
"sui_enabled": true,
"peers": [],
"role": "LOCAL"
},
"inputs": []
}
Dual emission during transition

When parsing the nodes[] array returned by get device, expect both a USB_ICRON node and a USB_EXTENDER node to appear in the same response on modern Control Servers. They describe the same underlying hardware extender. Pick one and parse it consistently, preferring USB_EXTENDER when present.

Companion renames (beyond the node)

The node rename came with matching renames across the rest of the USB-extender surface. As with the node, the usb_extender forms were added in API 3.8 and the usb_icron forms were removed in API 3.9.

Old form (≤ 3.8)New form (3.8+)Notes
capabilities.usb_icron (Boolean)capabilities.usb_extender (Boolean)Indicates the device has a USB 2.0 extender.
USB_ICRON stream-type literal (switch / stop)USB_EXTENDER stream-type literale.g. switch <src>:USB_EXTENDER:0 <dst>:0, stop <dev> USB_EXTENDER 0.
usb_icron subscription typeusb_extender subscription typeUsed wherever subscriptions are enumerated.
icron <target> <pair|unpair|reset> … commandusb_extender <target> <pair|unpair|reset> … commandSame subcommands and argument order; only the verb changed. Address devices by their BlueRiver device_id.
API 3.9 removes the legacy forms

On a 3.9 Control Server the icron command, the usb_icron capability flag, and the USB_ICRON stream-type and subscription type no longer exist. Using them returns an error (INVALID_COMMAND / ILLEGAL_ARGUMENT). Send the usb_extender forms instead. They are also accepted by 3.8 builds, so prefer them whenever the device reports a USB_EXTENDER node.

Unchanged behaviour

AreaStatus
USB extender hardware behavior, IP mode, RS-232 programming, etc.Unchanged. This is a Control Server reporting and command-naming change only.
Pairing semantics (LEX ↔ REX, SUI multi-pairing limits)Unchanged. Only the command verb and identifiers changed.

Implement a small accessor layer that hides the dual-shape complexity from the rest of your integration. Three accessors cover the vast majority of usage: locate the node, read the role, read the peers.

Pseudo-code

// 1. Locate the USB extender node, preferring the new node type.
function findUsbExtenderNode(device) {
const nodes = device.nodes || [];
return nodes.find(n => n.type === "USB_EXTENDER")
|| nodes.find(n => n.type === "USB_ICRON")
|| null;
}

// 2. Read the role ("LOCAL" / "REMOTE") with field-name fallback.
function getExtenderRole(node) {
if (!node) return "";
return node.configuration.role
|| node.configuration.extender_type
|| "";
}

// 3. Read the peer list as a normalized array of {mac_address, device_id}.
function getExtenderPeers(node) {
if (!node) return [];
if (Array.isArray(node.status.peers)) return node.status.peers;
if (Array.isArray(node.status.sui_peers)) return node.status.sui_peers;
// Old scalar fields: synthesize a one-entry array if both are populated.
const mac = node.status.peer_mac_address || "";
const did = node.status.peer_device_id || "";
return (mac && did) ? [{ mac_address: mac, device_id: did }] : [];
}

Setting the role (LEX vs REX)

If your integration writes the role via set <device_id> property <path> <value>, the property path also changes. Use the path that matches the node the Control Server emits:

# Old form (still accepted by old Control Server builds):
set <device_id> property nodes[USB_ICRON:0].configuration.extender_type LOCAL

# New form (accepted by Control Server builds that emit USB_EXTENDER):
set <device_id> property nodes[USB_EXTENDER:0].configuration.role LOCAL

A safe pattern is to issue the set against whichever node type was present in the most recent get device response for that device.

Q-SYS integration notes

If your Q-SYS plugin is parsing the JSON response of get device in Lua (e.g. via rapidjson or the Q-SYS JSON library), the porting work is mechanical:

  • Wherever you currently iterate device.nodes looking for type == "USB_ICRON", accept "USB_EXTENDER" as well, and prefer it.
  • Wherever you index into nodes[USB_ICRON:0].configuration.extender_type, read configuration.role first, falling back to configuration.extender_type.
  • Wherever you read status.peer_mac_address or status.peer_device_id directly, switch to reading the first element of status.peers, falling back to status.sui_peers, falling back to the scalar fields.
  • Routing and pairing commands do need to change on API 3.9: use the USB_EXTENDER stream-type literal with switch / stop, and the usb_extender command in place of the removed icron command (same subcommands, only the verb changed). Address devices by their BlueRiver device_id, not the extender chip MAC.

Verification checklist

  • Against a Control Server that emits the new USB_EXTENDER node, your accessor returns the correct role and peers.
  • Against a Control Server that emits only the legacy USB_ICRON node, your accessor still returns the correct role and peers.
  • Against a Control Server that emits both nodes in the same response, your accessor consistently uses one (recommended: USB_EXTENDER) and does not double-count peers.
  • Pairing a LEX/REX via your existing pair/unpair flow continues to work end-to-end.
  • On API 3.9, routing/pairing uses the usb_extender command and the USB_EXTENDER stream literal addressed by device_id; the legacy icron / USB_ICRON forms return errors and are only valid on Control Servers older than 3.9.
  • If you display the extender peer count in your UI, it stays consistent across a Control Server upgrade.

Questions or issues

If your integration relies on a field not covered above, or you observe a Control Server response that doesn't fit either shape, please reach out to DVIGear support with a captured get device response and a description of the integration scenario. We will extend this guide as needed.

See also