Skip to content

Add hid_set_input_report_buffer_size() API#787

Open
auxcorelabs wants to merge 2 commits intolibusb:masterfrom
auxcorelabs:feature/input-report-buffer-size
Open

Add hid_set_input_report_buffer_size() API#787
auxcorelabs wants to merge 2 commits intolibusb:masterfrom
auxcorelabs:feature/input-report-buffer-size

Conversation

@auxcorelabs
Copy link
Copy Markdown

Exposes a new public function hid_set_input_report_buffer_size(dev, size) to resize the per-device input report queue.

High-throughput HID devices (medical telemetry, high-poll-rate gaming peripherals, data acquisition hardware) can emit bursts of input reports that exceed the current hardcoded queue sizes (30 on macOS and Linux/libusb, 64 on Windows). When a burst exceeds the queue, reports are silently dropped with no error indication to the caller. Observed on hardware emitting ~90 reports in 200 ms bursts: both the macOS and Linux/libusb backends silently drop ~20% of frames.

Per-backend behavior

  • macOS: resizes the userspace IOHIDQueue-fed report queue
  • Linux libusb: resizes the userspace report queue
  • Windows: wraps HidD_SetNumInputBuffers (parity with existing behavior)
  • Linux hidraw / NetBSD: no-op (kernel manages buffering)

Safety

  • Values outside [1, HID_API_MAX_INPUT_REPORT_BUFFER_SIZE] return -1; NULL dev returns -1 with a global error
  • Thread-safe: setter uses the same lock (dev->mutex / dev->thread_state) as the respective report callback

Design notes

  • Backwards compatibility: Purely additive public API. Defaults per backend are unchanged, so existing callers see no behavioral change. hid_device is opaque in hidapi.h, so struct field additions in backend-private files are not an ABI break.
  • Why 1024 cap: Bounds per-device memory to roughly 1 MB on USB high-speed links, preventing memory exhaustion from a caller that passes INT_MAX (malicious or buggy). We've measured bursts up to ~90 reports deep in practice; 1024 leaves room for devices ~10× more demanding. Overridable via -DHID_API_MAX_INPUT_REPORT_BUFFER_SIZE=N at build time for memory-constrained targets.
  • No getter: hidraw and NetBSD back the queue in the kernel with sizes not portably exposed to userspace, so a cross-platform getter couldn't return a meaningful value there.
  • Why not hid_get_input_report() instead? That API issues a host-initiated GET_REPORT request (via the control endpoint or OS equivalent). It does not drain the interrupt-endpoint queue that streaming devices fill, and in practice many devices either don't implement GET_REPORT for input reports or respond incorrectly. The two APIs use different USB transfer mechanisms (interrupt endpoint vs. control endpoint); this PR fixes the interrupt-streaming path.

References

CI equivalent status

All upstream CI equivalents tested locally:

Platform Compiler Flags Result
Linux (libusb + hidraw, shared + static) gcc -Wall -Wextra -pedantic -Werror -Wformat-signedness Pass
Linux with ASAN gcc same + HIDAPI_ENABLE_ASAN=ON Pass
macOS gcc (Xcode) -Wall -Wextra -pedantic -Werror Pass
Windows x64 / x86 MSVC 19.44 /W4 /WX Pass

Zero warnings on all platforms. Symbol verified exported in all built artifacts.

Exposes a new public function to resize the per-device input report
queue. High-throughput HID devices (medical telemetry, high-poll-rate
gaming peripherals, data acquisition hardware) emit bursts of input
reports that exceed the current hardcoded queue sizes (30 on macOS and
the libusb backend, 64 on Windows). When a burst exceeds the queue,
reports are silently dropped with no error indication to the caller.

This adds:
- hid_set_input_report_buffer_size(dev, size) in hidapi.h
- HID_API_MAX_INPUT_REPORT_BUFFER_SIZE (1024) cap to prevent unbounded
  memory growth

Per-backend behavior:
- macOS: resizes the userspace IOHIDQueue-fed report queue
- Linux libusb: resizes the userspace report queue
- Windows: wraps HidD_SetNumInputBuffers (parity with existing behavior)
- Linux hidraw: no-op (kernel manages buffering)
- NetBSD: no-op (kernel manages buffering)

Defaults are unchanged, so existing callers are unaffected. Values
outside [1, HID_API_MAX_INPUT_REPORT_BUFFER_SIZE] are rejected with -1.
Thread-safe on macOS (dev->mutex) and libusb (dev->thread_state),
matching the locks used by the respective report callbacks.

Addresses the same need as closed issue libusb#154 (HidD_SetNumInputBuffers
exposure) and complements libusb#725 (callback-based input API).
@mcuee mcuee added API API change, Version 1 stuff enhancement New feature or request labels Apr 17, 2026
Comment thread linux/hid.c Outdated
Comment on lines +1205 to +1208
if (!dev) {
register_global_error("Device is NULL");
return -1;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

remove this check (from all backends) - device functions do not check for validity of the device handle
the only exception is hid_close

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks. done.

Comment thread linux/hid.c Outdated
Comment on lines +1213 to +1215
/* hidraw: kernel manages the input report buffer, no userspace queue
to resize. Accept the call to preserve a consistent cross-platform
API so callers do not need per-backend conditional code. */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

too bad we don't have a logging mechanism
this looks like a perfect spot for a warning
making this completely silent might confuse some users

anyway - even though documentation mentiones that there is no user-space queue for linux backend - we should explicitly document that this function for linux and bsd backend is a no-op

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Have updated the comment to explicitly call out no-op. Thanks

Comment thread mac/hid.c Outdated
Comment on lines +1355 to +1358
if (!dev) {
register_global_error("Device is NULL");
return -1;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

remove

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks. done.

Comment thread netbsd/hid.c Outdated
Comment on lines +961 to +964
if (!dev) {
register_global_error("Device is NULL");
return -1;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

remove

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks done.

Comment thread windows/hid.c Outdated
Comment on lines +1263 to +1266
if (!dev) {
register_global_error(L"Device is NULL");
return -1;
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

remove

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks. done.

Copy link
Copy Markdown
Member

@Youw Youw left a comment

Choose a reason for hiding this comment

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

refer to comments, otherwise looks good

Per maintainer feedback on PR libusb#787:

- Remove if (!dev) validation from all 5 backends. hidapi convention is that device functions trust the caller to pass a valid handle; only hid_close is permitted to accept NULL.

- Reword the inline comment in linux/hid.c and netbsd/hid.c to lead with "No-op" so the caller-visible behavior is explicit at the implementation site.
@auxcorelabs
Copy link
Copy Markdown
Author

Thanks for reviewing. I have made the changes.

@JoergAtGithub
Copy link
Copy Markdown
Contributor

I think the name of the Win32-API HidD_SetNumInputBuffers describes better what it does than hid_set_input_report_buffer_size, as it does change the number of buffers and not the size of the bufferin bytes.

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

Labels

API API change, Version 1 stuff enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants