Add hid_set_num_input_buffers() API #787

Open
auxcorelabs wants to merge 8 commits from auxcorelabs/feature/input-report-buffer-size into master
auxcorelabs commented 2026-04-17 03:55:21 -05:00 (Migrated from github.com)

Exposes a new public function hid_set_num_input_buffers(dev, num_buffers) 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 input-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 — documented as a @note on the API declaration in hidapi.h)

Safety

  • Values outside [1, HID_API_MAX_NUM_INPUT_BUFFERS] return -1 and register a descriptive error on the device (via the backend's register_device_error helper where available)
  • 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 at build time via -DHID_API_MAX_NUM_INPUT_BUFFERS=N 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.

Userspace queue: flat pre-allocated ring buffer

The userspace queue is a fixed-size ring with inline-slot storage:

  • Pre-allocated, not MAX-sized. Backing store is a single allocation holding the lengths region (capacity × sizeof(size_t) bytes) followed by the slot data region (capacity × slot_size bytes), allocated once at device open. The struct holds three pointers: storage owns the allocation, while lengths and data are non-owning views into the lengths and slot-data regions respectively.
  • slot_size determined at runtime per backend:
    • macOS — kIOHIDMaxInputReportSizeKey (IOKit-parsed HID report descriptor; authoritative)
    • libusb — interrupt-IN wMaxPacketSize (matches the existing single-packet transfer sizing)
    • 64-byte clamp on both backends as a defensive fallback when the OS reports no value
  • O(1) push/pop. Push is memcpy-only (no per-report malloc); pop is copy-out (pop_into(r, dst, dst_len)) — the ring owns its storage end-to-end, no borrowed-pointer contract.
  • Resize. hidapi_input_ring_resize() allocates new storage, memcpys survivors in FIFO order, frees old, swaps under the caller-held mutex. Shrink-below-count drops oldest, matching push-time policy.
  • Implementation. Single shared header core/hidapi_input_ring.h; backend .c files include it as a static-in-header helper.
  • Tests. tests/test_hidapi_input_ring.c — test cases covering init/destroy idempotency, push/pop FIFO, drop-oldest, varying lengths, resize grow/shrink/wrap/empty/post-wrap/invalid-args, plus a 10k-iteration stress run.

References

  • #154 — this PR also addresses the prior request to expose HidD_SetNumInputBuffers functionality to callers

Assisted-by: Claude Code:opus-4.6, Claude Code:opus-4.7, Codex:gpt-5.4

Exposes a new public function `hid_set_num_input_buffers(dev, num_buffers)` 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 input-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 — documented as a `@note` on the API declaration in `hidapi.h`) ### Safety - Values outside `[1, HID_API_MAX_NUM_INPUT_BUFFERS]` return -1 and register a descriptive error on the device (via the backend's `register_device_error` helper where available) - 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 at build time via `-DHID_API_MAX_NUM_INPUT_BUFFERS=N` 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. ### Userspace queue: flat pre-allocated ring buffer The userspace queue is a fixed-size ring with inline-slot storage: - **Pre-allocated, not MAX-sized.** Backing store is a single allocation holding the lengths region (`capacity × sizeof(size_t)` bytes) followed by the slot data region (`capacity × slot_size` bytes), allocated once at device open. The struct holds three pointers: `storage` owns the allocation, while `lengths` and `data` are non-owning views into the lengths and slot-data regions respectively. - **slot_size determined at runtime per backend:** - **macOS** — `kIOHIDMaxInputReportSizeKey` (IOKit-parsed HID report descriptor; authoritative) - **libusb** — interrupt-IN `wMaxPacketSize` (matches the existing single-packet transfer sizing) - 64-byte clamp on both backends as a defensive fallback when the OS reports no value - **O(1) push/pop.** Push is `memcpy`-only (no per-report `malloc`); pop is copy-out (`pop_into(r, dst, dst_len)`) — the ring owns its storage end-to-end, no borrowed-pointer contract. - **Resize.** `hidapi_input_ring_resize()` allocates new storage, memcpys survivors in FIFO order, frees old, swaps under the caller-held mutex. Shrink-below-count drops oldest, matching push-time policy. - **Implementation.** Single shared header `core/hidapi_input_ring.h`; backend `.c` files include it as a static-in-header helper. - **Tests.** `tests/test_hidapi_input_ring.c` — test cases covering init/destroy idempotency, push/pop FIFO, drop-oldest, varying lengths, resize grow/shrink/wrap/empty/post-wrap/invalid-args, plus a 10k-iteration stress run. ### References - #154 — this PR also addresses the prior request to expose `HidD_SetNumInputBuffers` functionality to callers Assisted-by: Claude Code:opus-4.6, Claude Code:opus-4.7, Codex:gpt-5.4
Youw (Migrated from github.com) reviewed 2026-04-17 09:20:47 -05:00
@ -1199,6 +1199,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
Youw (Migrated from github.com) commented 2026-04-17 09:20:47 -05:00

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

