Skip to content

nutdrv_qx: add OMRON BN150T support - #3554

Open
junkurihara wants to merge 12 commits into
networkupstools:masterfrom
junkurihara:feat/nutdrv-qx-omron-usb-subdriver
Open

nutdrv_qx: add OMRON BN150T support#3554
junkurihara wants to merge 12 commits into
networkupstools:masterfrom
junkurihara:feat/nutdrv-qx-omron-usb-subdriver

Conversation

@junkurihara

Copy link
Copy Markdown

Key Changes

  • Add an omron USB transport for OMRON BN150T (0590:00b7). It uses the device's 16-byte HID Output report size, rejects short writes, and bounds reply parsing and debug output by the number of bytes actually received.
  • Add an omron protocol subdriver based on the Q1 family, with OMRON-specific status handling, strict validation, extension queries, and automatic USB selection guarded by OMRON's vendor ID.
  • Publish the observed OMRON extension data, including battery charge, runtime and temperature, output frequency, firmware revisions, serial number, battery date, nominal power, and nominal battery voltage.
  • Add the OMRON forms of shutdown.stop, shutdown.return, and shutdown.stayoff, including the required An/Af auto-restart prologue and OK acknowledgement handling.
  • Document the protocol, transport, tested hardware scope, source provenance, and known limitations in the manual, NEWS, subdriver list, spell-check dictionary, and hardware compatibility list. Bump the nutdrv_qx driver version to 0.54.

Testing

  • Built with make -j2 -C drivers -W nutdrv_qx_omron.c nutdrv_qx: exit 0, no warnings.
  • Compiled nutdrv_qx_omron.c with -DTESTING -fsyntax-only and the project warning flags: exit 0, no warnings.
  • Ran git diff --check 26177060b: exit 0, no output.
  • Exercised protocol claiming, Q1 polling, and all eight OMRON extension queries on an OMRON BN150T over USB.
  • Verified explicit OMRON transport/protocol selection, protocol autodetection with the OMRON USB transport selected explicitly, and automatic selection of both transport and protocol with the device constrained to USB 0590:00b7. All three paths selected Omron 0.01; autodetection sent no other protocol probes.
  • Ran the driver continuously for about 62 hours. The archived debug-level-1 log contains 22,372 completed updates (5,605 full and 16,767 quick). Automated checks found no stale-data, NAK, timeout, short-transfer, overflow, USB-loss, or communication-loss/failure events.
  • On the completely unloaded BN150T, exercised shutdown.stop, shutdown.return, and shutdown.stayoff, including 120-second schedule/cancel checks and actual 12-second shutdowns. The observed command sequences and acknowledgements matched C, An then S.2/S02, and Af then Sf.2/Sf02 as expected.
  • Verified shutdown.return while on battery and automatic output recovery after utility restoration. Verified that shutdown.stayoff held the output off with utility present until manual front-panel recovery.
  • The UPS output was unloaded throughout: every output receptacle was empty and only the USB data cable was connected. OB was observed; LB, serial connections, other OMRON models, and other OMRON USB IDs were not tested.
  • After hardware testing, only comments and documentation were changed to record and clarify the observed results; driver logic remained unchanged.
  • Did not exercise shutdown.default, upsdrvctl shutdown, the driver -k path, or driver.killpower because of the separately reported shared-core failure-masking issue (drivers: shutdown.default can report success after upsdrv_shutdown() fails #3553).
  • Ran make distcheck: exit 0. This covered the distribution archive, an all-features configured build, checks, and normal and DESTDIR install/uninstall passes, including the new subdriver files.
  • Ran NUT's source non-ASCII check and an added-line byte scan over the complete PR diff: both passed with no findings.
  • Regenerated the USB metadata with tools/nut-usbinfo.pl. The BN150T appears in the generated udev, devd, hotplug and nut-scanner data. The tracked scripts/upower/95-upower-hid.hwdb is unchanged because that generator emits entries there only for usbhid-ups and apc_modbus devices.
  • Ran make spellcheck with aspell and its English dictionary: exit 0, with no findings after adding OMRON's, DSM, QNAP, and Synology to docs/nut.dict.

Related Tasks

Other

  • The protocol implementation was derived from OMRON-authored GPL driver version 1.00 distributed in the Synology DSM 7.3-86009 GPL sources and version 1.02 distributed in the QNAP QTS 5.2.3 GPL sources.
  • The device does not expose an independent readback of ups.start.auto. Automatic recovery after a non-cancelled An shutdown was physically verified, but preservation of the final An setting across C remains an inference rather than a device readback.
  • AI assistance from Claude and OpenAI Codex was used during implementation, review, test planning, and drafting. The human contributor reviewed the resulting code, documentation, hardware observations, and submission text and remains responsible for the contribution.

Below is a checklist from the PR template.

General points

  • Described the changes in the PR submission or a separate issue, e.g. known published or discovered protocols, applicable hardware (expected compatible and actually tested/developed against), limitations, etc.

  • There may be multiple commits in the PR, aligned and commented with a functional change. Notably, coding style changes better belong in a separate PR, but certainly in a dedicated commit to simplify reviews of "real" changes in the other commits. Similarly for typo fixes in comments or text documents.

  • Use of coding helper tools and AI should be disclosed in the commit or PR comments (it is interesting to know which ones do a decent job). As with other contributions, a human is responsible and thanked for the quality and content of the change, and is presumed to have the right to post that code to be published further under the project's license terms.

  • Especially with involvement of AI, including modern IDE coding aid, please be sure to revise that proposed code and documentation changes follow NUT code style guide -- this helps portability across the decades worth of supported systems. Notably, avoid Unicode characters where ASCII text is expected (C sources and headers, manual pages and other acsiidoc inputs). Particularly AI is keen on adding mdash characters instead of plain ASCII double-dash (which renders into the long dash where applicable).

  • Please star NUT on GitHub, this helps with sponsorships! ;)

