sl@0: using Microsoft.Win32.SafeHandles; sl@0: using System; sl@0: using System.Diagnostics; sl@0: using System.IO; sl@0: using System.Runtime.InteropServices; sl@0: using System.Threading; sl@0: using System.Threading.Tasks; sl@0: using System.Windows.Forms; sl@0: sl@0: namespace GenericHid sl@0: { sl@0: /// sl@0: /// Supports Windows API functions for accessing HID-class USB devices. sl@0: /// Includes routines for retrieving information about the configuring a HID and sl@0: /// sending and receiving reports via control and interrupt transfers. sl@0: /// sl@0: sl@0: internal sealed partial class Hid sl@0: { sl@0: // Used in error messages. sl@0: sl@0: private const String ModuleName = "Hid"; sl@0: sl@0: internal NativeMethods.HIDP_CAPS Capabilities; sl@0: internal NativeMethods.HIDD_ATTRIBUTES DeviceAttributes; sl@0: sl@0: // For viewing results of API calls in debug.write statements: sl@0: sl@0: internal static Debugging MyDebugging = new Debugging(); sl@0: sl@0: /// sl@0: /// Provides a central mechanism for exception handling. sl@0: /// Displays a message box that describes the exception. sl@0: /// sl@0: /// sl@0: /// the module where the exception occurred. sl@0: /// the exception sl@0: sl@0: internal static void DisplayException(String moduleName, Exception e) sl@0: { sl@0: // Create an error message. sl@0: sl@0: String message = "Exception: " + e.Message + Environment.NewLine + "Module: " + moduleName + Environment.NewLine + "Method: " + e.TargetSite.Name; sl@0: sl@0: const String caption = "Unexpected Exception"; sl@0: sl@0: MessageBox.Show(message, caption, MessageBoxButtons.OK); sl@0: Debug.Write(message); sl@0: sl@0: // Get the last error and display it. sl@0: Int32 error = Marshal.GetLastWin32Error(); sl@0: sl@0: Debug.WriteLine("The last Win32 Error was: " + error); sl@0: } sl@0: sl@0: /// sl@0: /// Remove any Input reports waiting in the buffer. sl@0: /// sl@0: /// a handle to a device. sl@0: /// sl@0: /// True on success, False on failure. sl@0: /// sl@0: sl@0: internal Boolean FlushQueue(SafeFileHandle hidHandle) sl@0: { sl@0: try sl@0: { sl@0: // *** sl@0: // API function: HidD_FlushQueue sl@0: sl@0: // Purpose: Removes any Input reports waiting in the buffer. sl@0: sl@0: // Accepts: a handle to the device. sl@0: sl@0: // Returns: True on success, False on failure. sl@0: // *** sl@0: sl@0: Boolean success = NativeMethods.HidD_FlushQueue(hidHandle); sl@0: sl@0: return success; sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: sl@0: /// sl@0: /// Get HID attributes. sl@0: /// sl@0: /// HID handle retrieved with CreateFile sl@0: /// HID attributes structure sl@0: /// true on success sl@0: sl@0: internal Boolean GetAttributes(SafeFileHandle hidHandle, ref NativeMethods.HIDD_ATTRIBUTES deviceAttributes) sl@0: { sl@0: Boolean success; sl@0: try sl@0: { sl@0: // *** sl@0: // API function: sl@0: // HidD_GetAttributes sl@0: sl@0: // Purpose: sl@0: // Retrieves a HIDD_ATTRIBUTES structure containing the Vendor ID, sl@0: // Product ID, and Product Version Number for a device. sl@0: sl@0: // Accepts: sl@0: // A handle returned by CreateFile. sl@0: // A pointer to receive a HIDD_ATTRIBUTES structure. sl@0: sl@0: // Returns: sl@0: // True on success, False on failure. sl@0: // *** sl@0: sl@0: success = NativeMethods.HidD_GetAttributes(hidHandle, ref deviceAttributes); sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: return success; sl@0: } sl@0: sl@0: /// sl@0: /// Retrieves a structure with information about a device's capabilities. sl@0: /// sl@0: /// sl@0: /// a handle to a device. sl@0: /// sl@0: /// sl@0: /// An HIDP_CAPS structure. sl@0: /// sl@0: sl@0: internal NativeMethods.HIDP_CAPS GetDeviceCapabilities(SafeFileHandle hidHandle) sl@0: { sl@0: var preparsedData = new IntPtr(); sl@0: sl@0: try sl@0: { sl@0: // *** sl@0: // API function: HidD_GetPreparsedData sl@0: sl@0: // Purpose: retrieves a pointer to a buffer containing information about the device's capabilities. sl@0: // HidP_GetCaps and other API functions require a pointer to the buffer. sl@0: sl@0: // Requires: sl@0: // A handle returned by CreateFile. sl@0: // A pointer to a buffer. sl@0: sl@0: // Returns: sl@0: // True on success, False on failure. sl@0: // *** sl@0: sl@0: NativeMethods.HidD_GetPreparsedData(hidHandle, ref preparsedData); sl@0: sl@0: // *** sl@0: // API function: HidP_GetCaps sl@0: sl@0: // Purpose: find out a device's capabilities. sl@0: // For standard devices such as joysticks, you can find out the specific sl@0: // capabilities of the device. sl@0: // For a custom device where the software knows what the device is capable of, sl@0: // this call may be unneeded. sl@0: sl@0: // Accepts: sl@0: // A pointer returned by HidD_GetPreparsedData sl@0: // A pointer to a HIDP_CAPS structure. sl@0: sl@0: // Returns: True on success, False on failure. sl@0: // *** sl@0: sl@0: Int32 result = NativeMethods.HidP_GetCaps(preparsedData, ref Capabilities); sl@0: if ((result != 0)) sl@0: { sl@0: Debug.WriteLine(""); sl@0: Debug.WriteLine(" Usage: " + Convert.ToString(Capabilities.Usage, 16)); sl@0: Debug.WriteLine(" Usage Page: " + Convert.ToString(Capabilities.UsagePage, 16)); sl@0: Debug.WriteLine(" Input Report Byte Length: " + Capabilities.InputReportByteLength); sl@0: Debug.WriteLine(" Output Report Byte Length: " + Capabilities.OutputReportByteLength); sl@0: Debug.WriteLine(" Feature Report Byte Length: " + Capabilities.FeatureReportByteLength); sl@0: Debug.WriteLine(" Number of Link Collection Nodes: " + Capabilities.NumberLinkCollectionNodes); sl@0: Debug.WriteLine(" Number of Input Button Caps: " + Capabilities.NumberInputButtonCaps); sl@0: Debug.WriteLine(" Number of Input Value Caps: " + Capabilities.NumberInputValueCaps); sl@0: Debug.WriteLine(" Number of Input Data Indices: " + Capabilities.NumberInputDataIndices); sl@0: Debug.WriteLine(" Number of Output Button Caps: " + Capabilities.NumberOutputButtonCaps); sl@0: Debug.WriteLine(" Number of Output Value Caps: " + Capabilities.NumberOutputValueCaps); sl@0: Debug.WriteLine(" Number of Output Data Indices: " + Capabilities.NumberOutputDataIndices); sl@0: Debug.WriteLine(" Number of Feature Button Caps: " + Capabilities.NumberFeatureButtonCaps); sl@0: Debug.WriteLine(" Number of Feature Value Caps: " + Capabilities.NumberFeatureValueCaps); sl@0: Debug.WriteLine(" Number of Feature Data Indices: " + Capabilities.NumberFeatureDataIndices); sl@0: sl@0: // *** sl@0: // API function: HidP_GetValueCaps sl@0: sl@0: // Purpose: retrieves a buffer containing an array of HidP_ValueCaps structures. sl@0: // Each structure defines the capabilities of one value. sl@0: // This application doesn't use this data. sl@0: sl@0: // Accepts: sl@0: // A report type enumerator from hidpi.h, sl@0: // A pointer to a buffer for the returned array, sl@0: // The NumberInputValueCaps member of the device's HidP_Caps structure, sl@0: // A pointer to the PreparsedData structure returned by HidD_GetPreparsedData. sl@0: sl@0: // Returns: True on success, False on failure. sl@0: // *** sl@0: sl@0: Int32 vcSize = Capabilities.NumberInputValueCaps; sl@0: var valueCaps = new Byte[vcSize]; sl@0: sl@0: NativeMethods.HidP_GetValueCaps(NativeMethods.HidP_Input, valueCaps, ref vcSize, preparsedData); sl@0: sl@0: // (To use this data, copy the ValueCaps byte array into an array of structures.) sl@0: } sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: finally sl@0: { sl@0: // *** sl@0: // API function: HidD_FreePreparsedData sl@0: sl@0: // Purpose: frees the buffer reserved by HidD_GetPreparsedData. sl@0: sl@0: // Accepts: A pointer to the PreparsedData structure returned by HidD_GetPreparsedData. sl@0: sl@0: // Returns: True on success, False on failure. sl@0: // *** sl@0: sl@0: if (preparsedData != IntPtr.Zero) sl@0: { sl@0: NativeMethods.HidD_FreePreparsedData(preparsedData); sl@0: } sl@0: } sl@0: return Capabilities; sl@0: } sl@0: sl@0: /// sl@0: /// reads a Feature report from the device. sl@0: /// sl@0: /// sl@0: /// the handle for learning about the device and exchanging Feature reports. sl@0: /// contains the requested report. sl@0: sl@0: internal Boolean GetFeatureReport(SafeFileHandle hidHandle, ref Byte[] inFeatureReportBuffer) sl@0: { sl@0: try sl@0: { sl@0: Boolean success = false; sl@0: sl@0: // *** sl@0: // API function: HidD_GetFeature sl@0: // Attempts to read a Feature report from the device. sl@0: sl@0: // Requires: sl@0: // A handle to a HID sl@0: // A pointer to a buffer containing the report ID and report sl@0: // The size of the buffer. sl@0: sl@0: // Returns: true on success, false on failure. sl@0: // *** sl@0: sl@0: if (!hidHandle.IsInvalid && !hidHandle.IsClosed) sl@0: { sl@0: success = NativeMethods.HidD_GetFeature(hidHandle, inFeatureReportBuffer, inFeatureReportBuffer.Length); sl@0: sl@0: Debug.Print("HidD_GetFeature success = " + success); sl@0: } sl@0: return success; sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: sl@0: /// sl@0: /// Get the HID-class GUID sl@0: /// sl@0: /// the GUID sl@0: sl@0: internal Guid GetHidGuid() sl@0: { sl@0: Guid hidGuid = Guid.Empty; sl@0: try sl@0: { sl@0: // *** sl@0: // API function: 'HidD_GetHidGuid sl@0: sl@0: // Purpose: Retrieves the interface class GUID for the HID class. sl@0: sl@0: // Accepts: A System.Guid object for storing the GUID. sl@0: // *** sl@0: sl@0: NativeMethods.HidD_GetHidGuid(ref hidGuid); sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: return hidGuid; sl@0: } sl@0: sl@0: /// sl@0: /// Creates a 32-bit Usage from the Usage Page and Usage ID. sl@0: /// Determines whether the Usage is a system mouse or keyboard. sl@0: /// Can be modified to detect other Usages. sl@0: /// sl@0: /// sl@0: /// a HIDP_CAPS structure retrieved with HidP_GetCaps. sl@0: /// sl@0: /// sl@0: /// A String describing the Usage. sl@0: /// sl@0: sl@0: internal String GetHidUsage(NativeMethods.HIDP_CAPS myCapabilities) sl@0: { sl@0: String usageDescription = ""; sl@0: sl@0: try sl@0: { sl@0: // Create32-bit Usage from Usage Page and Usage ID. sl@0: sl@0: Int32 usage = myCapabilities.UsagePage * 256 + myCapabilities.Usage; sl@0: sl@0: if (usage == Convert.ToInt32(0X102)) sl@0: { sl@0: usageDescription = "mouse"; sl@0: } sl@0: if (usage == Convert.ToInt32(0X106)) sl@0: { sl@0: usageDescription = "keyboard"; sl@0: } sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: sl@0: return usageDescription; sl@0: } sl@0: sl@0: /// sl@0: /// reads an Input report from the device using a control transfer. sl@0: /// sl@0: /// the handle for learning about the device and exchanging Feature reports. sl@0: /// contains the requested report. sl@0: sl@0: internal Boolean GetInputReportViaControlTransfer(SafeFileHandle hidHandle, ref Byte[] inputReportBuffer) sl@0: { sl@0: var success = false; sl@0: sl@0: try sl@0: { sl@0: // *** sl@0: // API function: HidD_GetInputReport sl@0: sl@0: // Purpose: Attempts to read an Input report from the device using a control transfer. sl@0: sl@0: // Requires: sl@0: // A handle to a HID sl@0: // A pointer to a buffer containing the report ID and report sl@0: // The size of the buffer. sl@0: sl@0: // Returns: true on success, false on failure. sl@0: // *** sl@0: sl@0: if (!hidHandle.IsInvalid && !hidHandle.IsClosed) sl@0: { sl@0: success = NativeMethods.HidD_GetInputReport(hidHandle, inputReportBuffer, inputReportBuffer.Length + 1); sl@0: Debug.Print("HidD_GetInputReport success = " + success); sl@0: } sl@0: return success; sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: sl@0: /// sl@0: /// Reads an Input report from the device using an interrupt transfer. sl@0: /// sl@0: /// sl@0: /// the Filestream for writing data. sl@0: /// contains the report ID and report data. sl@0: /// sl@0: /// True on success. False on failure. sl@0: /// sl@0: sl@0: internal async Task GetInputReportViaInterruptTransfer(FileStream deviceData, Byte[] inputReportBuffer, CancellationTokenSource cts) sl@0: { sl@0: try sl@0: { sl@0: Int32 bytesRead = 0; sl@0: sl@0: // Begin reading an Input report. sl@0: sl@0: Task t = deviceData.ReadAsync(inputReportBuffer, 0, inputReportBuffer.Length, cts.Token); sl@0: sl@0: bytesRead = await t; sl@0: sl@0: // Gets to here only if the read operation completed before a timeout. sl@0: sl@0: Debug.Print("Asynchronous read completed. Bytes read = " + Convert.ToString(bytesRead)); sl@0: sl@0: // The operation has one of these completion states: sl@0: sl@0: switch (t.Status) sl@0: { sl@0: case TaskStatus.RanToCompletion: sl@0: Debug.Print("Input report received from device"); sl@0: break; sl@0: case TaskStatus.Canceled: sl@0: Debug.Print("Task canceled"); sl@0: break; sl@0: case TaskStatus.Faulted: sl@0: Debug.Print("Unhandled exception"); sl@0: break; sl@0: } sl@0: return bytesRead; sl@0: } sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: sl@0: /// sl@0: /// Retrieves the number of Input reports the HID driver will store. sl@0: /// sl@0: /// sl@0: /// a handle to a device sl@0: /// an integer to hold the returned value. sl@0: /// sl@0: /// sl@0: /// True on success, False on failure. sl@0: /// sl@0: sl@0: internal Boolean GetNumberOfInputBuffers(SafeFileHandle hidDeviceObject, ref Int32 numberOfInputBuffers) sl@0: { sl@0: try sl@0: { sl@0: // *** sl@0: // API function: HidD_GetNumInputBuffers sl@0: sl@0: // Purpose: retrieves the number of Input reports the host can store. sl@0: // Not supported by Windows 98 Gold. sl@0: // If the buffer is full and another report arrives, the host drops the sl@0: // ldest report. sl@0: sl@0: // Accepts: a handle to a device and an integer to hold the number of buffers. sl@0: sl@0: // Returns: True on success, False on failure. sl@0: // *** sl@0: sl@0: Boolean success = NativeMethods.HidD_GetNumInputBuffers(hidDeviceObject, ref numberOfInputBuffers); sl@0: sl@0: return success; sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: sl@0: /// sl@0: /// Timeout if read or write via interrupt transfer doesn't return. sl@0: /// sl@0: sl@0: internal void OnTimeout() sl@0: { sl@0: try sl@0: { sl@0: // No action required. sl@0: sl@0: Debug.Print("timeout"); sl@0: } sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: sl@0: /// sl@0: /// Attempts to open a handle to a HID. sl@0: /// sl@0: /// device path name returned by SetupDiGetDeviceInterfaceDetail sl@0: /// true if requesting read/write access for Input and Output reports sl@0: /// hidHandle - a handle to the HID sl@0: sl@0: internal SafeFileHandle OpenHandle(String devicePathName, Boolean readAndWrite) sl@0: { sl@0: SafeFileHandle hidHandle; sl@0: sl@0: try sl@0: { sl@0: if (readAndWrite) sl@0: { sl@0: // *** sl@0: // API function: sl@0: // CreateFile sl@0: sl@0: // Purpose: sl@0: // Retrieves a handle to a device. sl@0: sl@0: // Accepts: sl@0: // A device path name returned by SetupDiGetDeviceInterfaceDetail sl@0: // The type of access requested (read/write). sl@0: // FILE_SHARE attributes to allow other processes to access the device while this handle is open. sl@0: // A Security structure or IntPtr.Zero. sl@0: // A creation disposition value. Use OPEN_EXISTING for devices. sl@0: // Flags and attributes for files. Not used for devices. sl@0: // Handle to a template file. Not used. sl@0: sl@0: // Returns: a handle without read or write access. sl@0: // This enables obtaining information about all HIDs, even system sl@0: // keyboards and mice. sl@0: // Separate handles are used for reading and writing. sl@0: // *** sl@0: sl@0: hidHandle = FileIo.CreateFile(devicePathName, FileIo.GenericRead | FileIo.GenericWrite, FileIo.FileShareRead | FileIo.FileShareWrite, IntPtr.Zero, FileIo.OpenExisting, 0, IntPtr.Zero); sl@0: } sl@0: else sl@0: { sl@0: hidHandle = FileIo.CreateFile(devicePathName, 0, FileIo.FileShareRead | FileIo.FileShareWrite, IntPtr.Zero, FileIo.OpenExisting, 0, IntPtr.Zero); sl@0: } sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: return hidHandle; sl@0: } sl@0: sl@0: /// sl@0: /// Writes a Feature report to the device. sl@0: /// sl@0: /// sl@0: /// contains the report ID and report data. sl@0: /// handle to the device. sl@0: /// sl@0: /// sl@0: /// True on success. False on failure. sl@0: /// sl@0: sl@0: internal Boolean SendFeatureReport(SafeFileHandle hidHandle, Byte[] outFeatureReportBuffer) sl@0: { sl@0: try sl@0: { sl@0: // *** sl@0: // API function: HidD_SetFeature sl@0: sl@0: // Purpose: Attempts to send a Feature report to the device. sl@0: sl@0: // Accepts: sl@0: // A handle to a HID sl@0: // A pointer to a buffer containing the report ID and report sl@0: // The size of the buffer. sl@0: sl@0: // Returns: true on success, false on failure. sl@0: // *** sl@0: sl@0: Boolean success = NativeMethods.HidD_SetFeature(hidHandle, outFeatureReportBuffer, outFeatureReportBuffer.Length); sl@0: sl@0: Debug.Print("HidD_SetFeature success = " + success); sl@0: sl@0: return success; sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: sl@0: /// sl@0: /// Writes an Output report to the device using a control transfer. sl@0: /// sl@0: /// sl@0: /// contains the report ID and report data. sl@0: /// handle to the device. sl@0: /// sl@0: /// sl@0: /// True on success. False on failure. sl@0: /// sl@0: sl@0: internal Boolean SendOutputReportViaControlTransfer(SafeFileHandle hidHandle, Byte[] outputReportBuffer) sl@0: { sl@0: try sl@0: { sl@0: // *** sl@0: // API function: HidD_SetOutputReport sl@0: sl@0: // Purpose: sl@0: // Attempts to send an Output report to the device using a control transfer. sl@0: sl@0: // Accepts: sl@0: // A handle to a HID sl@0: // A pointer to a buffer containing the report ID and report sl@0: // The size of the buffer. sl@0: sl@0: // Returns: true on success, false on failure. sl@0: // *** sl@0: sl@0: Boolean success = NativeMethods.HidD_SetOutputReport(hidHandle, outputReportBuffer, outputReportBuffer.Length + 1); sl@0: sl@0: Debug.Print("HidD_SetOutputReport success = " + success); sl@0: sl@0: return success; sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: sl@0: /// sl@0: /// Writes an Output report to the device using an interrupt transfer. sl@0: /// sl@0: /// sl@0: /// the Filestream for writing data. sl@0: /// SafeFileHandle to the device. sl@0: /// contains the report ID and report data. sl@0: /// CancellationTokenSource sl@0: /// sl@0: /// sl@0: /// 1 on success. 0 on failure. sl@0: /// sl@0: sl@0: internal async Task SendOutputReportViaInterruptTransfer sl@0: (FileStream fileStreamDeviceData, SafeFileHandle hidHandle, Byte[] outputReportBuffer, CancellationTokenSource cts) sl@0: { sl@0: try sl@0: { sl@0: var success = false; sl@0: sl@0: // Begin writing the Output report. sl@0: sl@0: Task t = fileStreamDeviceData.WriteAsync(outputReportBuffer, 0, outputReportBuffer.Length, cts.Token); sl@0: sl@0: await t; sl@0: sl@0: // Gets to here only if the write operation completed before a timeout. sl@0: sl@0: Debug.Print("Asynchronous write completed"); sl@0: sl@0: // The operation has one of these completion states: sl@0: sl@0: switch (t.Status) sl@0: { sl@0: case TaskStatus.RanToCompletion: sl@0: success = true; sl@0: Debug.Print("Output report written to device"); sl@0: break; sl@0: case TaskStatus.Canceled: sl@0: Debug.Print("Task canceled"); sl@0: break; sl@0: case TaskStatus.Faulted: sl@0: Debug.Print("Unhandled exception"); sl@0: break; sl@0: } sl@0: sl@0: return success; sl@0: } sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: sl@0: /// sl@0: /// sets the number of input reports the host HID driver store. sl@0: /// sl@0: /// sl@0: /// a handle to the device. sl@0: /// the requested number of input reports. sl@0: /// sl@0: /// sl@0: /// True on success. False on failure. sl@0: /// sl@0: sl@0: internal Boolean SetNumberOfInputBuffers(SafeFileHandle hidDeviceObject, Int32 numberBuffers) sl@0: { sl@0: try sl@0: { sl@0: // *** sl@0: // API function: HidD_SetNumInputBuffers sl@0: sl@0: // Purpose: Sets the number of Input reports the host can store. sl@0: // If the buffer is full and another report arrives, the host drops the sl@0: // oldest report. sl@0: sl@0: // Requires: sl@0: // A handle to a HID sl@0: // An integer to hold the number of buffers. sl@0: sl@0: // Returns: true on success, false on failure. sl@0: // *** sl@0: sl@0: NativeMethods.HidD_SetNumInputBuffers(hidDeviceObject, numberBuffers); sl@0: return true; sl@0: } sl@0: sl@0: catch (Exception ex) sl@0: { sl@0: DisplayException(ModuleName, ex); sl@0: throw; sl@0: } sl@0: } sl@0: } sl@0: }