Skip to content

Add --download-only mode to fetch firmware without a printer - #56

Merged
jcoffland merged 1 commit into
CauldronDevelopmentLLC:masterfrom
auto-charlie:download-only-mode
Aug 27, 2026
Merged

Add --download-only mode to fetch firmware without a printer#56
jcoffland merged 1 commit into
CauldronDevelopmentLLC:masterfrom
auto-charlie:download-only-mode

Conversation

@auto-charlie

Copy link
Copy Markdown

Summary

The vendor's fileUpdate endpoint resolves the firmware image from the model
name and SPEC alone, so the update image can be downloaded without a printer
being reachable on the network
. Today the script requires a printer IP,
always performs the SNMP walk, and aborts on any SNMP failure — even though
only the download half needs the printer at all.

Changes

  • Make the IP argument optional (nargs='?').
  • Add --spec / -S to provide the model's SPEC code directly (previously
    SPEC could only be read from the printer, and had no override even though
    --model and --category already had them).
  • Add --download-only to skip the upload phase; --test is unchanged.
  • When no IP is given, require --model and --spec (clear
    parser.error otherwise).
  • Surface VERSIONCHECK=2 (invalid model name / wrong SPEC) as an explicit
    error with a hint, instead of exiting silently with
    "No firmware update info path found".
  • Print LATESTVERSION from the server response (was in the payload,
    previously ignored).

Usage

./oh-brother.py --download-only -m "Brother HL-L2375DW series" -S <SPEC> -c MAIN -f 1.77

--model/--spec values can be read from a reachable printer via SNMP:

snmpget -v1 -c public <printer-ip> 1.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2

Notes / findings from testing against the vendor server

  • VERSIONCHECK semantics as observed: 0 = update available (PATH holds a
    plain-HTTP Akamai CDN URL, no auth), 1 = already up to date, 2 =
    invalid model name / wrong SPEC / missing device context.
  • The <VERSION> value in the request should be a real, lower installed
    version (e.g. 1.77); placeholder values like 0 or 1.0 get
    VERSIONCHECK=2.
  • On models with an NC-9300h network card the SNMP agent lives on the
    network card and expects community public; unknown communities are
    silently dropped, which looks like a timeout. (The --community option
    already exists upstream — this PR only documents the failure mode.)
  • README: new "Download firmware without the printer" section.

Compatibility

Backwards compatible: existing invocations with an IP behave exactly as
before. No dependency changes. Related open PRs (#44, #47) only touch the
README and do not conflict.

The vendor's fileUpdate endpoint resolves the firmware image from the
model name and SPEC alone, so the update image can be downloaded without
a printer being reachable on the network.

  * make the IP argument optional
  * add --spec so the model's SPEC code can be provided directly
  * add --download-only to skip the upload phase
  * validate that --model and --spec are present when no IP is given
  * surface VERSIONCHECK=2 (invalid model/SPEC) as a clear error and
    print LATESTVERSION from the server response
@jcoffland

Copy link
Copy Markdown
Member

I fixed these issues:

Blocking

No IP without --download-only is accepted and tries to upload to localhost. The validation only checks args.ip is None → require model+spec. It never requires --download-only. So ./oh-brother.py -m X -S Y -c MAIN -f 1.77 downloads the firmware, then falls into the upload path with args.ip = None. I checked: socket.getaddrinfo(None, 9100, proto=SOL_TCP) resolves to 127.0.0.1. Normally you get connection refused (caught, prints "aborted"), but if anything is listening on local 9100 — a raw JetDirect queue, CUPS socket backend — it gets a firmware blob. The -p path is worse: FTP(None) skips connect, then storbinary raises something not caught by the ConnectionRefusedError handler. Fix is one line: require --download-only when no IP, or imply it.

--category is silently required too but not validated. With no IP, firmInfo stays [] unless -c is given, so the download loop runs zero times and the script prints Success having done nothing. The README example passes -c MAIN -f 1.77, so the author knows — the check just doesn't cover it.

@jcoffland
jcoffland merged commit 54d303e into CauldronDevelopmentLLC:master Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants