// Invoke the HasReadData event; called whenever the Read completes: protected virtual void OnDataReadComplete(AsyncInputReportArgs e) { if (HasReadData != null) { HasReadData(this, e); } }
/// <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) { 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) { Tracer.Trace("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; Tracer.Trace("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); Tracer.Error("Readfile timeout"); success = false; myDeviceDetected = false; break; default: // Cancel the operation on other error. CancelTransfer(hidHandle, readHandle, writeHandle, eventObject); Tracer.Error("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); AsyncInputReportArgs args = new AsyncInputReportArgs(); args.InputBuffer = inputReportBuffer; OnDataReadComplete(args); } } catch (Exception ex) { DisplayException(MODULE_NAME, ex); throw; } }
// This will be called whenever the data is read from the board: private void DataReadCompleteHandler(object sender, AsyncInputReportArgs aira) { Tracer.Trace("Async data arrived. " + DateTime.Now); StringBuilder byteValue = new StringBuilder(); byteValue.Append("DataReadCompleteHandler(): Input Report Data: "); for (int count = 0; count <= aira.InputBuffer.Length - 1; count++) { // Display bytes as 2-character Hex strings. byteValue.AppendFormat("{0:X02} ", aira.InputBuffer[count]); } Tracer.Trace(byteValue.ToString()); int servo1target = intFromBuffer(aira.InputBuffer, 1); int servo2target = intFromBuffer(aira.InputBuffer, 3); int ping1value = intFromBuffer(aira.InputBuffer, 5); int ping2value = intFromBuffer(aira.InputBuffer, 7); AsyncInputFrameArgs args = new AsyncInputFrameArgs(servo1target, servo2target, ping1value, ping2value); OnDataFrameComplete(args); if (inDataContinuousMode) { // initiate next read: ReadFromDevice(new EventHandler<AsyncInputReportArgs>(DataReadCompleteHandler)); } }
/// <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) { 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) { Tracer.Trace("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; Tracer.Trace("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); Tracer.Error("Readfile timeout"); success = false; myDeviceDetected = false; break; default: // Cancel the operation on other error. CancelTransfer(hidHandle, readHandle, writeHandle, eventObject); Tracer.Error("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); AsyncInputReportArgs args = new AsyncInputReportArgs(); args.InputBuffer = inputReportBuffer; OnDataReadComplete(args); } } catch ( Exception ex ) { DisplayException( MODULE_NAME, ex ); throw ; } }