networkupstools / nut

The Network UPS Tools repository. UPS management protocol Informational RFC 9271 published by IETF at https://www.rfc-editor.org/info/rfc9271 Please star NUT on GitHub, this helps with sponsorships!
https://networkupstools.org/
Other
2.13k stars 355 forks source link

USB scan requirements for nut-scanner #1884

Open bremenpl opened 1 year ago

bremenpl commented 1 year ago

Hello, I am developing a custom UPS device that is supposed to be accessed by the usbhid-ups interface. I am uncertain yet how to configure my device for NUT to consider it a UPS device. I am trying to start with nut-scanner tool to find my device with -U option. I am going through the source code, but cannot figure out what parameter is crucial for this program to consider a specific HID device to be NUT enabled.

I would appreciate all feedback!

jimklimov commented 1 year ago

I'd wager an educated guess that https://github.com/networkupstools/nut/blob/master/tools/nut-scanner/scan_usb.c#L217 is_usb_device_supported() is the key. Since different devices often require customized sub-drivers for practical support, we have to reactively map the Vendor+Product IDs to them. This relies on a brave assumption that vendors do diligently and uniquely name their products in USB metadata, and that product capabilities remain stable over time.

For example,

Some sub-drivers like https://github.com/networkupstools/nut/blob/master/drivers/mge-hid.c support several vendors (e.g. same OEM for different brands), that is not a problem. Even several drivers for same vendors (but different products): https://github.com/networkupstools/nut/blob/master/drivers/tripplite-hid.c overlaps with mge-hid like this. And it is not limited to usbhid-ups subdrivers: ones for nutdrv_qx (megatec) and some older standalone drivers also support this scheme.

These VID:PID pairs are then parsed and generated into many artifacts, including udev rules and similar data for other frameworks (such device nodes, and only they, should become owned by NUT run-time user account), and the nut-scanner headers - see https://github.com/networkupstools/nut/blob/master/tools/nut-usbinfo.pl

So if you assume your newly developed device should be supported by an existing (or newly added/cloned) subdriver, add its identifiers into one source file and regenerate the project (./autogen.sh && ./configure ... && make or just ./ci_build.sh) and they should become supported.

jimklimov commented 1 year ago

Perhaps https://github.com/networkupstools/nut/blob/master/docs/hid-subdrivers.txt should mention this, even if by just referring to https://github.com/networkupstools/nut/blob/master/docs/new-drivers.txt#L539 chapter, if it does not yet.

bremenpl commented 1 year ago

Perhaps https://github.com/networkupstools/nut/blob/master/docs/hid-subdrivers.txt should mention this, even if by just referring to https://github.com/networkupstools/nut/blob/master/docs/new-drivers.txt#L539 chapter, if it does not yet.

Hi @jimklimov , thank you a lot for an elaborated answer. So I will try to manually add the support and rebuild the software. But that is just the nut-scanner, or is it NUT in general? Assuming in the ups.conf I will add the driver "usbhid-ups", there is still the desc parameter- this I guess has to be on supported list? So then the driver + decs is a key to target my specific device? Especially since I could have couple devices connected at once (maybe ours + Eaton or other config).

Thing is for us right now that we are running the product on a rented VID:PID from the MCU manufacturer (for the development and testing time). So it would make no sense for the whole NUT to support that pair.

jimklimov commented 1 year ago

desc is for users, not relevant nor required for matching. You may want to specify some others though (text product, vendor, serial, bus, device) if you can set up a recognized and unique set to differentiate devices.

jimklimov commented 1 year ago

Normally if an usbhid-ups subdriver supports your fancy new VID:PID (reported by your USB chip, and if it is unique to your devices), then to match one device automatically just the driver=usbhid-ups and port=auto should be sufficient (and required) in the device config section.

bremenpl commented 1 year ago

desc is for users, not relevant nor required for matching. You may want to specify some others though (text product, vendor, serial, bus, device) if you can set up a recognized and unique set to differentiate devices.

Ok, understood, thank you. But does this mean that even if my device is not supported by nut-scanner due to unknown vid:pid, it will still be communicated with if I set all relevant parameters in ups.conf?

bremenpl commented 1 year ago

Normally if an usbhid-ups subdriver supports your fancy new VID:PID (reported by your USB chip, and if it is unique to your devices),

Thing is I don't suppose it does. This is just a generic HID device with unsupported VID:PID by nut.

jimklimov commented 1 year ago

does this mean that even if my device is not supported by nut-scanner due to unknown vid:pid, it will still be communicated with if I set all relevant parameters in ups.conf?

Not sure, may depend on the driver. I think nutdrv_qx has options to explicitly tune the subdriver and protocol dialect, so can specify "arbitrary" VID:PID while people lock-pick the best support for their yet-unknown device. Not sure if usbhid-ups is currently that flexible, or if it relies more on known identifiers in subdriver source code to deduce the code-path for available support (with hard-coded set of codepaths for a binary build, effectively); I had an issue logged for that to research more and improve framework feature parity if needed, but did not have time to look more at that yet.

I don't suppose it does. This is just a generic HID device with unsupported VID:PID by nut.

In that case try adding the identifiers (following markup format) to an existing subdriver that you expect could handle the reports from your device, and regenerate/rebuild your copy of NUT to experiment with it further. You can run the driver for tests in data-dump mode, so it prints the discovered values and exits, right from the build workspace (here as root to not worry about permissions to access un-occupied device nodes), iterating like this as you edit the sources (after initial autogen + configure):

:; (cd drivers && make -j 4) && \
    sudo ./drivers/usbhid-ups -a myups -u root -x port=auto -DDDDDD -d1 \
    # any more args needed for your deployment?

FWIW, at some point recently I began documenting use of IDEs like NetBeans and Visual Studio Code (+MSYS2 on Windows) to debug NUT programs - stepping through code, seeing variables, evaluating expressions not yet coded into the programs... Did not get far with the docs yet, but can say it does work on several platforms so may help in your development particularly. Note that you would probably need to feed ./drivers/.libs/usbhid-ups binary to the debugger, if the drivers/usbhid-ups is a libtool wrapper program or even script.

bremenpl commented 1 year ago

Thanks for the explanation,

I must admit this is more complicated than I thought. Wondering whether every vendor/ developer wanting to add their device to NUT goes this path...

But more or less I know what I am standing on. I guess ill start with trying to convince nut-scanner program to talk to me first. After that I'll move to nut.

I went through the links you provided, but maybe I have missed that- is there any document specifying exactly what nut sends (HID interface vise) to the eventual device (set/ read report, pages, id's etc) to talk to it? There is the "Universal Serial Bus Usage Tables for HID Power Devices", but I cannot get any concrete info out of it- it's a bit fuzzy (many options, nothing is strictly told).

What I am looking for is something like Modbus protocol description (very exact) + a register map. I grasp that here it might be more complicated, but its just to give you an idea.

bremenpl commented 1 year ago

@jimklimov also, just to provide some confirmation- I have a reference Eaton 3S 550D device. It works out of the box. What I did for testing, is copying its VID and PID to my program. Nut scanner picked it up:

lukasz@vm:~$ nut-scanner -U
Neon library not found. XML search disabled.
IPMI library not found. IPMI search disabled.
Scanning USB bus.
[nutdev1]
    driver = "usbhid-ups"
    port = "auto"
    vendorid = "0463"
    productid = "FFFF"
    bus = "003"
[nutdev2]
    driver = "usbhid-ups"
    port = "auto"
    vendorid = "0463"
    productid = "FFFF"
    bus = "003"

So it is indeed about being registered VID:PID on a list supported by NUT.

jimklimov commented 1 year ago

BTW, looking at the nut-scanner output, it does not seem that you are using a current master-branch build, right? I'd expect it to also show a device=... line, and a commented-away BCD version (reserved for future use). Particularly it would be useful here, as your two devices seem currently identical by the fields present...

bremenpl commented 1 year ago

No, this was a whatever version available via ubuntu package manager. I will build from source and re-check. Thanks.