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: }