remove this check (from all backends) - device functions do not check for validity of the device handle the only exception is `hid_close`
Youw (Migrated from github.com) reviewed 2026-04-17 09:23:08 -05:00
@ -1199,6 +1199,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
Youw (Migrated from github.com) commented 2026-04-17 09:23:08 -05:00

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

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
Youw (Migrated from github.com) reviewed 2026-04-17 09:23:21 -05:00
Youw (Migrated from github.com) commented 2026-04-17 09:23:21 -05:00

remove

remove
Youw (Migrated from github.com) reviewed 2026-04-17 09:23:29 -05:00
@ -955,6 +955,17 @@ HID_API_EXPORT const wchar_t* HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
Youw (Migrated from github.com) commented 2026-04-17 09:23:29 -05:00

remove

remove
Youw (Migrated from github.com) reviewed 2026-04-17 09:23:37 -05:00
@ -1257,6 +1257,20 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
Youw (Migrated from github.com) commented 2026-04-17 09:23:37 -05:00

remove

remove
Youw (Migrated from github.com) reviewed 2026-04-17 09:24:03 -05:00
Youw (Migrated from github.com) left a comment

refer to comments, otherwise looks good

refer to comments, otherwise looks good
auxcorelabs (Migrated from github.com) reviewed 2026-04-17 11:19:47 -05:00
@ -1199,6 +1199,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
auxcorelabs (Migrated from github.com) commented 2026-04-17 11:19:47 -05:00

Thanks. done.

Thanks. done.
auxcorelabs (Migrated from github.com) reviewed 2026-04-17 11:20:05 -05:00
auxcorelabs (Migrated from github.com) commented 2026-04-17 11:20:05 -05:00

Thanks. done.

Thanks. done.
auxcorelabs (Migrated from github.com) reviewed 2026-04-17 11:20:25 -05:00
@ -955,6 +955,17 @@ HID_API_EXPORT const wchar_t* HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
auxcorelabs (Migrated from github.com) commented 2026-04-17 11:20:25 -05:00

Thanks done.

Thanks done.
auxcorelabs (Migrated from github.com) reviewed 2026-04-17 11:20:36 -05:00
@ -1257,6 +1257,20 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
auxcorelabs (Migrated from github.com) commented 2026-04-17 11:20:36 -05:00

Thanks. done.

Thanks. done.
auxcorelabs (Migrated from github.com) reviewed 2026-04-17 11:21:19 -05:00
@ -1199,6 +1199,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
auxcorelabs (Migrated from github.com) commented 2026-04-17 11:21:19 -05:00

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

Have updated the comment to explicitly call out no-op. Thanks
auxcorelabs commented 2026-04-17 11:21:36 -05:00 (Migrated from github.com)

Thanks for reviewing. I have made the changes.

Thanks for reviewing. I have made the changes.
JoergAtGithub commented 2026-04-18 06:41:56 -05:00 (Migrated from github.com)

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.

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.
auxcorelabs commented 2026-04-19 00:59:20 -05:00 (Migrated from github.com)

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.

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 commented 2026-04-19 03:01:47 -05:00 (Migrated from github.com)

@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.

@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.
Youw (Migrated from github.com) reviewed 2026-04-19 15:47:31 -05:00
@ -1199,6 +1199,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
Youw (Migrated from github.com) commented 2026-04-19 15:47:31 -05:00

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)

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)
auxcorelabs (Migrated from github.com) reviewed 2026-04-20 04:56:06 -05:00
@ -1199,6 +1199,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
auxcorelabs (Migrated from github.com) commented 2026-04-20 04:56:06 -05:00

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

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

@Youw - have moved this to .h file as a Note section. @mcuee - have updated the hidtest app to include the new API.
Youw (Migrated from github.com) approved these changes 2026-04-21 11:43:09 -05:00
Youw (Migrated from github.com) left a comment

So far so good.

So far so good.
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-04-21 11:49:39 -05:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

Adds a new public HIDAPI entry point to let callers increase the per-device input report queue depth, addressing silent report drops during bursty/high-throughput input on backends that queue reports in userspace (macOS + Linux/libusb) and exposing the existing Windows kernel buffering control.

Changes:

  • Introduces hid_set_num_input_buffers(dev, num_buffers) and documents it in hidapi.h (with a max-cap macro).
  • Updates macOS and Linux/libusb backends to enforce queue limits via a per-device num_input_buffers value (default 30).
  • Adds no-op stub implementations for Linux hidraw and NetBSD uhid; updates hidtest to exercise the new API when available.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
hidapi/hidapi.h Declares and documents the new public API and its max-cap macro.
mac/hid.c Adds per-device buffer cap field, uses it in the report callback, and provides a setter guarded by the device mutex.
libusb/hid.c Adds per-device buffer cap field, uses it in the read callback, and provides a setter guarded by the thread-state mutex.
windows/hid.c Implements the API by forwarding to HidD_SetNumInputBuffers.
linux/hid.c Adds a validated no-op stub for the hidraw backend.
netbsd/hid.c Adds a validated no-op stub for the uhid backend.
hidtest/test.c Calls the new API under a version guard to ensure all backends export it.

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

## Pull request overview Adds a new public HIDAPI entry point to let callers increase the per-device input report queue depth, addressing silent report drops during bursty/high-throughput input on backends that queue reports in userspace (macOS + Linux/libusb) and exposing the existing Windows kernel buffering control. **Changes:** - Introduces `hid_set_num_input_buffers(dev, num_buffers)` and documents it in `hidapi.h` (with a max-cap macro). - Updates macOS and Linux/libusb backends to enforce queue limits via a per-device `num_input_buffers` value (default 30). - Adds no-op stub implementations for Linux hidraw and NetBSD uhid; updates `hidtest` to exercise the new API when available. ### Reviewed changes Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | `hidapi/hidapi.h` | Declares and documents the new public API and its max-cap macro. | | `mac/hid.c` | Adds per-device buffer cap field, uses it in the report callback, and provides a setter guarded by the device mutex. | | `libusb/hid.c` | Adds per-device buffer cap field, uses it in the read callback, and provides a setter guarded by the thread-state mutex. | | `windows/hid.c` | Implements the API by forwarding to `HidD_SetNumInputBuffers`. | | `linux/hid.c` | Adds a validated no-op stub for the hidraw backend. | | `netbsd/hid.c` | Adds a validated no-op stub for the uhid backend. | | `hidtest/test.c` | Calls the new API under a version guard to ensure all backends export it. | </details> --- 💡 <a href="/libusb/hidapi/new/master?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
@ -426,0 +433,4 @@
-DHID_API_MAX_NUM_INPUT_BUFFERS=<value>.
*/
#ifndef HID_API_MAX_NUM_INPUT_BUFFERS
#define HID_API_MAX_NUM_INPUT_BUFFERS 1024
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-21 11:49:38 -05:00

HID_API_MAX_NUM_INPUT_BUFFERS is defined unconditionally, which makes the “overridable via -D…” behavior described in the PR text impossible (command-line defines will be overwritten by this header definition). If the intent is to allow build-time overrides, wrap this in #ifndef HID_API_MAX_NUM_INPUT_BUFFERS (or similar) so downstreams can set the cap without patching the header.

		*/
		#ifndef HID_API_MAX_NUM_INPUT_BUFFERS
		#define HID_API_MAX_NUM_INPUT_BUFFERS 1024
		#endif
`HID_API_MAX_NUM_INPUT_BUFFERS` is defined unconditionally, which makes the “overridable via -D…” behavior described in the PR text impossible (command-line defines will be overwritten by this header definition). If the intent is to allow build-time overrides, wrap this in `#ifndef HID_API_MAX_NUM_INPUT_BUFFERS` (or similar) so downstreams can set the cap without patching the header. ```suggestion */ #ifndef HID_API_MAX_NUM_INPUT_BUFFERS #define HID_API_MAX_NUM_INPUT_BUFFERS 1024 #endif ```
@ -426,0 +470,4 @@
backend-specific error). Call hid_error(dev) for
details where supported.
*/
int HID_API_EXPORT HID_API_CALL hid_set_num_input_buffers(hid_device *dev, int num_buffers);
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-21 11:49:38 -05:00

PR description mentions a new public API named hid_set_input_report_buffer_size(dev, size), but the code adds hid_set_num_input_buffers(dev, num_buffers) instead. Please either update the PR description to match the shipped API name, or rename the API in code (including docs) so they are consistent.

PR description mentions a new public API named `hid_set_input_report_buffer_size(dev, size)`, but the code adds `hid_set_num_input_buffers(dev, num_buffers)` instead. Please either update the PR description to match the shipped API name, or rename the API in code (including docs) so they are consistent.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-21 11:49:37 -05:00

Same concern as the macOS backend: with num_input_buffers now configurable up to 1024, this per-report linked-list tail scan is O(n) and can become a significant CPU cost during bursts. Also, the current num_queued counting makes the effective cap differ from dev->num_input_buffers. Consider keeping a tail pointer + queued-count (or a ring buffer) so enqueue/drop is O(1) and the limit matches the API’s meaning.

Same concern as the macOS backend: with `num_input_buffers` now configurable up to 1024, this per-report linked-list tail scan is O(n) and can become a significant CPU cost during bursts. Also, the current `num_queued` counting makes the effective cap differ from `dev->num_input_buffers`. Consider keeping a tail pointer + queued-count (or a ring buffer) so enqueue/drop is O(1) and the limit matches the API’s meaning.
@ -1199,6 +1199,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-21 11:49:38 -05:00

This backend has a register_device_error() helper for setting dev->last_error_str, but this new API writes dev->last_error_str via register_error_str() directly. For consistency (and to keep any future behavior in the helper centralized), consider using register_device_error(dev, "num_buffers out of range") here.

		register_device_error(dev, "num_buffers out of range");
