/// <summary> /// writes an Output report to the device. /// </summary> /// <param name="hidHandle">a handle to the device.</param> /// <param name="outputReportBuffer">contains the report ID and report to send.</param> /// <returns>True on success. False on failure.</returns> protected override bool ProtectedWrite(int hidHandle, byte[] outputReportBuffer) { int NumberOfBytesWritten = 0; bool Success = false; try { // The host will use an interrupt transfer if the the HID has an interrupt OUT // endpoint (requires USB 1.1 or later) AND the OS is NOT Windows 98 Gold (original version). // Otherwise the the host will use a control transfer. // The application doesn't have to know or care which type of transfer is used. // *** // API function: WriteFile // Purpose: writes an Output report to the device. // Accepts: // A handle returned by CreateFile // The output report byte length returned by HidP_GetCaps. // An integer to hold the number of bytes written. // Returns: True on success, False on failure. // *** int Result = FileIOApiDeclarations.WriteFile(hidHandle, ref outputReportBuffer[0], outputReportBuffer.Length, ref NumberOfBytesWritten, 0); if (Settings.Instance.ExtensiveLogging) { Log.Debug(Debugging.ResultOfAPICall("WriteFile")); Log.Debug(""); Log.Debug(" OutputReportByteLength = " + outputReportBuffer.Length); Log.Debug(" NumberOfBytesWritten = " + NumberOfBytesWritten); Log.Debug(" Report ID: " + outputReportBuffer[0]); Log.Debug(" Report Data:"); for (int i = 0; i < outputReportBuffer.Length; i++) { Log.Debug(" " + outputReportBuffer[i].ToString("x")); } } // Return True on success, False on failure. Success = (Result == 0) ? false : true; } catch (Exception ex) { HandleException(ModuleName + ":" + MethodBase.GetCurrentMethod(), ex); } return(Success); }
private bool ReadyForOverlappedTransfer; // initialize to false #endregion /// <summary> /// closes open handles to a device. /// </summary> /// <param name="readHandle">the handle for reading from the device.</param> /// <param name="hidHandle">the handle for other device communications.</param> internal void CancelTransfer(int readHandle, int hidHandle) { try { // *** // API function: CancelIo // Purpose: Cancels a call to ReadFile // Accepts: the device handle. // Returns: True on success, False on failure. // *** Result = FileIOApiDeclarations.CancelIo(readHandle); if (Settings.Instance.ExtensiveLogging) { Log.Debug("************ReadFile error*************"); Log.Debug(Debugging.ResultOfAPICall("CancelIo")); Log.Debug(""); } // The failure may have been because the device was removed, // so close any open handles and // set myDeviceDetected=False to cause the application to // look for the device on the next attempt. if (hidHandle != 0) { FileIOApiDeclarations.CloseHandle(hidHandle); if (Settings.Instance.ExtensiveLogging) { Log.Debug(Debugging.ResultOfAPICall("CloseHandle (HIDHandle)")); Log.Debug(""); } } if (hidHandle != 0) { FileIOApiDeclarations.CloseHandle(readHandle); if (Settings.Instance.ExtensiveLogging) { Log.Debug(Debugging.ResultOfAPICall("CloseHandle (ReadHandle)")); } } } catch (Exception ex) { HandleException(ModuleName + ":" + MethodBase.GetCurrentMethod(), ex); } }
/// <summary> /// Perform actions that must execute when the program ends. /// Disconnects the USB /// </summary> public void Shutdown() { try { // Close open handles to the device. if (_HIDHandle != 0) { FileIOApiDeclarations.CloseHandle(_HIDHandle); if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: " + Debugging.ResultOfAPICall("CloseHandle (HIDHandle)")); } } } catch (Exception ex) { Log.Error(ex); } }
/// <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> /// Uses a series of API calls to locate a HID-class device /// by its Vendor ID and Product ID. /// </summary> /// <returns>True if the device is detected, False if not detected.</returns> private bool FindTheHid() { string[] DevicePathName = new string[128]; FileIOApiDeclarations.SECURITY_ATTRIBUTES Security = new FileIOApiDeclarations.SECURITY_ATTRIBUTES(); try { if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: Searching for display with VendorID:{0:X} & ProductID:{1:X}", _VendorID, _ProductID); } Guid HidGuid = Guid.Empty; _MyDeviceDetected = false; // Values for the SECURITY_ATTRIBUTES structure: Security.lpSecurityDescriptor = 0; Security.bInheritHandle = Convert.ToInt32(true); Security.nLength = Marshal.SizeOf(Security); /* * API function: 'HidD_GetHidGuid * Purpose: Retrieves the interface class GUID for the HID class. * Accepts: 'A System.Guid object for storing the GUID. */ HidApiDeclarations.HidD_GetHidGuid(ref HidGuid); if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: " + Debugging.ResultOfAPICall("GetHidGuid")); } // Display the GUID. string GUIDString = HidGuid.ToString(); if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: GUID for system HIDs: " + GUIDString); } // Fill an array with the device path names of all attached HIDs. bool DeviceFound = DeviceManagement.FindDeviceFromGuid(HidGuid, ref DevicePathName); // If there is at least one HID, attempt to read the Vendor ID and Product ID // of each device until there is a match or all devices have been examined. if (DeviceFound) { int MemberIndex = 0; do { // *** // API function: // CreateFile // Purpose: // Retrieves a handle to a device. // Accepts: // A device path name returned by SetupDiGetDeviceInterfaceDetail // The type of access requested (read/write). // FILE_SHARE attributes to allow other processes to access the device while this handle is open. // A Security structure. Using Null for this may cause problems under Windows XP. // A creation disposition value. Use OPEN_EXISTING for devices. // Flags and attributes for files. Not used for devices. // Handle to a template file. Not used. // Returns: a handle that enables reading and writing to the device. // *** _HIDHandle = FileIOApiDeclarations.CreateFile (DevicePathName[MemberIndex], FileIOApiDeclarations.GENERIC_READ | FileIOApiDeclarations.GENERIC_WRITE, FileIOApiDeclarations.FILE_SHARE_READ | FileIOApiDeclarations.FILE_SHARE_WRITE, ref Security, FileIOApiDeclarations.OPEN_EXISTING, 0, 0); if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: " + Debugging.ResultOfAPICall("CreateFile")); } if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: Returned handle: " + _HIDHandle.ToString("x") + "h"); } if (_HIDHandle != FileIOApiDeclarations.INVALID_HANDLE_VALUE) { // The returned handle is valid, // so find out if this is the device we're looking for. // Set the Size property of DeviceAttributes to the number of bytes in the structure. _MyHID.DeviceAttributes.Size = Marshal.SizeOf(_MyHID.DeviceAttributes); // *** // API function: // HidD_GetAttributes // Purpose: // Retrieves a HIDD_ATTRIBUTES structure containing the Vendor ID, // Product ID, and Product Version Number for a device. // Accepts: // A handle returned by CreateFile. // A pointer to receive a HIDD_ATTRIBUTES structure. // Returns: // True on success, False on failure. // *** int Result = HidApiDeclarations.HidD_GetAttributes(_HIDHandle, ref _MyHID.DeviceAttributes); if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: " + Debugging.ResultOfAPICall("HidD_GetAttributes")); } if (Result != 0) { if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: HIDD_ATTRIBUTES structure filled without error."); } if (Settings.Instance.ExtensiveLogging) { Log.Debug( "MiniDisplay.VFD_Control: Vendor ID: {0:X}, Product ID: {1:X}, Version {2:X}" + _MyHID.DeviceAttributes.VendorID, _MyHID.DeviceAttributes.ProductID, _MyHID.DeviceAttributes.VersionNumber); } // Find out if the device matches the one we're looking for. if ((_MyHID.DeviceAttributes.VendorID == _VendorID) & (_MyHID.DeviceAttributes.ProductID == _ProductID)) { // It's the desired device. if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: My device detected"); } _MyDeviceDetected = true; // Save the DevicePathName so OnDeviceChange() knows which name is my device. } else { // It's not a match, so close the handle. _MyDeviceDetected = false; FileIOApiDeclarations.CloseHandle(_HIDHandle); if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: " + Debugging.ResultOfAPICall("CloseHandle")); } } } else { // There was a problem in retrieving the information. if (Settings.Instance.ExtensiveLogging) { Log.Debug("MiniDisplay.VFD_Control: Error in filling HIDD_ATTRIBUTES structure."); } _MyDeviceDetected = false; FileIOApiDeclarations.CloseHandle(_HIDHandle); } } // Keep looking until we find the device or there are no more left to examine. MemberIndex = MemberIndex + 1; } while (!(_MyDeviceDetected || (MemberIndex == DevicePathName.Length) || DevicePathName[MemberIndex] == null)); } if (_MyDeviceDetected) { // The device was detected. // Learn the capabilities of the device. _MyHID.Capabilities = _MyHID.GetDeviceCapabilities(_HIDHandle); } } catch (Exception ex) { Log.Error(ex); //HandleException(this.Name + ":" + System.Reflection.MethodBase.GetCurrentMethod(), ex); } return(_MyDeviceDetected); }
/// <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); } }