Frequent "underwater rocks" for driver addition/update PRs

  • Revised existing driver families and added a sub-driver if applicable (nutdrv_qx, usbhid-ups...) or added a brand new driver in the other case.

  • Did not extend obsoleted drivers with new hardware support features (notably blazer and other single-device family drivers for Qx protocols, except the new nutdrv_qx which should cover them all).

  • For updated existing device drivers, bumped the DRIVER_VERSION macro or its equivalent.

  • For USB devices (HID or not), revised that the driver uses unique VID/PID combinations, or raised discussions when this is not the case (several vendors do use same interface chips for unrelated protocols).

  • For new USB devices, built and committed the changes for the scripts/upower/95-upower-hid.hwdb file

    -> N/A for this nutdrv_qx device: tools/nut-usbinfo.pl was run and produced no change to that file because its UPower output includes only usbhid-ups and apc_modbus devices.

  • Proposed NUT data mapping is aligned with existing docs/nut-names.txt file. If the device exposes useful data points not listed in the file, the experimental.* namespace can be used as documented there, and discussion should be raised on the NUT Developers mailing list to standardize the new concept.

  • Updated data/driver.list.in if applicable (new tested device info)

Frequent "underwater rocks" for general C code PRs

  • Did not "blindly assume" default integer type sizes and value ranges, structure layout and alignment in memory, endianness (layout of bytes and bits in memory for multi-byte numeric types), or use of generic int where language or libraries dictate the use of size_t (or ssize_t sometimes).

  • Progress and errors are handled with upsdebugx(), upslogx(), fatalx() and related methods, not with direct printf() or exit(). Similarly, NUT helpers are used for error-checked memory allocation and string operations (except where customized error handling is needed, such as unlocking device ports, etc.)

  • Coding style (including whitespace for indentations) follows precedent in the code of the file, and examples/guide in docs/developers.txt file.

  • For newly added files, the Makefile.am recipes were updated and the make distcheck target passes.

