Skip to content
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1b0b6ac
hotplug: Add ability to register device connection/disconnection call…
DJm00n May 1, 2023
79a3516
Merge branch 'master' into connection-callback
Youw Mar 11, 2024
ce92386
Windows hotplug: Mutex for callback actions (#646)
k1-801 Apr 6, 2024
c3a2775
Connection callback: add stubs for netbsd (#668)
k1-801 Apr 6, 2024
60b40d9
Linux Hotplug: connection-callback implementation for libusb backend …
k1-801 Apr 6, 2024
4537833
Linux Hotplug: Connection-callback implementation for hidraw (#647)
k1-801 Apr 6, 2024
4f73d1f
Hotplug implementation for MacOS (HidManager approach) (#653)
k1-801 Apr 6, 2024
cfed154
Merge branch 'master' into connection-callback
Youw Apr 6, 2024
b6606ca
Connection callback: fix LeaveCriticalSection not being called after …
d3xMachina Aug 20, 2024
da500c6
Fix possible deadlock in Connection-callback feature (#676)
k1-801 Sep 6, 2024
19112a2
Merge branch 'master' into connection-callback
Youw May 18, 2025
ec2cd2f
Merge branch 'master' into connection-callback
Youw Jan 15, 2026
12a30f1
Merge branch 'master' into connection-callback
Youw Mar 1, 2026
4398a7b
Merge branch 'master' into connection-callback
mcuee Mar 31, 2026
91145c9
fix console log
Youw Mar 31, 2026
9f2c472
Apply suggestions from code review
Youw Mar 31, 2026
5360e03
better device unplug handling on Windows
Youw Mar 31, 2026
8bd8ff7
code review fix
Youw Mar 31, 2026
1889e9f
libusb: Fix high CPU usage in callback thread (#783)
Copilot Apr 24, 2026
885e3e4
ci: use setup-msvc-dev action instead of a hard-coded vcvars path (#817)
Youw Jun 14, 2026
ab7c490
Hotplug docs: thread-safety contract and async ENUMERATE semantics (#…
Youw Jul 13, 2026
2dbb689
Merge branch 'master' into connection-callback
Youw Jul 13, 2026
65a3235
hotplug: fix C++ portability build across all backends
Youw Jul 13, 2026
acf58af
hotplug docs: state the global-error caveat for the thread-safe hotpl…
Youw Jul 14, 2026
e9567ca
hotplug docs: calls made from within a callback do not set the global…
Youw Jul 14, 2026
68af344
hotplug docs: note the unspecified invalid-arg string and the implici…
Youw Jul 15, 2026
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
106 changes: 106 additions & 0 deletions hidapi/hidapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,112 @@ extern "C" {
*/
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);

/** @brief Callback handle.

Callbacks handles are generated by hid_hotplug_register_callback()
and can be used to deregister callbacks. Callback handles are unique
and it is safe to call hid_hotplug_deregister_callback() on
an already deregistered callback.
Comment thread
Youw marked this conversation as resolved.
Outdated

@ingroup API
*/
typedef int hid_hotplug_callback_handle;

/**
Hotplug events

@ingroup API
*/
typedef enum {
/** A device has been plugged in and is ready to use */
HID_API_HOTPLUG_EVENT_DEVICE_ARRIVED = (1 << 0),

/** A device has left and is no longer available.
It is the user's responsibility to call hid_close with a disconnected device.
*/
HID_API_HOTPLUG_EVENT_DEVICE_LEFT = (1 << 1)
} hid_hotplug_event;

/**
Hotplug flags

@ingroup API
*/
typedef enum {
/** Arm the callback and fire it for all matching currently attached devices. */
HID_API_HOTPLUG_ENUMERATE = (1 << 0)
} hid_hotplug_flag;

/** @brief Hotplug callback function type. When requesting hotplug event notifications,
you pass a pointer to a callback function of this type.

This callback may be called by an internal event thread and as such it is
recommended the callback do minimal processing before returning.

hidapi will call this function later, when a matching event had happened on
a matching device.

Note that when callbacks are called from hid_hotplug_register_callback()
because of the \ref HID_API_HOTPLUG_ENUMERATE flag, the callback return
value is ignored. In other words, you cannot cause a callback to be
deregistered by returning 1 when it is called from hid_hotplug_register_callback().

@ingroup API

@param callback_handle The hid_hotplug_callback_handle callback handle.
@param device The hid_device_info of device this event occurred on event that occurred.
@param event Event that occurred.
@param user_data User data provided when this callback was registered.
(Optionally NULL).

@returns bool
Whether this callback is finished processing events.
Returning non-zero value will cause this callback to be deregistered.
*/
typedef int (HID_API_CALL *hid_hotplug_callback_fn)(
hid_hotplug_callback_handle callback_handle,
struct hid_device_info *device,
hid_hotplug_event event,
void *user_data);

/** @brief Register a HID hotplug callback function.

If @p vendor_id is set to 0 then any vendor matches.
If @p product_id is set to 0 then any product matches.
If @p vendor_id and @p product_id are both set to 0, then all HID devices will be notified.

@ingroup API

@param vendor_id The Vendor ID (VID) of the types of device to notify about.
@param product_id The Product ID (PID) of the types of device to notify about.
@param events Bitwise or of hotplug events that will trigger this callback.
See \ref hid_hotplug_event.
@param flags Bitwise or of hotplug flags that affect registration.
See \ref hid_hotplug_flag.
@param callback The callback function that will be called on device connection/disconnection.
See \ref hid_hotplug_callback_fn.
@param user_data The user data you wanted to provide to your callback function.
@param callback_handle Pointer to store the handle of the allocated callback
(Optionally NULL).

@returns
This function returns 0 on success or -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_hotplug_register_callback(unsigned short vendor_id, unsigned short product_id, int events, int flags, hid_hotplug_callback_fn callback, void *user_data, hid_hotplug_callback_handle *callback_handle);

/** @brief Deregister a callback from a HID hotplug.

This function is safe to call from within a hotplug callback.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

while we want this to be true, I have a few conserns:

  1. why do we wan't to make this possible? one could simply return non-zero from a callback function, and that would effectively deregister, w/o a need to call deregister manually...

  2. register/deregister functions are not really thread-safe with regard to each other, mostly because context/mutex initisalisation in not thread-safe. even if we allow calling deregister from within the callback, there should be a big NOTE regarding the fact, that all calls to register/deregister, including the one from withing the callback function - should be serialized / protected by a mutex or so.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. one could simply return non-zero from a callback function, and that would effectively deregister, w/o a need to call deregister manually

It could be deregistering a different callback than the one currently running, OR the user could need to perform certain actions after the callback is deregistered.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2. there should be a big NOTE regarding the fact, that all calls to register/deregister, including the one from withing the callback function - should be serialized / protected by a mutex or so.

True. We do need such a note.
Some thread safety did actually exist there and was removed later during review.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There is also things like: #674 (comment) that needs to be resolved first, and taken into account in general


@ingroup API

@param callback_handle The handle of the callback to deregister.

@returns
This function returns 0 on success or -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_hotplug_deregister_callback(hid_hotplug_callback_handle callback_handle);

/** @brief Open a HID device using a Vendor ID (VID), Product ID
(PID) and optionally a serial number.

Expand Down
Loading