Skip to content

Experimental libwinhid backend for usbhid-ups (Windows only)#3335

Open
MysteryDove wants to merge 5 commits intonetworkupstools:masterfrom
MysteryDove:experimental_libwinhid
Open

Experimental libwinhid backend for usbhid-ups (Windows only)#3335
MysteryDove wants to merge 5 commits intonetworkupstools:masterfrom
MysteryDove:experimental_libwinhid

Conversation

@MysteryDove
Copy link
Contributor

@MysteryDove MysteryDove commented Mar 3, 2026

Proof of concept stage

While working on my own STM32 project to simulate USB HID UPS, I've made a python script to read windows HID API and it works as expected. So I'm looking for some ways to port that so I can use nut on windows without any additional drivers.

I'm working on an experimental, native Windows HID backend (libwinhid) for the usbhid-ups driver to try avoid the libusb's problem of fetching raw bytes from Windows system claimed HID UPS device. So that no extra driver like WinUSB or Zadig is needed.

For enumeration I'm using setupapi.dll

For HID device:

  • HidD_GetPreparsedData and HidP_GetCaps to read collection mappings.
  • HidD_GetFeature / HidD_SetFeature to handle feature reports.

The current implementation is kinda messy, takes Windows capabilities to reconstruct a descriptor, route back to Parse_ReportDesc() to parse that, And continue the remaining logic as untouched, but few functions are introduced here to deal with improper HID descriptor Parsing. The code is not cleaned and completly tested yet, but it's working now with apchid subdriver with correct data reading now.

To use current updated code, pollonly and experimentalhid(newly added) is required:

[usbups]

    experimentalhid

    pollonly

    driver = usbhid-ups

    port = auto

Looking for test result and idea how to improve this to make the code works better

@AppVeyorBot
Copy link

@jimklimov
Copy link
Member

This looks promising, thanks! The indentation is a bit jumpy when I looked at it in GitHub WebUI (tabs vs spaces?) and the two aliases for exp(e)rimentalhid look odd (IMHO one (use)winhid would be more to the point).

Notably, does the resulting program need linking with libusb{0,1}.c if you use a different backend? Is the LibUSB "proper" still used here?

Also, I wonder if the methods you've added to usbhid-ups.c driver sources make more sense in e.g. libhid.c so other USB-capable drivers could take advantage of them eventually?

@MysteryDove
Copy link
Contributor Author

This looks promising, thanks! The indentation is a bit jumpy when I looked at it in GitHub WebUI (tabs vs spaces?) and the two aliases for exp(e)rimentalhid look odd (IMHO one (use)winhid would be more to the point).

Notably, does the resulting program need linking with libusb{0,1}.c if you use a different backend? Is the LibUSB "proper" still used here?

Also, I wonder if the methods you've added to usbhid-ups.c driver sources make more sense in e.g. libhid.c so other USB-capable drivers could take advantage of them eventually?

I have make few rounds of refactoring of this patch, beginning with using IOCTL_HID_GET_REPORT_DESCRIPTOR and other IOCTL functions but get no luck with same result and behavior like current libusb. Some of the code is not cleaned or reused with current code, also I'm working on diffenrent devices so the config of IDE might affect indentation. During testing of the code the linking is still remained, will check that later.

Thanks for the advice and I will make the code cleaner.

@MysteryDove
Copy link
Contributor Author

MysteryDove commented Mar 3, 2026

For the second part, my goal is make it acting like a replacement of libusb under windows to provide alternative of transporting data besides libusb for HID devices ONLY (But it has drawback of not getting any raw data from USB interface), I think current code should already be capable for testing with other USB-capable drivers (I'm assuming all USB-capable drivers are a sub-driver of usbhid-ups since I'm not having full context of the NUT project, and also windows hid api obviously works straighfoward with usbhid-ups)

@jimklimov
Copy link
Member

assuming all USB-capable drivers are a sub-driver of usbhid-ups

Well, actually yes, for USB HID that should be the case. Other USB cases include numerous Megatec Qx protocol handlers, mostly under nutdrv_qx umbrella now, or Modbus USB. But if your effort is specifically about HID, those drivers are probably not much interested indeed.

Skimming through sources, I see that drivers/apc_modbus.c includes "libhid.h" and mge_shut_SOURCES include libhid.c but not quickly sure further to what end.

@MysteryDove
Copy link
Contributor Author

@jimklimov Fixed for typo and indent now, Under assist of Claude Opus 4.6, A major refactor is also done

I've walk through mge_shut and apc_modbus, the former one seems like a usb over serial things to use libhid for parsing only, and the latter one uses libhid to extract report id for finding modbus data payload report. So I think the libwinhid is not applicable for them.

For newly added libwinhid, it is runtime independent and it won't change any original libusb behavior if experimentalhid not present under ups.conf, I believe it is not a breaking change.

@MysteryDove MysteryDove marked this pull request as ready for review March 4, 2026 11:14
@AppVeyorBot
Copy link

@AppVeyorBot
Copy link

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

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

3 participants