They can vanish for UP TO EIGHT SECONDS...!
This is for devices that connect to HDMI/DisplayPort/etc, where it
presumably has to wait for a display to get up and running before it
can play audio through it, so one can see the audio device fail when
changing display modes, or the system returning from sleep. Since this
can be triggered by a game changing video resolutions at startup (either
before or after opening the audio device!), it's important to deal with.
In normal conditions, it shouldn't take this long to open or recover an
audio device, but this is better than unexpectedly losing the device
in this situation.
Fixes#7044.
Fixes#5571.
(cherry picked from commit 48e71ae87be425f117dece3735b148fbc5f2606e)
This is unsafe because the event is auto-reset, therefore the call to
WaitForSingleObject() resets the event which GetOverlappedResult() will
try to wait on.
Even though the overlapped operation is guaranteed to be completed at
the point we call GetOverlappedResult(), it will still wait on the event
handle for a short time to trigger the reset for auto-reset events. This
amounts to roughly a 100 ms sleep each time GetOverlappedResult() is called
for a completed I/O with a non-signalled event.
In the context of HIDAPI, this extra sleep means that callers that loop
on hid_read_timeout() with timeout=0 will loop forever, since the 100 ms
sleep each iteration ensures ReadFile() will always have new data.
Signed-off-by: Cameron Gutman <aicommander@gmail.com>
Signed-off-by: Sam Lantinga <slouken@libsdl.org>
- hidapi already called CancelIo on hid_close but that only cancels pending IO for the current thread. Controller read/writes originate from multiple threads (serialized, but on a different thread nonetheless) but device destruction was always done on the main device thread which left any pending overlapped reads still running after hidapi's internal read buffer is deallocated leading to intermittent free list corruption.
Signed-off-by: Sam Lantinga <slouken@libsdl.org>
Touching HID devices with keyboard usages will trigger a keyboard capture
permission prompt on macOS 11+. See #4887
Like the IOKit joystick backend, we accept HID devices that have joystick,
gamepad, or multi-axis controller usages. We also allow the Valve VID for
the Steam Controller, just like the Windows HIDAPI implementation does.
Signed-off-by: Cameron Gutman <aicommander@gmail.com>
Signed-off-by: Sam Lantinga <slouken@libsdl.org>
The get_usb_string call is rather expensive on some USB devices, so we
cache the vendor/product strings for future lookups (e.g. when
hid_enumerate is invoked again later).
This way, we only need to ask libusb for strings for devices we haven't
seen since before we started.
Signed-off-by: Steven Noonan <steven@valvesoftware.com>
Signed-off-by: Sam Lantinga <slouken@libsdl.org>
We weren't meant to have multiple contexts and mainloops, but we had one
for each opened device and the hotplug detection thread. Instead, use
pa_threaded_mainloop, which can be shared between threads and objects, and
a single context (which, according to the PulseAudio documentation, is
usually meant to be a singleton that represents a global server connection,
possibly with multiple streams hung on it).
Now instead of polling in a loop, threads will block until the
threaded_mainloop runs a callback, and the callback will fire a signal to
unblock the thread.
Prior to this, the code upset ThreadSanitizer, as Pulse has some unprotected
global resource that each mainloop/context would touch.
Reference Issue #7427.
SDL mutexes are always recursive in modern times, so no need to check this,
plus the test triggers a false-positive on ThreadSanitizer.
Reference Issue #7427.