/// <summary> /// reads an Input report from the device using interrupt transfers. /// </summary> /// /// <param name="hidHandle"> the handle for learning about the device and exchanging Feature reports. </param> /// <param name="readHandle"> the handle for reading Input reports from the device. </param> /// <param name="writeHandle"> the handle for writing Output reports to the device. </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> internal override void Read(SafeFileHandle hidHandle, SafeFileHandle readHandle, SafeFileHandle writeHandle, ref Boolean myDeviceDetected, ref Byte[] inputReportBuffer, ref Boolean success) { IntPtr eventObject = IntPtr.Zero; NativeOverlapped HidOverlapped = new NativeOverlapped(); IntPtr nonManagedBuffer = IntPtr.Zero; IntPtr nonManagedOverlapped = IntPtr.Zero; Int32 numberOfBytesRead = 0; Int32 result = 0; try { // Set up the overlapped structure for ReadFile. PrepareForOverlappedTransfer(ref HidOverlapped, ref eventObject); // Allocate memory for the input buffer and overlapped structure. nonManagedBuffer = Marshal.AllocHGlobal(inputReportBuffer.Length); nonManagedOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(HidOverlapped)); Marshal.StructureToPtr(HidOverlapped, nonManagedOverlapped, false); // *** // 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. // *** success = FileIO.ReadFile(readHandle, nonManagedBuffer, inputReportBuffer.Length, ref numberOfBytesRead, nonManagedOverlapped); if (!success) { Debug.WriteLine("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 = FileIO.WaitForSingleObject(eventObject, 3000); // Find out if ReadFile completed or timeout. switch (result) { case (System.Int32)FileIO.WAIT_OBJECT_0: // ReadFile has completed success = true; Debug.WriteLine("ReadFile completed successfully."); // Get the number of bytes read. // API function: GetOverlappedResult // Purpose: gets the result of an overlapped operation. // Accepts: // A device handle returned by CreateFile. // A pointer to an overlapped structure. // A pointer to a variable to hold the number of bytes read. // False to return immediately. // Returns: non-zero on success and the number of bytes read. FileIO.GetOverlappedResult(readHandle, nonManagedOverlapped, ref numberOfBytesRead, false); break; case FileIO.WAIT_TIMEOUT: // Cancel the operation on timeout CancelTransfer(hidHandle, readHandle, writeHandle, eventObject); Debug.WriteLine("Readfile timeout"); success = false; myDeviceDetected = false; break; default: // Cancel the operation on other error. CancelTransfer(hidHandle, readHandle, writeHandle, eventObject); Debug.WriteLine("Readfile undefined error"); success = false; myDeviceDetected = false; break; } } if (success) { // A report was received. // Copy the received data to inputReportBuffer for the application to use. Marshal.Copy(nonManagedBuffer, inputReportBuffer, 0, numberOfBytesRead); } } catch (Exception ex) { DisplayException(MODULE_NAME, ex); throw; } finally { if (nonManagedBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(nonManagedBuffer); } if (nonManagedOverlapped != IntPtr.Zero) { Marshal.FreeHGlobal(nonManagedOverlapped); } } }
/// <summary> /// reads an Input report from the device using interrupt transfers. /// </summary> /// /// <param name="hidHandle"> the handle for learning about the device and exchanging Feature reports. </param> /// <param name="readHandle"> the handle for reading Input reports from the device. </param> /// <param name="writeHandle"> the handle for writing Output reports to the device. </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> public override void Read(SafeFileHandle hidHandle, SafeFileHandle readHandle, SafeFileHandle writeHandle, ref Boolean myDeviceDetected, ref Byte[] inputReportBuffer, ref Boolean success) { SafeWaitHandle eventObject = null; FileIO.OVERLAPPED HidOverlapped = new FileIO.OVERLAPPED(); Int32 numberOfBytesRead = 0; Int32 result = 0; try { // If it's the first attempt to read, set up the overlapped structure for ReadFile. if (readyForOverlappedTransfer == false) { 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. // *** result = FileIO.ReadFile(readHandle, inputReportBuffer, inputReportBuffer.Length, ref numberOfBytesRead, HidOverlapped); Debug.WriteLine("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 = FileIO.WaitForSingleObject(eventObject, 3000); // Find out if ReadFile completed or timeout. switch (result) { case (System.Int32)FileIO.WAIT_OBJECT_0: // ReadFile has completed success = true; Debug.WriteLine("ReadFile completed successfully."); break; case FileIO.WAIT_TIMEOUT: // Cancel the operation on timeout CancelTransfer(hidHandle, readHandle, writeHandle); Debug.WriteLine("Readfile timeout"); success = false; myDeviceDetected = false; break; default: // Cancel the operation on other error. CancelTransfer(hidHandle, readHandle, writeHandle); Debug.WriteLine("Readfile undefined error"); success = false; myDeviceDetected = false; break; } if (result == 0) { success = true; } else { success = false; } } catch (Exception ex) { DisplayException(MODULE_NAME, ex); } }