Skip to content

Add hid_set_num_input_buffers() API#787

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

Add hid_set_num_input_buffers() API#787
auxcorelabs wants to merge 4 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 thread linux/hid.c Outdated
Comment thread mac/hid.c Outdated
Comment thread netbsd/hid.c Outdated
Comment thread windows/hid.c Outdated
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.

… controls the number of input report buffers, not their byte size.

- Function:    hid_set_input_report_buffer_size -> hid_set_num_input_buffers
- Macro:       HID_API_MAX_INPUT_REPORT_BUFFER_SIZE -> HID_API_MAX_NUM_INPUT_BUFFERS
- Parameter:   buffer_size -> num_buffers
- Error string: "buffer_size out of range" -> "num_buffers out of range"
@auxcorelabs auxcorelabs changed the title Add hid_set_input_report_buffer_size() API Add hid_set_num_input_buffers() API Apr 19, 2026
@auxcorelabs
Copy link
Copy Markdown
Author

Good callout @JoergAtGithub. Have renamed the function to hid_set_num_input_buffers() and made the associated changes.

@Youw - Please let me know if any further changes required.

Thanks both.

@mcuee
Copy link
Copy Markdown
Member

mcuee commented Apr 19, 2026

@auxcorelabs
Just wondering if you can enhance the hidtest application to include this new API.

If not, do you have a simple test to share? Thanks.

Comment thread linux/hid.c Outdated
Comment on lines +1209 to +1212
/* No-op on Linux hidraw and BSD backends: the kernel manages input
report buffering and there is no userspace queue to resize. The
call is accepted (returns 0) 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.

I meant having this section in the .h as a NOTE section.
not much point having it here as verbose versino, specifically no point mentioning other backends from within (like mentioning BSD backend inside of the hidraw implementation)

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.

@Youw - have moved this to .h file as a Note section.

@mcuee - have updated the hidtest app to include the new API.

…ile commentary, add hidtest coverage

- hidapi/hidapi.h: replace the Defaults per backend list with an
  @note Per-backend behavior block covering macOS / Windows /
  libusb / hidraw / uhid semantics, ranges, and defaults. Per
  @Youw, the public header is the canonical place for the
  cross-backend contract.
- linux/hid.c, netbsd/hid.c: drop the comment that cross-referenced
  other backends. The (void)num_buffers; idiom and the header
  contract speak for themselves.
- libusb/hid.c: drop the self-scoped no-error-registration note
  for the same reason.
- hidtest/test.c: add a compile-time symbol reference and a
  runtime call hid_set_num_input_buffers(handle, 500) right after
  hid_open() succeeds, per @mcuee. Both guarded on
  HID_API_VERSION >= 0.16.0 so they activate in the 0.16 release
  cycle, matching the precedent of hid_send_output_report at
  0.15.0.
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