This backend has a `register_device_error()` helper for setting `dev->last_error_str`, but this new API writes `dev->last_error_str` via `register_error_str()` directly. For consistency (and to keep any future behavior in the helper centralized), consider using `register_device_error(dev, "num_buffers out of range")` here. ```suggestion register_device_error(dev, "num_buffers out of range"); ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-21 11:49:37 -05:00

The queue-length enforcement here becomes both expensive and semantically fuzzy now that callers can raise num_input_buffers up to 1024. Each report traverses the entire linked list to find the tail (O(n)), which can become a hot path at high report rates, and the current num_queued accounting means the steady-state queue length is not exactly dev->num_input_buffers. Consider tracking a tail pointer and an explicit queued-count (or switching to a ring buffer) so enqueue/drop is O(1) and the limit corresponds precisely to num_input_buffers.

The queue-length enforcement here becomes both expensive and semantically fuzzy now that callers can raise `num_input_buffers` up to 1024. Each report traverses the entire linked list to find the tail (O(n)), which can become a hot path at high report rates, and the current `num_queued` accounting means the steady-state queue length is not exactly `dev->num_input_buffers`. Consider tracking a tail pointer and an explicit queued-count (or switching to a ring buffer) so enqueue/drop is O(1) and the limit corresponds precisely to `num_input_buffers`.
@ -955,6 +955,17 @@ HID_API_EXPORT const wchar_t* HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-21 11:49:38 -05:00

Similar to other NetBSD APIs, prefer using the register_device_error() helper (or the same error helper used elsewhere in this backend) rather than writing dev->last_error_str via register_error_str() directly. This keeps error-setting behavior consistent across the file.

		register_device_error(dev, "num_buffers out of range");
Similar to other NetBSD APIs, prefer using the `register_device_error()` helper (or the same error helper used elsewhere in this backend) rather than writing `dev->last_error_str` via `register_error_str()` directly. This keeps error-setting behavior consistent across the file. ```suggestion register_device_error(dev, "num_buffers out of range"); ```
Youw (Migrated from github.com) reviewed 2026-04-21 13:02:14 -05:00
@ -1199,6 +1199,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
Youw (Migrated from github.com) commented 2026-04-21 13:02:13 -05:00

agree

agree
Youw (Migrated from github.com) reviewed 2026-04-21 13:02:16 -05:00
@ -955,6 +955,17 @@ HID_API_EXPORT const wchar_t* HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
Youw (Migrated from github.com) commented 2026-04-21 13:02:16 -05:00

agree

agree
Youw (Migrated from github.com) reviewed 2026-04-21 13:02:29 -05:00
@ -426,0 +470,4 @@
backend-specific error). Call hid_error(dev) for
details where supported.
*/
int HID_API_EXPORT HID_API_CALL hid_set_num_input_buffers(hid_device *dev, int num_buffers);
Youw (Migrated from github.com) commented 2026-04-21 13:02:29 -05:00

minor: need update PR description

minor: need update PR description
Youw (Migrated from github.com) reviewed 2026-04-21 13:02:55 -05:00
@ -426,0 +433,4 @@
-DHID_API_MAX_NUM_INPUT_BUFFERS=<value>.
*/
#ifndef HID_API_MAX_NUM_INPUT_BUFFERS
#define HID_API_MAX_NUM_INPUT_BUFFERS 1024
Youw (Migrated from github.com) commented 2026-04-21 13:02:55 -05:00

true - either a PR descriptino or code needs to be updated, I don't really have a preference

true - either a PR descriptino or code needs to be updated, I don't really have a preference
Youw (Migrated from github.com) reviewed 2026-04-21 13:04:10 -05:00
Youw (Migrated from github.com) commented 2026-04-21 13:04:10 -05:00

Someone needs to double-check this, but I'm pretty sure Copilot is right here.
We might even need to consider one step further and switch from linked list to a ring buffer as an optimisation

Someone needs to double-check this, but I'm pretty sure Copilot is right here. We might even need to consider one step further and switch from linked list to a ring buffer as an optimisation
auxcorelabs (Migrated from github.com) reviewed 2026-04-22 12:54:17 -05:00
@ -955,6 +955,17 @@ HID_API_EXPORT const wchar_t* HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
auxcorelabs (Migrated from github.com) commented 2026-04-22 12:54:17 -05:00

Updated.

Updated.
auxcorelabs (Migrated from github.com) reviewed 2026-04-22 12:54:25 -05:00
@ -1199,6 +1199,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->last_read_error_str;
auxcorelabs (Migrated from github.com) commented 2026-04-22 12:54:24 -05:00

Updated.

Updated.
auxcorelabs (Migrated from github.com) reviewed 2026-04-22 12:54:37 -05:00
@ -426,0 +470,4 @@
backend-specific error). Call hid_error(dev) for
details where supported.
*/
int HID_API_EXPORT HID_API_CALL hid_set_num_input_buffers(hid_device *dev, int num_buffers);
auxcorelabs (Migrated from github.com) commented 2026-04-22 12:54:36 -05:00

Updated PR description.

Updated PR description.
auxcorelabs (Migrated from github.com) reviewed 2026-04-22 12:55:00 -05:00
@ -426,0 +433,4 @@
-DHID_API_MAX_NUM_INPUT_BUFFERS=<value>.
*/
#ifndef HID_API_MAX_NUM_INPUT_BUFFERS
#define HID_API_MAX_NUM_INPUT_BUFFERS 1024
auxcorelabs (Migrated from github.com) commented 2026-04-22 12:55:00 -05:00

Updated code.

Updated code.
auxcorelabs (Migrated from github.com) reviewed 2026-04-22 12:55:20 -05:00
auxcorelabs (Migrated from github.com) commented 2026-04-22 12:55:20 -05:00

Updated to ring buffer

Updated to ring buffer
auxcorelabs (Migrated from github.com) reviewed 2026-04-22 12:55:30 -05:00
auxcorelabs (Migrated from github.com) commented 2026-04-22 12:55:30 -05:00

Updated to ring buffer.

Updated to ring buffer.
Youw (Migrated from github.com) reviewed 2026-04-22 16:15:06 -05:00
Youw (Migrated from github.com) reviewed 2026-04-22 16:16:05 -05:00
Youw (Migrated from github.com) left a comment

This is an impressive amount of new code contributed in a short amount of time.
What AI tool has been used to generate it? I will not believe it was hand-written.

This is an impressive amount of new code contributed in a short amount of time. What AI tool has been used to generate it? I will not believe it was hand-written.
auxcorelabs (Migrated from github.com) reviewed 2026-04-23 09:59:34 -05:00
auxcorelabs commented 2026-04-23 10:08:37 -05:00 (Migrated from github.com)

This is an impressive amount of new code contributed in a short amount of time. What AI tool has been used to generate it? I will not believe it was hand-written.

This was a relatively large change, developed using a structured workflow with human oversight & guidance. The design and approach/choices were planned and reviewed (via AI-assisted passes and manually) before any code change. Two AI models were then used in complementary roles—one for code drafting and the other for iterative review to refine the result. The output went through human review and feedback, and the final changes were manually validated, including building across available platforms to verify there were no errors before committing.

From my experience, the effectiveness comes primarily from the structured workflow and repeated AI review iterations, followed by human review & guidance.

> This is an impressive amount of new code contributed in a short amount of time. What AI tool has been used to generate it? I will not believe it was hand-written. This was a relatively large change, developed using a structured workflow with human oversight & guidance. The design and approach/choices were planned and reviewed (via AI-assisted passes and manually) before any code change. Two AI models were then used in complementary roles—one for code drafting and the other for iterative review to refine the result. The output went through human review and feedback, and the final changes were manually validated, including building across available platforms to verify there were no errors before committing. From my experience, the effectiveness comes primarily from the structured workflow and repeated AI review iterations, followed by human review & guidance.
Youw (Migrated from github.com) reviewed 2026-04-23 11:21:15 -05:00
Youw commented 2026-04-23 12:03:07 -05:00 (Migrated from github.com)

the effectiveness comes primarily from the structured workflow and repeated AI review iterations, followed by human review & guidance

I generally don't mind as I'm using similar tools and aproaches myself in various other projects.

But since HIDAPI is open-source well-know public repo with many users and this is a first huge contribution to HIDAPI using AI-tools, I'd like to mention this explicitly in a form suggested by https://docs.kernel.org/process/coding-assistants.html, specifically the commit message/PR description attribution (at least I'm planning to include it in the final squash-merge commit into master), e.g.:
Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]

that's why I asked what AI tool/model was used to produce this.


I'll make a generic NOTE about this somewhere in the README a bit later.

> the effectiveness comes primarily from the structured workflow and repeated AI review iterations, followed by human review & guidance I generally don't mind as I'm using similar tools and aproaches myself in various other projects. But since HIDAPI is open-source well-know public repo with many users and this is a first huge contribution to HIDAPI using AI-tools, I'd like to mention this explicitly in a form suggested by https://docs.kernel.org/process/coding-assistants.html, specifically the commit message/PR description attribution (at least I'm planning to include it in the final squash-merge commit into master), e.g.: Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2] that's why I asked what AI tool/model was used to produce this. --- I'll make a generic NOTE about this somewhere in the README a bit later.
auxcorelabs (Migrated from github.com) reviewed 2026-04-25 08:19:29 -05:00
auxcorelabs commented 2026-04-25 08:20:45 -05:00 (Migrated from github.com)

Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]

Thanks for the information. Please find details below:
Assisted-by: Claude Code CLI:claude-opus-4.6
Assisted-by: Claude Code CLI:claude-opus-4.7
Assisted-by: Codex CLI:gpt-5.4

> Assisted-by: AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2] Thanks for the information. Please find details below: Assisted-by: Claude Code CLI:claude-opus-4.6 Assisted-by: Claude Code CLI:claude-opus-4.7 Assisted-by: Codex CLI:gpt-5.4
Youw (Migrated from github.com) reviewed 2026-04-25 08:35:42 -05:00
@ -877,48 +867,22 @@ static void hid_report_callback(void *context, IOReturn result, void *sender,
(void) report_type;
Youw (Migrated from github.com) commented 2026-04-25 08:35:42 -05:00

as per thread-safety notes posted on Wiki - register_device_error itself is not thread-safe (and not intended to be) and accessing error string from different threads (hid_report_callback thread in this case) can cause a data race

as per thread-safety notes posted on Wiki - `register_device_error` itself is not thread-safe (and not intended to be) and accessing error string from different threads (`hid_report_callback` thread in this case) can cause a data race
Youw (Migrated from github.com) reviewed 2026-04-25 08:40:37 -05:00
@ -0,0 +1,269 @@
/*******************************************************
Youw (Migrated from github.com) commented 2026-04-25 08:40:37 -05:00

I believe this doesn't have to be a separate allocation either. There could be a single storage and two non-owning poiinters to lengths and data

I believe this doesn't have to be a separate allocation either. There could be a single `storage` and two non-owning poiinters to `lengths` and `data`
Youw (Migrated from github.com) reviewed 2026-04-25 08:41:58 -05:00
Youw (Migrated from github.com) left a comment

This looks great, thanks!

I did a quick review, but I want to go over it again what I have a bit more free time than now.

Thanks for the contribution! I'll have it merged some time soon.

This looks great, thanks! I did a quick review, but I want to go over it again what I have a bit more free time than now. Thanks for the contribution! I'll have it merged some time soon.
auxcorelabs (Migrated from github.com) reviewed 2026-04-26 08:52:10 -05:00
@ -877,48 +867,22 @@ static void hid_report_callback(void *context, IOReturn result, void *sender,
(void) report_type;
auxcorelabs (Migrated from github.com) commented 2026-04-26 08:52:10 -05:00

Done. Dropped register_device_error() from the hid_report_callback thread.

Done. Dropped register_device_error() from the hid_report_callback thread.
auxcorelabs (Migrated from github.com) reviewed 2026-04-26 08:53:44 -05:00
@ -0,0 +1,269 @@
/*******************************************************
auxcorelabs (Migrated from github.com) commented 2026-04-26 08:53:44 -05:00

Done. Updated.

Done. Updated.
auxcorelabs commented 2026-04-26 08:54:18 -05:00 (Migrated from github.com)

This looks great, thanks!

I did a quick review, but I want to go over it again what I have a bit more free time than now.

Thanks for the contribution! I'll have it merged some time soon.

Thanks!

> This looks great, thanks! > > I did a quick review, but I want to go over it again what I have a bit more free time than now. > > Thanks for the contribution! I'll have it merged some time soon. Thanks!
auxcorelabs commented 2026-05-11 02:23:30 -05:00 (Migrated from github.com)

@Youw - just wanted to check whether you’ve had a chance to review this. Thanks.

@Youw - just wanted to check whether you’ve had a chance to review this. Thanks.
mcuee commented 2026-05-11 23:16:04 -05:00 (Migrated from github.com)

Somehow the added test is not built under Windows, only libusb and macOS.

Somehow the added test is not built under Windows, only libusb and macOS.
auxcorelabs commented 2026-05-12 01:31:49 -05:00 (Migrated from github.com)

Somehow the added test is not built under Windows, only libusb and macOS.

@mcuee - The tests/test_hidapi_input_ring.c are unit tests, all of them exercising the ring buffer (hidapi_input_ring.h). The ring buffer only links into mac and libusb backends — Windows wraps HidD_SetNumInputBuffers natively (our hid_set_num_input_buffers is a thin wrapper there). Hence these tests were gated to only libusb and mac.

Since hidtest/test.c builds everywhere, that's where symbol-availability check and a runtime smoke call to hid_set_num_input_buffers were added.

> Somehow the added test is not built under Windows, only libusb and macOS. @mcuee - The tests/test_hidapi_input_ring.c are unit tests, all of them exercising the ring buffer (hidapi_input_ring.h). The ring buffer only links into mac and libusb backends — Windows wraps HidD_SetNumInputBuffers natively (our hid_set_num_input_buffers is a thin wrapper there). Hence these tests were gated to only libusb and mac. Since hidtest/test.c builds everywhere, that's where symbol-availability check and a runtime smoke call to hid_set_num_input_buffers were added.
mcuee commented 2026-05-12 02:00:51 -05:00 (Migrated from github.com)

@auxcorelabs

I see. Thanks for the explanation.

@auxcorelabs I see. Thanks for the explanation.
This pull request has changes conflicting with the target branch.
  • CMakeLists.txt
  • libusb/hid.c
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin 'auxcorelabs/feature/input-report-buffer-size:auxcorelabs/feature/input-report-buffer-size'
git switch 'auxcorelabs/feature/input-report-buffer-size'

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch 'master'
git merge --no-ff 'auxcorelabs/feature/input-report-buffer-size'
git switch 'auxcorelabs/feature/input-report-buffer-size'
git rebase 'master'
git switch 'master'
git merge --ff-only 'auxcorelabs/feature/input-report-buffer-size'
git switch 'auxcorelabs/feature/input-report-buffer-size'
git rebase 'master'
git switch 'master'
git merge --no-ff 'auxcorelabs/feature/input-report-buffer-size'
git switch 'master'
git merge --squash 'auxcorelabs/feature/input-report-buffer-size'
git switch 'master'
git merge --ff-only 'auxcorelabs/feature/input-report-buffer-size'
git switch 'master'
git merge 'auxcorelabs/feature/input-report-buffer-size'
git push origin 'master'
Sign in to join this conversation.
No reviewers
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-libusb/hidapi!787
No description provided.