General documentation updates

  • Added a bullet point into NEWS.adoc, possibly also UPGRADING.adoc if there is something packagers or custom-build users should take into account (new driver categories, configuration options, dependencies...)

    -> UPGRADING.adoc is not applicable because this adds no dependency, incompatible configuration change, or packaging migration.

  • Updated docs/acknowledgements.txt (for vendor-backed device support)

    -> N/A: the implementation uses published GPL sources, but there was no vendor-backed contribution or claim of current official support.

  • Added or updated manual page information in docs/man/*.txt files and corresponding recipe lists in docs/man/Makefile.am for new pages

    -> The existing docs/man/nutdrv_qx.txt page was updated; no new manual page or recipe was added.

  • Passed make spellcheck, updated spell-checking dictionary in the docs/nut.dict file if needed (did not remove any words -- the make rule printout in case of changes suggests how to maintain it).

Additional work may be needed after posting this PR

  • Propose a PR for NUT DDL with detailed device data dumps from tests against real hardware (the more models, the better).

  • Address NUT CI farm build failures for the PR: testing on numerous platforms and toolkits can expose issues not seen on just one system.

  • Revise suggestions from LGTM.COM analysis about "new issues" with the changed codebase.

…orkupstools#3112]

Same transport as "ippon", except the control transfer carries a 16-byte HID
Output report, the size declared by the BN150T's report descriptor.

The send loop advances by the report size and rejects a short transfer, and
the reply length and both debug prints are bounded by the number of bytes
actually read.

Verified on 0590:00b7 with protocol=q1. Other OMRON models untested.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
…" subdriver [networkupstools#3112]

nut-usbinfo.pl generates the udev, hotplug and devd rules from the driver
device tables, so without a qx_usb_id[] row a packaged install grants the
device no permissions at all. The row needs a matching omron_subdriver():
qx_is_usb_device_supported() only reports SUPPORTED once a handler has
assigned subdriver_command.

Only the tested model is listed; the other OMRON IDs shipped by the vendor
driver are untested.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
…etworkupstools#3112]

The BN150T reports the third Q1 status bit as 1 continuously while on mains,
idle and unloaded, which "q1" turns into BYPASS - in NUT convention a state
where protection has been bypassed. OMRON's own driver does not evaluate that
bit at all: the block deciding between TRIM, BYPASS and BOOST is commented out
in its entirety, identically in the 1.00 and 1.02 vendor releases, while every
other status bit is handled. The row is dropped here rather than remapped,
since what the bit reports on this hardware is not known.

Instant commands the vendor driver does not implement are not registered:
test.battery.start, .deep, .quick and .stop have no T or TL command anywhere in
either vendor tree, the vendor's instant command set has no whole-load on/off
behind load.on and load.off, and beeper.toggle has no bare Q. Registering an
instant command tells clients the device can perform it.

The shutdown commands use OMRON's byte strings. The vendor sends "S<n>" and
"Sf<n>" with the delay in tenths of a minute below one minute and in whole
minutes above, and never appends the Megatec "R<mmmm>" return-delay field;
blazer_process_command() appends it to both as soon as ups.delay.start is
non-zero, and spells stay-off as "S<n>R0000" where OMRON has a distinct "Sf".
shutdown.return and shutdown.stayoff are also two transactions rather than one:
the auto-restart flag is set with "An" or "Af" first, as both the vendor driver
and docs/nut-names.txt require, and a failure there abandons the command instead
of powering the unit down with its restart behaviour unknown.

A command the UPS accepts is acknowledged with "OK", not the "ACK" that the
Megatec-derived subdrivers expect.

The claim is blazer_claim_light() gated on OMRON's USB vendor ID. Without the
gate this subdriver, which checks no more than "q1" does, would claim every
device the generic q1 fallback exists to serve. A serial-attached unit
therefore needs protocol=omron set explicitly.

The USB transport handler added earlier is renamed omron_usb_subdriver(),
because the subdriver_t structure takes the plain name; same treatment as
fabula_hunnox_subdriver().

Verified on 0590:00b7: polling reports OL without the spurious BYPASS. No
instant command has been sent to the hardware, so every command string here
rests on the vendor source alone. Other OMRON models untested.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
…s#3112]

Adds the OMRON BN150T to the compatibility list at support level 4, the
protocol to the nutdrv_qx man page, the subdriver source files to the
developer guide's list, and the two words the spell checker needs. The man
page states what was actually exercised: the polling path on one model over
USB. None of the shutdown commands has been sent to real hardware, so the
section says so rather than implying coverage.

ondelay is accepted for this protocol but does not reach the device:
OMRON's shutdown commands carry no return-delay field.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
Add BN150T extension queries, OMRON-specific status handling, and
shutdown command encoding and acknowledgement handling.

Prefer the vendor-ID-gated OMRON protocol during USB autodetection,
and document the tested scope and known limitations.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
…#3112]

Identify the OMRON-authored driver versions as 1.00 from the Synology
DSM 7.3-86009 GPL sources and 1.02 from the QNAP QTS 5.2.3 GPL
sources. Replace ambiguous references to vendor releases consistently
across the manual, NEWS, driver list and source comments.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
Improve the wording of the OMRON NEWS entry, manual section and source
comments. Clarify the tested scope, protocol behavior and source
provenance while keeping the private report details out of the public
documentation.

No driver logic is changed.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
…ools#3112]

Add DSM, OMRON's, QNAP and Synology to the spelling dictionary for
terms introduced by the OMRON documentation.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

A ZIP file with standard source tarball and another tarball with pre-built docs for commit c9be88e is temporarily available: NUT-tarballs-PR-3554.zip.

@AppVeyorBot

Copy link
Copy Markdown

Build nut 2.8.5.5018-master completed (commit 60e9165a5b by @junkurihara)

@junkurihara
junkurihara marked this pull request as ready for review August 3, 2026 11:32
Copilot AI review requested due to automatic review settings August 3, 2026 11:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the nutdrv_qx driver family with OMRON BN150T (USB 0590:00b7) support by adding a dedicated USB transport and a protocol subdriver derived from the Q1 family, plus the related documentation and metadata updates.

Changes:

  • Added an omron USB transport and omron protocol subdriver with OMRON-specific parsing, extensions, and shutdown command handling.
  • Registered the BN150T USB ID and enabled OMRON-gated autodetection/selection.
  • Updated documentation (manual, subdriver list, NEWS), spell-check dictionary, and driver list metadata; bumped driver version to 0.54.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
NEWS.adoc Announces the new OMRON BN150T support and summarizes behavior/limitations.
drivers/nutdrv_qx.c Bumps driver version; registers OMRON protocol/USB transport and USB VID:PID.
drivers/nutdrv_qx_omron.h Declares the new OMRON protocol subdriver interface.
drivers/nutdrv_qx_omron.c Implements the OMRON protocol subdriver, extensions, and shutdown commands.
drivers/Makefile.am Ensures the new OMRON subdriver sources/headers ship and build.
docs/nutdrv_qx-subdrivers.txt Adds the OMRON subdriver to the documented list.
docs/nut.dict Adds OMRON-related words to the spell-check dictionary.
docs/man/nutdrv_qx.txt Documents the new omron protocol and omron USB subdriver options and behavior.
data/driver.list.in Adds a BN150T entry with a recommended ups.conf configuration line.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/man/nutdrv_qx.txt Outdated
Comment thread drivers/nutdrv_qx.c Outdated
Describe the subdriver option as selecting a USB communication
subdriver so it also covers the OMRON HID transport.

Document that OMRON's non-standard SET_REPORT value 0x0002 is
intentional, matches both vendor driver releases, and was verified on
the BN150T. This changes only the literal's presentation, not its value
or behavior.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
@AppVeyorBot

Copy link
Copy Markdown

Build nut 2.8.5.5019-master completed (commit c15c0ac91c by @junkurihara)

Cast memchr() results explicitly to char * so C++ compatibility
checks do not reject the implicit conversion from void *.

Signed-off-by: Jun Kurihara <junkurihara@users.noreply.github.com>
@AppVeyorBot

Copy link
Copy Markdown

@AppVeyorBot

Copy link
Copy Markdown

@junkurihara

Copy link
Copy Markdown
Author

AppVeyor build 5023 appears to have hit the 60-minute job timeout while packaging the Windows artifacts. The build and install stages completed successfully, and the log ended during the final 7z command without a compiler or test error. Could someone please rerun it?

Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
@jimklimov jimklimov added enhancement USB Qx protocol driver Driver based on Megatec Q<number> such as new nutdrv_qx, or obsoleted blazer and some others labels Aug 4, 2026
@jimklimov jimklimov added this to the 2.8.6 milestone Aug 4, 2026
@jimklimov

Copy link
Copy Markdown
Member

Updated the spellcheck dictionary that some hosts complained about, this should re-build the Windows job as well.

Comment thread drivers/nutdrv_qx.c Dismissed
@AppVeyorBot

Copy link
Copy Markdown

Build nut 2.8.5.5025-master completed (commit 2d431f7d34 by @jimklimov)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Qx protocol driver Driver based on Megatec Q<number> such as new nutdrv_qx, or obsoleted blazer and some others USB

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Please add support for Omron UPS BN75T

5 participants