st-uhubm

A Python library, command-line tool, and web GUI for managing StarTech Managed Industrial USB Hubs on Linux.

Unofficial. This project is not affiliated with, endorsed by, or supported by StarTech.com. “StarTech” is a trademark of its respective owner. This package is a wrapper around StarTech’s own cusbi / cusba binary, which you must obtain separately (see Prerequisites). The binary is proprietary and is not redistributed here.


What is it

StarTech’s USB hubs expose a serial control channel (it enumerates as /dev/ttyUSB<n>) that lets user switches individual downstream ports on and off, reboot the hub, and persist a default port state. StarTech ships a control binary (cusbi on x86/AMD64, cusba on ARM) to drive that channel.

st-uhubm wraps that binary with:

  • a Python API for scripting and integration;

  • a ``stuhubm`` CLI with subcommands and optional JSON output;

  • an optional ``stuhubm-gui`` NiceGUI web GUI with port toggles.

Supported hardware

Model

Ports

Notes

5G7AINDRM-USB-A-HUB

7

7-port managed industrial hub

5G4AINDRM-USB-A-HUB

4

4-port managed industrial hub

Multiple hubs (including daisy-chained units) on one host are supported; each gets its own control port. Firmware v04 or newer is required.

This package controls hubs via StarTech’s serial protocol. It is not uhubctl and does not use USB per-port power switching (PPPS). The two are different projects.

Prerequisites

  1. Python 3.10 or newer.

  2. The StarTech binary, obtained from StarTech (see below). The correct binary for user’s CPU:

    • cusbi — Intel/AMD (x86-64) Linux hosts

    • cusba — ARM Linux hosts (e.g. Raspberry Pi, most SBCs)

  3. Root access. The binary opens the control tty directly and requires root. Run as root, use sudo, or grant access to the device via a udev rule / group membership (see Running without root).

Obtaining the vendor binary

This package does not redistribute StarTech’s proprietary binary. To obtain it:

  1. Go to the product page for your model (startech.com/5G7AINDRM-USB-A-HUB or startech.com/5G4AINDRM-USB-A-HUB) and open the Drivers & Downloads tab.

  2. Download the Linux package (a tarball such as cusbi-r1.02.tar.gz).

  3. Extract it and place the binary somewhere on your PATH, e.g.:

    tar xzf cusbi-r1.02.tar.gz
    sudo install -m 0755 cusbi /usr/local/bin/cusbi
    

    On ARM, do the same with cusba.

Verify the package can see it:

stuhubm health

Installation

Core library and CLI:

pip install st-uhubm

With the web GUI:

pip install "st-uhubm[gui]"

As an isolated tool (recommended for CLI-only use):

pipx install st-uhubm
# or
uv tool install st-uhubm

Installing the package does not install the StarTech binary, that is a separate manual step (see Prerequisites).

Quick start

# 1. Confirm the binary is working and list hubs
stuhubm health

# 2. Discover connected hubs
stuhubm list

# 3. Show the port states of a hub
stuhubm status /dev/ttyUSB0

# 4. Turn port 3 off, then back on
stuhubm off /dev/ttyUSB0 3
stuhubm on  /dev/ttyUSB0 3

# 5. Turn several ports off at once
stuhubm off /dev/ttyUSB0 3,4,5

# 6. Persist the current state so it survives a power cycle
stuhubm save /dev/ttyUSB0

If sudo prompts for a password on each call, see Running without root.

Core concepts

Control port. Each hub is addressed by the serial device it enumerates as. Pass exactly what stuhubm list reports for the hub, e.g. /dev/ttyUSB0.

Ports. Downstream USB-A ports are numbered from 1. User can act on a single port (3), a comma-separated list (3,4,5), or all ports (all).

Port state. Each port is simply on or off. stuhubm status reports the current state of every port.

Volatile vs. persistent. By default, changes are volatile — they apply immediately but are lost when the hub loses power or is reset. To make a state the power-on default, either:

  • pass --persist (writes each change straight to the hub’s flash), or

  • make your changes volatile, then run stuhubm save once to commit the current state to flash.

Prefer the second pattern for test rigs: it avoids a flash write on every toggle.

Password. Hubs ship with the default password pass. While the password is unchanged from default, you do not need to supply it. Once you set a custom password, every state-changing command must include it (via --password or the STUHUBM_PASSWORD environment variable). Passwords are at most 8 characters.

Command-line interface (stuhubm)

General form:

stuhubm [global options] <command> [arguments]

Commands

Command

Description

health

Check that the binary is present and list detected hubs

list

Discover hubs and show control port, model, serial, port count, firmware

status PORT

Show on/off state of every port on a hub

on PORT PORTS

Turn the given port(s) on

off PORT PORTS

Turn the given port(s) off

toggle PORT PORTS

Invert the given port(s)

all PORT on\|off

Turn all ports on or off

save PORT

Save current port states to flash (power-on default)

reset PORT

Hardware-reset the hub

restore PORT

Restore factory defaults (all ports on, password pass)

passwd PORT

Change the hub password (prompts interactively)

PORTS is a single port (3), a comma-separated list (3,4,5), or all.

Global options

Option

Env var

Default

Meaning

--binary PATH

STUHUBM_BINARY

cusbi

Control binary name or full path

--sudo / --no-sudo

STUHUBM_SUDO

--sudo

Run the binary via sudo

--password PW

STUHUBM_PASSWORD

(none)

Hub password, if changed from default

--persist

STUHUBM_PERSIST

off

Write changes to flash immediately

--json

off

Emit machine-readable JSON instead of text

--timeout N

10

Per-command timeout in seconds

--verbose

off

Print the exact binary invocation

Examples

# Use the ARM binary at a specific path, no sudo (already root)
stuhubm --binary /opt/startech/cusba --no-sudo list

# JSON output for scripting
stuhubm --json status /dev/ttyUSB0
# -> {"port": "/dev/ttyUSB0", "model": "7-port Managed USB Hub",
#     "serial": "00020000149E", "firmware": "v04", "n_ports": 7,
#     "states": {"1": true, "2": true, "3": false, ...}}

# Make port 1 the only powered port and persist it
stuhubm all /dev/ttyUSB0 off
stuhubm on  /dev/ttyUSB0 1
stuhubm save /dev/ttyUSB0

# Power-cycle a device on port 4 (off, wait, on)
stuhubm off /dev/ttyUSB0 4 && sleep 3 && stuhubm on /dev/ttyUSB0 4

Run any stuhubm command with --verbose to print the exact invocation.

Exit codes

Code

Meaning

0

Success

1

Command failed (non-zero from the binary, parse error)

2

Usage error (bad arguments)

3

Binary not found

4

Timeout

Web GUI (stuhubm-gui)

Requires the [gui] extra.

stuhubm-gui                       # serves on http://localhost:8080
stuhubm-gui --port 9000           # custom port
stuhubm-gui --native              # desktop window (requires pywebview)

The GUI provides hub discovery, a switch per port reflecting live state, all-on/all-off, save-to-flash, reset, restore, and a password-change dialog — plus a console pane showing the exact binary invocation and its output for every action. Settings (binary path, sudo, password, persist) are editable in-page. Each browser tab is independent, and a process-wide lock serialize the actual hardware calls so two tabs never issue overlapping commands.

The GUI is just a convenience layer; everything it does is also available through the CLI and the Python API.

Python API

The library mirrors the CLI. A short example:

from st_uhubm import HubManager, discover

# Convenience: discover with default settings (cusbi, sudo on)
for hub in discover():
    print(hub.port, hub.model, hub.firmware, hub.states)

# Explicit configuration
mgr = HubManager(binary="cusba", use_sudo=False, password="s3cret")
hub = mgr.hub("/dev/ttyUSB0")            # read one known hub

hub.set_port(3, on=False)                # volatile by default
hub.set_port(3, on=True, persist=True)   # write straight to flash
hub.set_all(on=False)
hub.toggle(2)
hub.save()                               # commit current states to flash
hub.refresh()                            # re-read live state
print(hub.is_on(3))

The parsers are also importable for custom integrations or for testing the tricky logic without hardware:

from st_uhubm.cli_backend import parse_query_all, parse_hub_info

parse_query_all("0002,/dev/ttyUSB0,/dev/ttyUSB1")
parse_hub_info("FBFFFFFF,7,v04,00020000149E,7-port Managed USB Hub")

The port-state bitmap is 32 bits, little-endian by byte; bit n−1 corresponds to port n (1 = on).

Further details: every class, method, parser, and exception are in the API reference, generated directly from the source.

Configuration

Settings resolve in this order (later overrides earlier):

  1. Built-in defaults

  2. Environment variables (STUHUBM_BINARY, STUHUBM_SUDO, STUHUBM_PASSWORD, STUHUBM_PERSIST)

  3. Command-line flags (CLI) or HubManager arguments (API)

This makes CI configuration straightforward: set the environment once, then call plain commands.

Use in CI automation

Typical pattern: power-cycle a DUT between stages:

# Example CI step (any runner with the hub attached)
env:
  STUHUBM_BINARY: /opt/startech/cusbi
  STUHUBM_SUDO: "1"
steps:
  - run: stuhubm health
  - run: stuhubm off /dev/ttyUSB0 4         # cut power to the DUT
  - run: sleep 3
  - run: stuhubm on  /dev/ttyUSB0 4         # power back on
  - run: stuhubm --json status /dev/ttyUSB0 # record final state

For unattended use, configure passwordless sudo scoped to the binary so calls never block on a prompt (see below), or run the job as root.

Because the parsing functions are pure text processing, user can cover the tricky logic in their own unit tests without any hardware attached:

from st_uhubm.cli_backend import parse_hub_info

def test_port3_off():
    n, states, fw, serial, model = parse_hub_info(
        "FBFFFFFF,7,v04,00020000149E,7-port Managed USB Hub")
    assert states[3] is False
    assert n == 7

Troubleshooting

Binary not found

stuhubm health reports the binary cannot be located. Confirm the file is on PATH or pass --binary /full/path/to/cusbi. On ARM hosts, ensure you are using cusba, not cusbi.

No hubs detected

  • Check the cable :)

  • Confirm the device node exists: ls /dev/ttyUSB*.

  • Make sure the hub is externally powered if your model/setup requires it.

  • Try stuhubm --verbose list to see the raw discovery output.

Permission denied / sudo prompts

The binary needs root to open the control tty.

Running without root

To avoid sudo entirely, grant your user access to the control device with a udev rule. Identify the device’s vendor/product, then add (example):

# /etc/udev/rules.d/99-startech-hub.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="XXXX", ATTRS{idProduct}=="YYYY", MODE="0660", GROUP="dialout"

Reload rules (sudo udevadm control --reload && sudo udevadm trigger), add your user to the dialout group, re-login, and run with --no-sudo.

Alternatively, allow passwordless sudo for just the binary in /etc/sudoers.d/:

youruser ALL=(root) NOPASSWD: /usr/local/bin/cusbi

A port powers back on by itself

Some kernel drivers re-initialize a device shortly after a state change. If a port you turned off comes back, persist the desired state (--persist or stuhubm save) so the hub re-applies it, and verify with stuhubm status.

Forgotten password

If you set a password and lost it, use the physical recovery procedure in the StarTech hardware manual (power off, hold the button, power on) to restore factory defaults, which resets the password to pass.

Caveats

  • Flash wear. --persist (the /F path) writes flash on every change. For frequently-toggled test rigs, make changes volatile and save once.

  • Power-cycling live devices. Cutting a port drops the device immediately. Ensure nothing is mid-write (e.g. mass storage) before switching a port off.

  • Root. The binary runs with elevated privileges; review the --verbose output if you need to audit exactly what is executed.

  • Compatibility. This package targets firmware v04+ output of the StarTech binary. If StarTech changes the binary’s output format in a future revision, parsing may need updating; stuhubm --verbose and the exposed parser functions make this easy to diagnose.

Support

The public API is everything exported from the top-level st_uhubm package; internal module layout may change between minor versions.

This is community software provided as-is. For issues with the hub hardware or the StarTech binary itself, contact StarTech support. Those are outside the scope of this package.

License

This package is released under the GNU General Public License, version 2 or later (GPL-2.0-or-later). See the LICENSE file for the version 2 text.

It does not include or redistribute any StarTech software; the cusbi / cusba binary is the property of StarTech.com and is governed by StarTech’s own license terms. The GPL applies only to this project’s own code.