Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .builds/freebsd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ tasks:
for package in hidapi hidapi-hidraw; do
cc -Wall -Wextra -Werror \
$(pkg-config --cflags "$package") \
tests/pkg-config/test.c \
src/tests/pkg-config/test.c \
-o "build/$package-pkg-config-test" \
$(pkg-config --static --libs "$package")
"./build/$package-pkg-config-test"
done
cc -Wall -Wextra -Werror \
$(pkg-config --cflags hidapi-libusb) \
tests/pkg-config/test.c \
src/tests/pkg-config/test.c \
-o build/hidapi-libusb-pkg-config-test \
$(pkg-config --libs hidapi-libusb)
./build/hidapi-libusb-pkg-config-test
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ jobs:
run: make install
- name: Check pkg-config package
run: |
autoreconf --install --force hidapisrc/tests/pkg-config
autoreconf --install --force hidapisrc/src/tests/pkg-config
mkdir -p build/pkg-config-test
cd build/pkg-config-test
CFLAGS="${GNU_COMPILE_FLAGS}" \
PKG_CONFIG_PATH="${GITHUB_WORKSPACE}/install/shared/lib/pkgconfig" \
"${GITHUB_WORKSPACE}/hidapisrc/tests/pkg-config/configure"
"${GITHUB_WORKSPACE}/hidapisrc/src/tests/pkg-config/configure"
make V=1
- name: Run virtual-device tests (uhid -> hidraw; raw-gadget self-skips)
working-directory: build/shared
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,6 @@ if(HIDAPI_BUILD_HIDTEST)
add_subdirectory(hidtest)
endif()

if(HIDAPI_WITH_TESTS AND (WIN32 OR CMAKE_SYSTEM_NAME MATCHES "Linux" OR APPLE))
if(HIDAPI_WITH_TESTS)
add_subdirectory(src/tests)
endif()
7 changes: 4 additions & 3 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ endif
EXTRA_DIST = \
udev \
doxygen \
tests/pkg-config/configure.ac \
tests/pkg-config/Makefile.am \
tests/pkg-config/test.c
src/core/hidapi_input_ring.h \
src/tests/pkg-config/configure.ac \
src/tests/pkg-config/Makefile.am \
src/tests/pkg-config/test.c

dist_doc_DATA = \
README.md \
Expand Down
11 changes: 11 additions & 0 deletions freebsd/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,17 @@ HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
return dev->read_error_str;
}

int HID_API_EXPORT HID_API_CALL hid_set_num_input_buffers(hid_device *dev, int num_buffers)
{
if (num_buffers <= 0 || num_buffers > HID_API_MAX_NUM_INPUT_BUFFERS) {
register_device_error(dev, "num_buffers out of range");
return -1;
}
/* The kernel manages the input report queue. */
register_device_error(dev, NULL);
return 0;
}

int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
{
/* Do all non-blocking in userspace using poll(), since it looks
Expand Down
57 changes: 57 additions & 0 deletions hidapi/hidapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,63 @@ extern "C" {
*/
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock);

/** @brief Upper bound for hid_set_num_input_buffers().

Values passed above this limit are rejected by
hid_set_num_input_buffers(). Guards against
memory-exhaustion via unbounded input report queue growth.

May be overridden at build time via
-DHID_API_MAX_NUM_INPUT_BUFFERS=<value>.
The library enforces the value used when it was built;
redefining this macro only in an application does not change
that limit. Build the library and application with the same
value to keep the declaration and enforced limit consistent.
*/
#ifndef HID_API_MAX_NUM_INPUT_BUFFERS
#define HID_API_MAX_NUM_INPUT_BUFFERS 1024
Comment thread
Youw marked this conversation as resolved.
Resolved
#endif

/** @brief Set the number of input report buffers queued per device.

Since version 0.16.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 16, 0)

Some HID devices emit input reports in bursts at rates
that exceed the default internal queue capacity, causing
silent report drops on macOS and the libusb backend.
This function allows callers to change how many input
report buffers are retained per device.

Call after hid_open() and before the first hid_read() to
avoid losing reports buffered at open time.

@note Per-backend behavior:
- **macOS (IOKit)** and **libusb**: resizes the
userspace input-report queue. Default: 30 reports.
A full queue drops the oldest report. Shrinking below the
queued count keeps the newest reports in FIFO order.
- **Windows**: forwards to HidD_SetNumInputBuffers(),
which resizes the kernel HID ring buffer. The kernel
accepts values in the range [2, 512]; requests outside
this range return -1. Default: 64 reports.
- **Linux/FreeBSD hidraw** and **NetBSD uhid**: the call is
accepted (returns 0) and validated against
HID_API_MAX_NUM_INPUT_BUFFERS, but has no effect (no-op) —
these kernels manage the input report buffer internally
and expose no userspace resize.

@ingroup API
@param dev A device handle returned from hid_open().
@param num_buffers The desired number of input report buffers.
Must be in range [1, HID_API_MAX_NUM_INPUT_BUFFERS].

@returns
0 on success, -1 on failure (invalid parameters or
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);
Comment thread
Youw marked this conversation as resolved.
Resolved

/** @brief Asynchronously interrupt blocking hid_read/hid_read_timeout call.

Since version 0.16.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 16, 0)
Expand Down
10 changes: 10 additions & 0 deletions hidtest/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ int main(int argc, char* argv[])
(void)&hid_get_input_report;
#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 15, 0)
(void)&hid_send_output_report;
#endif
#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 16, 0)
(void)&hid_set_num_input_buffers;
#endif
(void)&hid_get_feature_report;
(void)&hid_send_feature_report;
Expand Down Expand Up @@ -198,6 +201,13 @@ int main(int argc, char* argv[])
return 1;
}

#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 16, 0)
res = hid_set_num_input_buffers(handle, 500);
if (res < 0) {
printf("Unable to set input buffers: %ls\n", hid_error(handle));
}
#endif

#if defined(_WIN32) && HID_API_VERSION >= HID_API_MAKE_VERSION(0, 15, 0)
hid_winapi_set_write_timeout(handle, 5000);
#endif
Expand Down
Loading
Loading