mirror of
https://github.com/Relintai/sdl2_frt.git
synced 2025-01-12 05:41:10 +01:00
Add 500ms max wait time for hid_write to complete on Windows
It appears that with some (presumably) flaky drivers or hardware that the WriteFile in hid_write never completes leading to GetOverlappedResult to block forever waiting for it.
This commit is contained in:
parent
07000bfc33
commit
96836ec643
@ -63,6 +63,11 @@ typedef LONG NTSTATUS;
|
|||||||
|
|
||||||
/*#define HIDAPI_USE_DDK*/
|
/*#define HIDAPI_USE_DDK*/
|
||||||
|
|
||||||
|
/* The timeout in milliseconds for waiting on WriteFile to
|
||||||
|
complete in hid_write. The longest observed time to do a output
|
||||||
|
report that we've seen is ~200-250ms so let's double that */
|
||||||
|
#define HID_WRITE_TIMEOUT_MILLISECONDS 500
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -163,6 +168,7 @@ struct hid_device_ {
|
|||||||
BOOL read_pending;
|
BOOL read_pending;
|
||||||
char *read_buf;
|
char *read_buf;
|
||||||
OVERLAPPED ol;
|
OVERLAPPED ol;
|
||||||
|
OVERLAPPED write_ol;
|
||||||
};
|
};
|
||||||
|
|
||||||
static hid_device *new_hid_device()
|
static hid_device *new_hid_device()
|
||||||
@ -178,6 +184,8 @@ static hid_device *new_hid_device()
|
|||||||
dev->read_buf = NULL;
|
dev->read_buf = NULL;
|
||||||
memset(&dev->ol, 0, sizeof(dev->ol));
|
memset(&dev->ol, 0, sizeof(dev->ol));
|
||||||
dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
|
dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
|
||||||
|
memset(&dev->write_ol, 0, sizeof(dev->write_ol));
|
||||||
|
dev->write_ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*initial state f=nonsignaled*/, NULL);
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
@ -185,6 +193,7 @@ static hid_device *new_hid_device()
|
|||||||
static void free_hid_device(hid_device *dev)
|
static void free_hid_device(hid_device *dev)
|
||||||
{
|
{
|
||||||
CloseHandle(dev->ol.hEvent);
|
CloseHandle(dev->ol.hEvent);
|
||||||
|
CloseHandle(dev->write_ol.hEvent);
|
||||||
CloseHandle(dev->device_handle);
|
CloseHandle(dev->device_handle);
|
||||||
LocalFree(dev->last_error_str);
|
LocalFree(dev->last_error_str);
|
||||||
free(dev->read_buf);
|
free(dev->read_buf);
|
||||||
@ -678,14 +687,12 @@ int HID_API_EXPORT HID_API_CALL hid_write_output_report(hid_device *dev, const u
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
static int hid_write_timeout(hid_device *dev, const unsigned char *data, size_t length, int milliseconds)
|
||||||
{
|
{
|
||||||
DWORD bytes_written;
|
DWORD bytes_written;
|
||||||
BOOL res;
|
BOOL res;
|
||||||
size_t stashed_length = length;
|
size_t stashed_length = length;
|
||||||
OVERLAPPED ol;
|
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
memset(&ol, 0, sizeof(ol));
|
|
||||||
|
|
||||||
/* Make sure the right number of bytes are passed to WriteFile. Windows
|
/* Make sure the right number of bytes are passed to WriteFile. Windows
|
||||||
expects the number of bytes which are in the _longest_ report (plus
|
expects the number of bytes which are in the _longest_ report (plus
|
||||||
@ -710,7 +717,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res = WriteFile( dev->device_handle, buf, ( DWORD ) length, NULL, &ol );
|
res = WriteFile( dev->device_handle, buf, ( DWORD ) length, NULL, &dev->write_ol );
|
||||||
if (!res) {
|
if (!res) {
|
||||||
if (GetLastError() != ERROR_IO_PENDING) {
|
if (GetLastError() != ERROR_IO_PENDING) {
|
||||||
/* WriteFile() failed. Return error. */
|
/* WriteFile() failed. Return error. */
|
||||||
@ -722,7 +729,16 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
|
|||||||
|
|
||||||
/* Wait here until the write is done. This makes
|
/* Wait here until the write is done. This makes
|
||||||
hid_write() synchronous. */
|
hid_write() synchronous. */
|
||||||
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/);
|
res = WaitForSingleObject(dev->write_ol.hEvent, milliseconds);
|
||||||
|
if (res != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
// There was a Timeout.
|
||||||
|
bytes_written = (DWORD) -1;
|
||||||
|
register_error(dev, "WriteFile/WaitForSingleObject Timeout");
|
||||||
|
goto end_of_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = GetOverlappedResult(dev->device_handle, &dev->write_ol, &bytes_written, FALSE/*F=don't_wait*/);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
/* The Write operation failed. */
|
/* The Write operation failed. */
|
||||||
register_error(dev, "WriteFile");
|
register_error(dev, "WriteFile");
|
||||||
@ -737,6 +753,10 @@ end_of_function:
|
|||||||
return bytes_written;
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
||||||
|
{
|
||||||
|
return hid_write_timeout(dev, data, length, HID_WRITE_TIMEOUT_MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
|
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user