| 1076 | |
| 1077 | |
| 1078 | int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) |
| 1079 | { |
| 1080 | DWORD bytes_read = 0; |
| 1081 | size_t copy_len = 0; |
| 1082 | BOOL res = FALSE; |
| 1083 | BOOL overlapped = FALSE; |
| 1084 | |
| 1085 | if (!data || !length) { |
| 1086 | register_string_error(dev, L"Zero buffer/length"); |
| 1087 | return -1; |
| 1088 | } |
| 1089 | |
| 1090 | register_string_error(dev, NULL); |
| 1091 | |
| 1092 | /* Copy the handle for convenience. */ |
| 1093 | HANDLE ev = dev->ol.hEvent; |
| 1094 | |
| 1095 | if (!dev->read_pending) { |
| 1096 | /* Start an Overlapped I/O read. */ |
| 1097 | dev->read_pending = TRUE; |
| 1098 | memset(dev->read_buf, 0, dev->input_report_length); |
| 1099 | ResetEvent(ev); |
| 1100 | res = ReadFile(dev->device_handle, dev->read_buf, (DWORD) dev->input_report_length, &bytes_read, &dev->ol); |
| 1101 | |
| 1102 | if (!res) { |
| 1103 | if (GetLastError() != ERROR_IO_PENDING) { |
| 1104 | /* ReadFile() has failed. |
| 1105 | Clean up and return error. */ |
| 1106 | register_winapi_error(dev, L"ReadFile"); |
| 1107 | CancelIo(dev->device_handle); |
| 1108 | dev->read_pending = FALSE; |
| 1109 | goto end_of_function; |
| 1110 | } |
| 1111 | overlapped = TRUE; |
| 1112 | } |
| 1113 | } |
| 1114 | else { |
| 1115 | overlapped = TRUE; |
| 1116 | } |
| 1117 | |
| 1118 | if (overlapped) { |
| 1119 | if (milliseconds >= 0) { |
| 1120 | /* See if there is any data yet. */ |
| 1121 | res = WaitForSingleObject(ev, milliseconds); |
| 1122 | if (res != WAIT_OBJECT_0) { |
| 1123 | /* There was no data this time. Return zero bytes available, |
| 1124 | but leave the Overlapped I/O running. */ |
| 1125 | return 0; |
| 1126 | } |
| 1127 | } |
| 1128 | |
| 1129 | /* Either WaitForSingleObject() told us that ReadFile has completed, or |
| 1130 | we are in non-blocking mode. Get the number of bytes read. The actual |
| 1131 | data has been copied to the data[] array which was passed to ReadFile(). */ |
| 1132 | res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/); |
| 1133 | } |
| 1134 | /* Set pending back to false, even if GetOverlappedResult() returned error. */ |
| 1135 | dev->read_pending = FALSE; |
no test coverage detected