@@ -297,31 +297,77 @@ extern "C" {
297297 HID_API_HOTPLUG_ENUMERATE = (1 << 0 )
298298 } hid_hotplug_flag ;
299299
300- /** @brief Hotplug callback function type. When requesting hotplug event notifications,
301- you pass a pointer to a callback function of this type.
300+ /** @brief Hotplug callback function type.
302301
303- This callback may be called by an internal event thread and as such it is
304- recommended the callback do minimal processing before returning .
302+ Called by HIDAPI when a device matching the registration filter
303+ is connected or disconnected. See #hid_hotplug_register_callback .
305304
306- hidapi will call this function later, when a matching event had happened on
307- a matching device.
305+ ## Execution context
308306
309- Note that when callbacks are called from hid_hotplug_register_callback()
310- because of the \ref HID_API_HOTPLUG_ENUMERATE flag, the callback return
311- value is ignored. In other words, you cannot cause a callback to be
312- deregistered by returning 1 when it is called from hid_hotplug_register_callback().
307+ The callback is invoked on an internal HIDAPI thread that is
308+ distinct from any thread the application creates. Every callback
309+ invocation holds an internal hotplug mutex for its duration, which
310+ means that any other thread calling hid_hotplug_register_callback()
311+ or hid_hotplug_deregister_callback() will block until the callback
312+ returns. Keep the callback short.
313+
314+ ## What the callback may call
315+
316+ The hotplug API itself is thread-safe (see "Thread safety" under
317+ #hid_hotplug_register_callback) and the following calls are always
318+ safe from within the callback:
319+
320+ - hid_hotplug_register_callback()
321+ - hid_hotplug_deregister_callback() (including on its own handle)
322+ - hid_error(dev) with a non-NULL device handle
323+
324+ Any other HIDAPI function follows HIDAPI's general thread-safety
325+ rule (see the Multi-threading Notes in the project wiki): it is
326+ the application's responsibility to serialize hid_init / hid_exit /
327+ hid_enumerate / hid_open* / hid_close / hid_error(NULL) across all
328+ threads, including the hotplug callback thread. If your application
329+ already calls those functions only from one thread, calling them
330+ from the hotplug callback adds a second thread and is therefore
331+ UNSAFE unless the application adds synchronisation itself. The
332+ recommended pattern is to copy the needed fields of @p device out
333+ of the callback and handle open/close on your own thread.
334+
335+ Calling hid_exit() from within the callback has undefined behavior:
336+ hid_exit() joins the hotplug thread, which would be joining itself.
337+
338+ ## device parameter
339+
340+ The @p device pointer is owned by HIDAPI and is valid only for the
341+ duration of the call. To keep any of its fields (path,
342+ serial_number, manufacturer_string, etc.) beyond the callback,
343+ copy them out; pointer fields must be deep-copied, as all strings
344+ are owned by HIDAPI.
345+
346+ The @p device->next pointer is always NULL. Each callback
347+ invocation describes exactly one device; compound or composite
348+ devices that expose multiple interfaces produce multiple callback
349+ invocations (typically delivered in quick succession).
350+
351+ ## Return value
352+
353+ Return 0 to keep the callback registered. Return any non-zero
354+ value to have HIDAPI deregister the callback; no further events
355+ for this handle will be delivered, and the handle is freed as if
356+ hid_hotplug_deregister_callback() had been called. This applies
357+ to both live events and to the synthetic "arrived" events
358+ delivered during registration when #HID_API_HOTPLUG_ENUMERATE is
359+ set.
313360
314361 @ingroup API
315362
316- @param callback_handle The hid_hotplug_callback_handle callback handle .
317- @param device The hid_device_info of device this event occurred on event that occurred .
318- @param event Event that occurred.
319- @param user_data User data provided when this callback was registered.
320- (Optionally NULL).
363+ @param callback_handle The handle of this callback .
364+ @param device The hid_device_info of the device this event occurred on.
365+ @param event Event that occurred. See \ref hid_hotplug_event.
366+ @param user_data User data provided when this callback was registered
367+ (may be NULL).
321368
322- @returns bool
323- Whether this callback is finished processing events.
324- Returning non-zero value will cause this callback to be deregistered.
369+ @returns
370+ 0 to stay registered; any non-zero value to be deregistered.
325371 */
326372 typedef int (HID_API_CALL * hid_hotplug_callback_fn )(
327373 hid_hotplug_callback_handle callback_handle ,
@@ -335,6 +381,20 @@ extern "C" {
335381 If @p product_id is set to 0 then any product matches.
336382 If @p vendor_id and @p product_id are both set to 0, then all HID devices will be notified.
337383
384+ ## Thread safety
385+
386+ hid_hotplug_register_callback() and hid_hotplug_deregister_callback()
387+ are thread-safe. They may be called from any thread, including
388+ from within a hotplug callback. This is a deliberate exception
389+ to HIDAPI's general "not thread-safe" rule (see the
390+ Multi-threading Notes in the project wiki).
391+
392+ The first successful call to hid_hotplug_register_callback()
393+ starts an internal HIDAPI thread that runs until either (a) the
394+ last callback is deregistered, or (b) hid_exit() is called.
395+ hid_exit() must not be called from within a hotplug callback
396+ (see #hid_hotplug_callback_fn).
397+
338398 @ingroup API
339399
340400 @param vendor_id The Vendor ID (VID) of the types of device to notify about.
@@ -356,7 +416,13 @@ extern "C" {
356416
357417 /** @brief Deregister a callback from a HID hotplug.
358418
359- This function is safe to call from within a hotplug callback.
419+ Thread-safe. May be called from any thread, including from within
420+ a hotplug callback (on its own handle or on another callback's
421+ handle). Calling it on a handle that was already deregistered,
422+ or on a handle that was never valid, is a safe no-op returning 0.
423+
424+ See "Thread safety" on #hid_hotplug_register_callback for the
425+ full thread-safety contract of the hotplug API.
360426
361427 @ingroup API
362428
0 commit comments