/// <summary> /// Creates an event object for the overlapped structure used with ReadFile. /// Called before the first call to ReadFile. /// </summary> /// <param name="hidOverlapped"></param> /// <param name="eventObject"></param> internal void PrepareForOverlappedTransfer(ref FileIOApiDeclarations.OVERLAPPED hidOverlapped, ref int eventObject) { FileIOApiDeclarations.SECURITY_ATTRIBUTES Security = new FileIOApiDeclarations.SECURITY_ATTRIBUTES(); try { // Values for the SECURITY_ATTRIBUTES structure: Security.lpSecurityDescriptor = 0; Security.bInheritHandle = Convert.ToInt32(true); Security.nLength = Marshal.SizeOf(Security); // *** // API function: CreateEvent // Purpose: Creates an event object for the overlapped structure used with ReadFile. // Accepts: // A security attributes structure. // Manual Reset = False (The system automatically resets the state to nonsignaled // after a waiting thread has been released.) // Initial state = True (signaled) // An event object name (optional) // Returns: a handle to the event object // *** eventObject = FileIOApiDeclarations.CreateEvent(ref Security, Convert.ToInt32(false), Convert.ToInt32(true), ""); if (Settings.Instance.ExtensiveLogging) { Log.Debug(Debugging.ResultOfAPICall("CreateEvent")); Log.Debug(""); } // Set the members of the overlapped structure. hidOverlapped.Offset = 0; hidOverlapped.OffsetHigh = 0; hidOverlapped.hEvent = eventObject; ReadyForOverlappedTransfer = true; } catch (Exception ex) { HandleException(ModuleName + ":" + MethodBase.GetCurrentMethod(), ex); } }
/// <summary> /// reads an Input report from the device using interrupt transfers. /// </summary> /// <param name="readHandle">the handle for reading from the device.</param> /// <param name="hidHandle">the handle for other device communications.</param> /// <param name="myDeviceDetected">tells whether the device is currently attached.</param> /// <param name="inputReportBuffer">contains the requested report.</param> /// <param name="success">read success</param> protected override void ProtectedRead(int readHandle, int hidHandle, ref bool myDeviceDetected, ref byte[] inputReportBuffer, ref bool success) { int EventObject = 0; FileIOApiDeclarations.OVERLAPPED HIDOverlapped = new FileIOApiDeclarations.OVERLAPPED(); int NumberOfBytesRead = 0; try { // If it's the first attempt to read, set up the overlapped structure for ReadFile. if (!ReadyForOverlappedTransfer) { PrepareForOverlappedTransfer(ref HIDOverlapped, ref EventObject); } // *** // API function: ReadFile // Purpose: Attempts to read an Input report from the device. // Accepts: // A device handle returned by CreateFile // (for overlapped I/O, CreateFile must have been called with FILE_FLAG_OVERLAPPED), // A pointer to a buffer for storing the report. // The Input report length in bytes returned by HidP_GetCaps, // A pointer to a variable that will hold the number of bytes read. // An overlapped structure whose hEvent member is set to an event object. // Returns: the report in ReadBuffer. // The overlapped call returns immediately, even if the data hasn't been received yet. // To read multiple reports with one ReadFile, increase the size of ReadBuffer // and use NumberOfBytesRead to determine how many reports were returned. // Use a larger buffer if the application can't keep up with reading each report // individually. // *** if (Settings.Instance.ExtensiveLogging) { Log.Debug("input report length = " + inputReportBuffer.Length); } FileIOApiDeclarations.ReadFile(readHandle, ref inputReportBuffer[0], inputReportBuffer.Length, ref NumberOfBytesRead, ref HIDOverlapped); if (Settings.Instance.ExtensiveLogging) { Log.Debug(Debugging.ResultOfAPICall("ReadFile")); Log.Debug(""); Log.Debug("waiting for ReadFile"); } // API function: WaitForSingleObject // Purpose: waits for at least one report or a timeout. // Used with overlapped ReadFile. // Accepts: // An event object created with CreateEvent // A timeout value in milliseconds. // Returns: A result code. Result = FileIOApiDeclarations.WaitForSingleObject(EventObject, 3000); if (Settings.Instance.ExtensiveLogging) { Log.Debug(Debugging.ResultOfAPICall("WaitForSingleObject")); Log.Debug(""); } // Find out if ReadFile completed or timeout. switch (Result) { case FileIOApiDeclarations.WAIT_OBJECT_0: // ReadFile has completed success = true; if (Settings.Instance.ExtensiveLogging) { Log.Debug("ReadFile completed successfully."); } break; case FileIOApiDeclarations.WAIT_TIMEOUT: // Cancel the operation on timeout CancelTransfer(readHandle, hidHandle); if (Settings.Instance.ExtensiveLogging) { Log.Debug("Readfile timeout"); } success = false; myDeviceDetected = false; break; default: // Cancel the operation on other error. CancelTransfer(readHandle, hidHandle); if (Settings.Instance.ExtensiveLogging) { Log.Debug("Readfile undefined error"); } success = false; myDeviceDetected = false; break; } success = (Result == 0) ? true : false; } catch (Exception ex) { HandleException(ModuleName + ":" + MethodBase.GetCurrentMethod(), ex); } }