protected HidDeviceData ReadData(int timeout) { var buffer = new byte[] { }; var status = HidDeviceData.ReadStatus.NoDataRead; IntPtr nonManagedBuffer; if (_deviceCapabilities.InputReportByteLength > 0) { uint bytesRead = 0; buffer = CreateInputBuffer(); nonManagedBuffer = Marshal.AllocHGlobal(buffer.Length); if (_deviceReadMode == DeviceMode.Overlapped) { var security = new NativeMethods.SECURITY_ATTRIBUTES(); var overlapped = new NativeOverlapped(); var overlapTimeout = timeout <= 0 ? NativeMethods.WAIT_INFINITE : timeout; security.lpSecurityDescriptor = IntPtr.Zero; security.bInheritHandle = true; security.nLength = Marshal.SizeOf(security); overlapped.OffsetLow = 0; overlapped.OffsetHigh = 0; overlapped.EventHandle = NativeMethods.CreateEvent(ref security, Convert.ToInt32(false), Convert.ToInt32(true), string.Empty); try { var success = NativeMethods.ReadFile(Handle, nonManagedBuffer, (uint)buffer.Length, out bytesRead, ref overlapped); if (success) { status = HidDeviceData.ReadStatus.Success; // No check here to see if bytesRead > 0 . Perhaps not necessary? } else { var result = NativeMethods.WaitForSingleObject(overlapped.EventHandle, overlapTimeout); switch (result) { case NativeMethods.WAIT_OBJECT_0: status = HidDeviceData.ReadStatus.Success; NativeMethods.GetOverlappedResult(Handle, ref overlapped, out bytesRead, false); break; case NativeMethods.WAIT_TIMEOUT: status = HidDeviceData.ReadStatus.WaitTimedOut; NativeMethods.CancelIo(Handle); buffer = new byte[] { }; break; case NativeMethods.WAIT_FAILED: status = HidDeviceData.ReadStatus.WaitFail; buffer = new byte[] { }; break; default: status = HidDeviceData.ReadStatus.NoDataRead; buffer = new byte[] { }; break; } } Marshal.Copy(nonManagedBuffer, buffer, 0, (int)bytesRead); } catch { status = HidDeviceData.ReadStatus.ReadError; } finally { CloseDeviceIO(overlapped.EventHandle); Marshal.FreeHGlobal(nonManagedBuffer); } } else { try { var overlapped = new NativeOverlapped(); NativeMethods.ReadFile(Handle, nonManagedBuffer, (uint)buffer.Length, out bytesRead, ref overlapped); status = HidDeviceData.ReadStatus.Success; Marshal.Copy(nonManagedBuffer, buffer, 0, (int)bytesRead); } catch { status = HidDeviceData.ReadStatus.ReadError; } finally { Marshal.FreeHGlobal(nonManagedBuffer); } } } return(new HidDeviceData(buffer, status)); }