Skip to content

Commit fa17fd0

Browse files
committed
Add hid_read_error
hid_read_error is a separate error function, that returns error status of hid_read/hid_read_timeout. hid_read/hid_read_timeout is no longer changes internal buffer used by hid_error and it makes it safe to use hid_read/hid_read_timeout from a separa thread, concurently with other device functions.
1 parent c5ee4d3 commit fa17fd0

File tree

3 files changed

+53
-7
lines changed

3 files changed

+53
-7
lines changed

hidapi/hidapi.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,11 @@ extern "C" {
341341
@returns
342342
This function returns the actual number of bytes read and
343343
-1 on error.
344-
Call hid_error(dev) to get the failure reason.
344+
Call hid_read_error(dev) to get the failure reason.
345345
If no packet was available to be read within
346346
the timeout period, this function returns 0.
347+
348+
@note This function doesn't change the buffer returned by the hid_error(dev).
347349
*/
348350
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
349351

@@ -363,12 +365,38 @@ extern "C" {
363365
@returns
364366
This function returns the actual number of bytes read and
365367
-1 on error.
366-
Call hid_error(dev) to get the failure reason.
368+
Call hid_read_error(dev) to get the failure reason.
367369
If no packet was available to be read and
368370
the handle is in non-blocking mode, this function returns 0.
371+
372+
@note This function doesn't change the buffer returned by the hid_error(dev).
369373
*/
370374
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length);
371375

376+
/** @brief Get a string describing the last error which occurred during hid_read/hid_read_timeout.
377+
378+
This function is intended for logging/debugging purposes.
379+
380+
This function guarantees to never return NULL.
381+
If there was no error in the last call to hid_read/hid_read_error -
382+
the returned string clearly indicates that.
383+
384+
Any HIDAPI function that can explicitly indicate an execution failure
385+
(e.g. by an error code, or by returning NULL) - may set the error string,
386+
to be returned by this function.
387+
388+
Strings returned from hid_read_error() must not be freed by the user,
389+
i.e. owned by HIDAPI library.
390+
Device-specific error string may remain allocated at most until hid_close() is called.
391+
392+
@ingroup API
393+
@param dev A device handle. Shall never be NULL.
394+
395+
@returns
396+
A string describing the hid_read/hid_read_timeout error (if any).
397+
*/
398+
HID_API_EXPORT const wchar_t* HID_API_CALL hid_read_error(hid_device *dev);
399+
372400
/** @brief Set the device handle to be non-blocking.
373401
374402
In non-blocking mode calls to hid_read() will return

hidtest/test.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,13 @@ int main(int argc, char* argv[])
245245
// Try to read from the device. There should be no
246246
// data here, but execution should not block.
247247
res = hid_read(handle, buf, 17);
248+
if (res < 0) {
249+
#if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 15, 0)
250+
printf("Unable to read from device: %ls\n", hid_read_error(handle));
251+
#else
252+
printf("Unable to read from device: %ls\n", hid_error(handle));
253+
#endif
254+
}
248255

249256
// Send a Feature Report to the device
250257
buf[0] = 0x2;
@@ -254,7 +261,7 @@ int main(int argc, char* argv[])
254261
buf[4] = 0x00;
255262
res = hid_send_feature_report(handle, buf, 17);
256263
if (res < 0) {
257-
printf("Unable to send a feature report.\n");
264+
printf("Unable to send a feature report: %ls\n", hid_error(handle));
258265
}
259266

260267
memset(buf,0,sizeof(buf));

windows/hid.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ struct hid_device_ {
189189
USHORT feature_report_length;
190190
unsigned char *feature_buf;
191191
wchar_t *last_error_str;
192+
wchar_t *last_read_error_str;
192193
BOOL read_pending;
193194
char *read_buf;
194195
OVERLAPPED ol;
@@ -213,6 +214,7 @@ static hid_device *new_hid_device()
213214
dev->feature_report_length = 0;
214215
dev->feature_buf = NULL;
215216
dev->last_error_str = NULL;
217+
dev->last_read_error_str = NULL;
216218
dev->read_pending = FALSE;
217219
dev->read_buf = NULL;
218220
memset(&dev->ol, 0, sizeof(dev->ol));
@@ -231,7 +233,9 @@ static void free_hid_device(hid_device *dev)
231233
CloseHandle(dev->write_ol.hEvent);
232234
CloseHandle(dev->device_handle);
233235
free(dev->last_error_str);
236+
free(dev->last_read_error_str);
234237
dev->last_error_str = NULL;
238+
dev->last_read_error_str = NULL;
235239
free(dev->write_buf);
236240
free(dev->feature_buf);
237241
free(dev->read_buf);
@@ -1152,11 +1156,11 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
11521156
BOOL overlapped = FALSE;
11531157

11541158
if (!data || !length) {
1155-
register_string_error(dev, L"Zero buffer/length");
1159+
register_string_error_to_buffer(&dev->last_read_error_str, L"Zero buffer/length");
11561160
return -1;
11571161
}
11581162

1159-
register_string_error(dev, NULL);
1163+
register_string_error_to_buffer(&dev->last_read_error_str, NULL);
11601164

11611165
/* Copy the handle for convenience. */
11621166
HANDLE ev = dev->ol.hEvent;
@@ -1172,7 +1176,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
11721176
if (GetLastError() != ERROR_IO_PENDING) {
11731177
/* ReadFile() has failed.
11741178
Clean up and return error. */
1175-
register_winapi_error(dev, L"ReadFile");
1179+
register_winapi_error_to_buffer(&dev->last_read_error_str, L"ReadFile");
11761180
CancelIo(dev->device_handle);
11771181
dev->read_pending = FALSE;
11781182
goto end_of_function;
@@ -1219,7 +1223,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
12191223
}
12201224
}
12211225
if (!res) {
1222-
register_winapi_error(dev, L"hid_read_timeout/GetOverlappedResult");
1226+
register_winapi_error_to_buffer(&dev->last_read_error_str, L"hid_read_timeout/GetOverlappedResult");
12231227
}
12241228

12251229
end_of_function:
@@ -1235,6 +1239,13 @@ int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, s
12351239
return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
12361240
}
12371241

1242+
HID_API_EXPORT const wchar_t * HID_API_CALL hid_read_error(hid_device *dev)
1243+
{
1244+
if (dev->last_read_error_str == NULL)
1245+
return L"Success";
1246+
return dev->last_read_error_str;
1247+
}
1248+
12381249
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock)
12391250
{
12401251
dev->blocking = !nonblock;

0 commit comments

Comments
 (0)