Exemplo n.º 1
0
        public Hid.HidD_Attributes GetAttributes()
        {
            var attributes = new Hid.HidD_Attributes();

            attributes.Size = Marshal.SizeOf(attributes);
            Hid.HidD_GetAttributes(this._handle, ref attributes);
            return(attributes);
        }
Exemplo n.º 2
0
        private static bool GetAttributes(ref DeviceInformationStructure deviceInformation)
        {
            try
            {
                deviceInformation.Attributes.Size = Marshal.SizeOf(deviceInformation.Attributes);

                if (Hid.HidD_GetAttributes(deviceInformation.HidHandle, ref deviceInformation.Attributes))
                {
                    return(true);
                }
            }
            catch
            {
                Debug.WriteLine("GetAttributes failed");
                return(false);
            }
            return(false);
        }
Exemplo n.º 3
0
        public KeyboardController()
        {
            // Get HID GUID.
            Hid.HidD_GetHidGuid(out Guid hidGuid);

            List <HidDevice> devs      = new List <HidDevice>();
            IntPtr           classDevs = SetupApi.SetupDiGetClassDevs(ref hidGuid, IntPtr.Zero, IntPtr.Zero, DiGetClassFlags.Present | DiGetClassFlags.DeviceInterface);

            try
            {
                // Enumerate HID devices.
                for (uint index = 0;; ++index)
                {
                    SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA {
                        cbSize = (uint)Marshal.SizeOf <SP_DEVICE_INTERFACE_DATA>()
                    };
                    if (!SetupApi.SetupDiEnumDeviceInterfaces(classDevs, IntPtr.Zero, ref hidGuid, index, ref deviceInterfaceData))
                    {
                        break;                         // End of list.
                    }
                    SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = new SP_DEVICE_INTERFACE_DETAIL_DATA {
                        cbSize = IntPtr.Size == 8 ? 8U : (uint)(4 + Marshal.SystemDefaultCharSize)
                    };
                    SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA {
                        cbSize = (uint)Marshal.SizeOf <SP_DEVINFO_DATA>()
                    };
                    if (SetupApi.SetupDiGetDeviceInterfaceDetail(classDevs, ref deviceInterfaceData, ref deviceInterfaceDetailData, 256U, out uint requiredSize, ref deviceInfoData))
                    {
                        // Found one.
                        // Try to open device.
                        string         devPath   = deviceInterfaceDetailData.DevicePath;
                        SafeFileHandle devHandle = Kernel32.CreateFile(devPath, Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
                                                                       Kernel32.FILE_SHARE_READ | Kernel32.FILE_SHARE_WRITE, IntPtr.Zero, Kernel32.CREATE_NEW | Kernel32.CREATE_ALWAYS, Kernel32.FILE_FLAG_OVERLAPPED, IntPtr.Zero);

                        // Get HID attributes.
                        HIDD_ATTRIBUTES attributes = default;
                        HIDP_CAPS       caps;
                        Hid.HidD_GetAttributes(devHandle, ref attributes);

                        // Match against Gigabyte keyboard product IDs.
                        if (!supportedKeyboards.TryGetValue(attributes.VendorID, out ushort[] pids))
        /// <summary>
        /// Find the Nintendo USB controller. Also save HID capabilities for device for later.
        /// </summary>
        /// <returns></returns>
        public bool FindController()
        {
            bool deviceFound = false;
            Guid hidGuid     = Guid.Empty;

            String[] devicePathName = new String[255];
            Int32    memberIndex    = 0;
            bool     success        = false;

            try
            {
                myDeviceDetected = false;
                CloseCommunications();

                // Get the Guid associated with USB HID class.
                Hid.HidD_GetHidGuid(ref hidGuid);

                Debug.WriteLineIf(WRITE_DEBUG_INFO,
                                  MyDebugging.ResultOfAPICall("Hid.HidD_GetHidGuid"));

                // Get all attached HIDs.  I am assuming there are a maximum of 128.
                deviceFound = MyDeviceManagement.FindDeviceFromGuid(hidGuid, ref devicePathName);

                if (deviceFound)
                {
                    memberIndex = 0;

                    // Loop through all USB HIDs found and look for my VID/PID.
                    do
                    {
                        // Open HID handle without read nor write access to get info.
                        hidHandle = FileIO.CreateFile(
                            devicePathName[memberIndex],
                            0,
                            FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE,
                            IntPtr.Zero,
                            FileIO.OPEN_EXISTING,
                            0,
                            0);

                        Debug.WriteLineIf(WRITE_DEBUG_INFO,
                                          MyDebugging.ResultOfAPICall("FileIO.CreateFile"));

                        if (!hidHandle.IsInvalid)
                        {
                            // Get DeviceAttribute size in bytes.
                            MyHid.DeviceAttributes.Size = Marshal.SizeOf(MyHid.DeviceAttributes);

                            // Get HID attributes.
                            success = Hid.HidD_GetAttributes(hidHandle, ref MyHid.DeviceAttributes);

                            if (success)
                            {
                                if (MyHid.DeviceAttributes.VendorID == USB_NINTENDO_VID &&
                                    MyHid.DeviceAttributes.ProductID == USB_NINTENDO_PID)
                                {
                                    myDeviceDetected = true;
                                    myDevicePathName = devicePathName[memberIndex];
                                }
                                else
                                {
                                    // Not a match - close handle.
                                    hidHandle.Close();
                                }
                            }
                            else
                            {
                                // There was a problem trying to retrieve the HID info.
                                Debug.WriteLineIf(WRITE_DEBUG_INFO,
                                                  "Error trying to get HID attributes in " +
                                                  "UsbSingleNintendoController.FindController() when calling " +
                                                  "Hid.HidD_GetAttributes(...)");
                                hidHandle.Close();
                            }
                        }

                        // Prepare to go to next index.
                        memberIndex++;
                    }while (!((myDeviceDetected || (memberIndex == devicePathName.Length))));
                }

                // If device found, wire it up to this class.
                if (myDeviceDetected)
                {
                    // Only allow a very few number of input reports to be queued.
                    MyHid.SetNumberOfInputBuffers(hidHandle, USB_NUMBER_INPUT_REPORT_BUFFERS);

                    Debug.WriteLineIf(WRITE_DEBUG_INFO,
                                      MyDebugging.ResultOfAPICall("MyHid.SetNumberOfInputBuffers"));


                    // Register for notification if HID removed or attached.
                    success = MyDeviceManagement.RegisterForDeviceNotifications(myDevicePathName,
                                                                                this.Handle, hidGuid, ref deviceNotificationHandle);

                    Debug.WriteLineIf(WRITE_DEBUG_INFO && !success,
                                      "Failed at: MyDeviceManagement.RegisterForDeviceNotifications");

                    // Get capabilities report for report sizes.
                    MyHid.Capabilities = MyHid.GetDeviceCapabilities(hidHandle);

                    Debug.WriteLineIf(WRITE_DEBUG_INFO,
                                      MyDebugging.ResultOfAPICall("MyHid.GetDeviceCapabilities"));

                    if (success)
                    {
                        // Close handle then reopen in RW mode.
                        hidHandle.Close();
                        hidHandle = FileIO.CreateFile(
                            myDevicePathName,
                            FileIO.GENERIC_READ | FileIO.GENERIC_WRITE,
                            FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE,
                            IntPtr.Zero,
                            FileIO.OPEN_EXISTING,
                            0,
                            0);

#pragma warning disable
                        Debug.WriteLineIf(WRITE_DEBUG_INFO && hidHandle.IsInvalid,
                                          "File handle invalid at: FileIO.CreateFile(read/write)");
#pragma warning restore

                        Debug.WriteLineIf(WRITE_DEBUG_INFO,
                                          MyDebugging.ResultOfAPICall("FileIO.CreateFile(read/write)"));

                        if (MyHid.Capabilities.InputReportByteLength > 0)
                        {
                            fileStreamDeviceData = new FileStream(
                                hidHandle,
                                FileAccess.ReadWrite,
                                MyHid.Capabilities.InputReportByteLength,
                                false);
                        }

                        MyHid.FlushQueue(hidHandle);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLineIf(WRITE_DEBUG_INFO, ex.Message);
                deviceFound = false;
            }

            return(deviceFound);
        }
Exemplo n.º 5
0
        public static bool FindTargetDevice(ref DeviceInformationStructure deviceInformation, bool callOther = true)
        {
            TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 开始扫描设备");

            var listOfDevicePathNames = new String[128]; // 128 is the maximum number of USB devices allowed on a single host
            var numberOfDevicesFound  = 0;

            try
            {
                // Reset the device detection flag
                var isDeviceDetected = false;
                deviceInformation.IsDeviceAttached = false;

                // Get all the devices with the correct HID GUID
                bool deviceFoundByGuid = FindHidDevices(ref listOfDevicePathNames, ref numberOfDevicesFound);

                if (deviceFoundByGuid)
                {
                    TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 找到一堆设备");
                    var listIndex = 0;
                    do
                    {
                        TmoShare.WriteLog(string.Format("DeviceDiscovery:findTargetDevice() ->遍历第{0}个设备", listIndex + 1));
                        deviceInformation.HidHandle = Kernel32.CreateFile(listOfDevicePathNames[listIndex], 0, Constants.FileShareRead | Constants.FileShareWrite, IntPtr.Zero, Constants.OpenExisting, 0, 0);

                        if (!deviceInformation.HidHandle.IsInvalid())
                        {
                            deviceInformation.Attributes.Size = Marshal.SizeOf(deviceInformation.Attributes);
                            var success = Hid.HidD_GetAttributes(deviceInformation.HidHandle, ref deviceInformation.Attributes);

                            if (success)
                            {
                                TmoShare.WriteLog(string.Format("DeviceDiscovery:findTargetDevice() -> 发现设备 VID_{0}, PID_{1} Ver_{2}",
                                                                Convert.ToString(deviceInformation.Attributes.VendorID, 16),
                                                                Convert.ToString(deviceInformation.Attributes.ProductID, 16),
                                                                Convert.ToString(deviceInformation.Attributes.VersionNumber, 16)));

                                //  Do the VID and PID of the device match our target device?
                                if ((deviceInformation.Attributes.VendorID == deviceInformation.TargetVendorId) &&
                                    (deviceInformation.Attributes.ProductID == deviceInformation.TargetProductId))
                                {
                                    // Matching device found
                                    if (string.IsNullOrWhiteSpace(deviceInformation.DevicePathName))
                                    {
                                        deviceInformation.DevicePathName = listOfDevicePathNames[listIndex];
                                        isDeviceDetected = true;
                                        TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 找到目标设备!");
                                    }
                                    else if (string.Compare(deviceInformation.DevicePathName, listOfDevicePathNames[listIndex], true) == 0)
                                    {
                                        isDeviceDetected = true;
                                        TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 找到目标设备!");
                                    }
                                    else
                                    {
                                        TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 不是目标设备... 继续寻找...");
                                        deviceInformation.HidHandle.Close();
                                    }
                                    // Store the device's pathname in the device information
                                }
                                else
                                {
                                    // Wrong device, close the handle
                                    TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 不是目标设备... 继续寻找...");
                                    deviceInformation.HidHandle.Close();
                                }
                            }
                            else
                            {
                                //  Something went rapidly south...  give up!
                                TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 识别设备失败, 继续下一个!");
                                deviceInformation.HidHandle.Close();
                            }
                        }
                        else
                        {
                            TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 句柄创建失败");
                        }

                        //  Move to the next device, or quit if there are no more devices to examine
                        listIndex++;
                    }while (!((isDeviceDetected || (listIndex == numberOfDevicesFound))));
                }

                // If we found a matching device then we need discover more details about the attached device
                // and then open read and write handles to the device to allow communication
                if (isDeviceDetected)
                {
                    // Query the HID device's capabilities (primarily we are only really interested in the
                    // input and output report byte lengths as this allows us to validate information sent
                    // to and from the device does not exceed the devices capabilities.
                    //
                    // We could determine the 'type' of HID device here too, but since this class is only
                    // for generic HID communication we don't care...

                    if (!callOther)
                    {
                        // Open the readHandle to the device
                        TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 开始创建读文件句柄");
                        deviceInformation.ReadHandle = Kernel32.CreateFile(
                            deviceInformation.DevicePathName,
                            Constants.GenericRead,
                            Constants.FileShareRead | Constants.FileShareWrite,
                            IntPtr.Zero,
                            Constants.OpenExisting,
                            Constants.FileFlagOverlapped,
                            0);

                        // Did we open the readHandle successfully?
                        if (deviceInformation.ReadHandle.IsInvalid())
                        {
                            TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 读文件句柄创建失败" + Marshal.GetLastWin32Error());
                            return(false);
                        }

                        //Open the writeHandel to the device
                        TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 开始创建写文件句柄");
                        deviceInformation.WriteHandle = Kernel32.CreateFile(
                            deviceInformation.DevicePathName,
                            Constants.GenericWrite,
                            Constants.FileShareWrite | Constants.FileShareRead,
                            IntPtr.Zero,
                            Constants.OpenExisting, 0, 0);

                        // Did we open the writeHandle successfully?
                        if (deviceInformation.WriteHandle.IsInvalid())
                        {
                            TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 写文件句柄创建失败" + Marshal.GetLastWin32Error());
                            return(false);
                        }
                    }

                    QueryDeviceCapabilities(ref deviceInformation);
                    // Device is now discovered and ready for use, update the status
                    deviceInformation.IsDeviceAttached = true;
                    return(true);
                }

                //  The device wasn't detected.
                TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 未找到目标设备!");
                return(false);
            }
            catch (Exception ex)
            {
                TmoShare.WriteLog("DeviceDiscovery:findTargetDevice() -> 发生异常:" + ex.Message);
                return(false);
            }
        }
        ///  <summary>
        ///  Uses a series of API calls to locate a HID-class device
        ///  by its Vendor ID and Product ID.
        ///  Fills myDevicePathName with a path to device found, readHandle and writeHandle. Registers for Device Notifications (attached / detached type of events).
        ///  </summary>
        ///
        ///  <returns>
        ///   True if the device is detected, False if not detected.
        ///  </returns>

        private Boolean FindTheHid(Int32 myVendorID, Int32 myProductID)
        {
            Boolean someHidDevicesFound = false;

            String[] devicePathName = new String[128];
            String   functionName   = "";
            Guid     hidGuid        = Guid.Empty;
            Int32    memberIndex    = 0;
            Boolean  success        = false;

            try
            {
                myDeviceDetected = false;

                Tracer.Trace(string.Format("FindTheHid(0x{0:X04}, 0x{1:X04})", myVendorID, myProductID));

                //  ***
                //  API function: 'HidD_GetHidGuid

                //  Purpose: Retrieves the interface class GUID for the HID class.

                //  Accepts: 'A System.Guid object for storing the GUID.
                //  ***

                Hid.HidD_GetHidGuid(ref hidGuid);

                functionName = "GetHidGuid";
                Tracer.Trace(MyDebugging.ResultOfAPICall(functionName));
                Tracer.Trace("  GUID for system HIDs: " + hidGuid.ToString());

                //  Fill an array with the device path names of all attached HIDs.

                someHidDevicesFound = MyDeviceManagement.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.
                //
                //  Fill myDevicePathName with a path to device found.

                if (someHidDevicesFound)
                {
                    memberIndex = 0;

                    // Tracer.Trace("  total number of HID devices: " + devicePathName.Length);        // will be something like 128, a lot of empty paths there.

                    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 or IntPtr.Zero.
                        //  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 without read or write access.
                        //  This enables obtaining information about all HIDs, even system
                        //  keyboards and mice.
                        //  Separate handles are used for reading and writing.
                        //  ***

                        if (!string.IsNullOrEmpty(devicePathName[memberIndex]))
                        {
                            Tracer.Trace("  trying HID device path '" + devicePathName[memberIndex] + "'");

                            hidHandle = FileIO.CreateFile(devicePathName[memberIndex], 0, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);

                            functionName = "CreateFile";
                            Tracer.Trace(MyDebugging.ResultOfAPICall(functionName));
                            Tracer.Trace("  FindTheHid(): some HID device found, returned handle: " + hidHandle.ToString());

                            if (!hidHandle.IsInvalid)
                            {
                                //  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.
                                //  ***

                                success = Hid.HidD_GetAttributes(hidHandle, ref MyHid.DeviceAttributes);

                                if (success)
                                {
                                    Tracer.Trace("  HIDD_ATTRIBUTES structure filled without error.");
                                    Tracer.Trace("  Structure size: " + MyHid.DeviceAttributes.Size);
                                    Tracer.Trace(string.Format("  Vendor ID: 0x{0:X04}", MyHid.DeviceAttributes.VendorID));
                                    Tracer.Trace(string.Format("  Product ID: 0x{0:X04}", MyHid.DeviceAttributes.ProductID));
                                    Tracer.Trace(string.Format("  Version Number: 0x{0:X04}", MyHid.DeviceAttributes.VersionNumber));

                                    //  Find out if the device matches the one we're looking for.

                                    if ((MyHid.DeviceAttributes.VendorID == myVendorID) && (MyHid.DeviceAttributes.ProductID == myProductID))
                                    {
                                        Tracer.Trace("  My device detected");

                                        myDeviceDetected = true;

                                        //  Save the DevicePathName for OnDeviceChange().

                                        myDevicePathName = devicePathName[memberIndex];
                                    }
                                    else
                                    {
                                        //  It's not a match, so close the handle.

                                        Tracer.Trace("  (This is not My Device)");

                                        myDeviceDetected = false;
                                        hidHandle.Close();
                                    }
                                }
                                else
                                {
                                    //  There was a problem in retrieving the information.

                                    Tracer.Trace("  Error in filling HIDD_ATTRIBUTES structure.");
                                    myDeviceDetected = false;
                                    hidHandle.Close();
                                }
                            }
                        }

                        //  Keep looking until we find the device or there are no devices left to examine.

                        memberIndex = memberIndex + 1;
                    }while (!((myDeviceDetected || (memberIndex == devicePathName.Length))));
                }

                if (myDeviceDetected)
                {
                    //  The device was detected.
                    //  Register to receive notifications if the device is removed or attached.

                    success = MyDeviceManagement.RegisterForDeviceNotifications(myDevicePathName, WindowHandle, hidGuid, ref deviceNotificationHandle);

                    Tracer.Trace("RegisterForDeviceNotifications = " + success);

                    //  Learn the capabilities of the device.

                    MyHid.Capabilities = MyHid.GetDeviceCapabilities(hidHandle);

                    if (success)
                    {
                        //  Find out if the device is a system mouse or keyboard.

                        hidUsage = MyHid.GetHidUsage(MyHid.Capabilities);

                        //  Get the Input report buffer size.

                        GetInputReportBufferSize();

                        //  Get handles to use in requesting Input and Output reports.

                        readHandle = FileIO.CreateFile(myDevicePathName, FileIO.GENERIC_READ, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, FileIO.FILE_FLAG_OVERLAPPED, 0);

                        functionName = "CreateFile, ReadHandle";
                        Tracer.Trace(MyDebugging.ResultOfAPICall(functionName));
                        Tracer.Trace("  FindTheHid(): success, returned handle: " + readHandle.ToString());

                        if (readHandle.IsInvalid)
                        {
                            exclusiveAccess = true;
                            Tracer.Error("The device is a system " + hidUsage + ". Applications can access Feature reports only.");
                        }
                        else
                        {
                            writeHandle = FileIO.CreateFile(myDevicePathName, FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);

                            functionName = "CreateFile, WriteHandle";
                            Tracer.Trace(MyDebugging.ResultOfAPICall(functionName));
                            Tracer.Trace("  FindTheHid(): handle valid, returned handle: " + writeHandle.ToString());

                            //  Flush any waiting reports in the input buffer. (optional)

                            MyHid.FlushQueue(readHandle);
                        }
                    }
                }
                else
                {
                    //  The device wasn't detected.

                    Tracer.Error(string.Format("My Device not found - need a HID with vendorId={0}, productId={1}.", vendorId, productId));
                }
                return(myDeviceDetected);
            }
            catch (Exception ex)
            {
                Tracer.Error(ex);
                throw;
            }
        }
Exemplo n.º 7
0
        public static bool FindTargetDevice(ref DeviceInformationStructure deviceInformation)
        {
            Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Method called");

            var listOfDevicePathNames = new String[128]; // 128 is the maximum number of USB devices allowed on a single host
            var numberOfDevicesFound  = 0;

            try
            {
                // Reset the device detection flag
                var isDeviceDetected = false;
                deviceInformation.IsDeviceAttached = false;

                // Get all the devices with the correct HID GUID
                var deviceFoundByGuid = FindHidDevices(ref listOfDevicePathNames, ref numberOfDevicesFound);

                if (deviceFoundByGuid)
                {
                    Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Devices with matching GUID found...");
                    var listIndex = 0;

                    do
                    {
                        Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Performing CreateFile to listIndex {0}", listIndex);
                        deviceInformation.HidHandle = Kernel32.CreateFile(listOfDevicePathNames[listIndex], 0, Constants.FileShareRead | Constants.FileShareWrite, IntPtr.Zero, Constants.OpenExisting, 0, 0);

                        if (!deviceInformation.HidHandle.IsInvalid)
                        {
                            deviceInformation.Attributes.Size = Marshal.SizeOf(deviceInformation.Attributes);
                            var success = Hid.HidD_GetAttributes(deviceInformation.HidHandle, ref deviceInformation.Attributes);

                            if (success)
                            {
                                Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Found device with VID {0}, PID {1} and Version number {2}",
                                                Convert.ToString(deviceInformation.Attributes.VendorID, 16),
                                                Convert.ToString(deviceInformation.Attributes.ProductID, 16),
                                                Convert.ToString(deviceInformation.Attributes.VersionNumber, 16));

                                //  Do the VID and PID of the device match our target device?
                                if ((deviceInformation.Attributes.VendorID == deviceInformation.TargetVendorId) &&
                                    (deviceInformation.Attributes.ProductID == deviceInformation.TargetProductId))
                                {
                                    // Matching device found
                                    Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Device with matching VID and PID found!");
                                    isDeviceDetected = true;

                                    // Store the device's pathname in the device information
                                    deviceInformation.DevicePathName = listOfDevicePathNames[listIndex];
                                }
                                else
                                {
                                    // Wrong device, close the handle
                                    Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Device didn't match... Continuing...");
                                    deviceInformation.HidHandle.Close();
                                }
                            }
                            else
                            {
                                //  Something went rapidly south...  give up!
                                Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Something bad happened - couldn't fill the HIDD_ATTRIBUTES, giving up!");
                                deviceInformation.HidHandle.Close();
                            }
                        }

                        //  Move to the next device, or quit if there are no more devices to examine
                        listIndex++;
                    }while (!((isDeviceDetected || (listIndex == numberOfDevicesFound + 1))));
                }

                // If we found a matching device then we need discover more details about the attached device
                // and then open read and write handles to the device to allow communication
                if (isDeviceDetected)
                {
                    // Query the HID device's capabilities (primarily we are only really interested in the
                    // input and output report byte lengths as this allows us to validate information sent
                    // to and from the device does not exceed the devices capabilities.
                    //
                    // We could determine the 'type' of HID device here too, but since this class is only
                    // for generic HID communication we don't care...
                    QueryDeviceCapabilities(ref deviceInformation);

                    // Open the readHandle to the device
                    Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Opening a readHandle to the device");
                    deviceInformation.ReadHandle = Kernel32.CreateFile(
                        deviceInformation.DevicePathName,
                        Constants.GenericRead,
                        Constants.FileShareRead | Constants.FileShareWrite,
                        IntPtr.Zero, Constants.OpenExisting,
                        Constants.FileFlagOverlapped,
                        0);

                    // Did we open the readHandle successfully?
                    if (deviceInformation.ReadHandle.IsInvalid)
                    {
                        Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Unable to open a readHandle to the device!");
                        return(false);
                    }

                    Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Opening a writeHandle to the device");
                    deviceInformation.WriteHandle = Kernel32.CreateFile(
                        deviceInformation.DevicePathName,
                        Constants.GenericWrite,
                        Constants.FileShareRead | Constants.FileShareWrite,
                        IntPtr.Zero,
                        Constants.OpenExisting, 0, 0);

                    // Did we open the writeHandle successfully?
                    if (deviceInformation.WriteHandle.IsInvalid)
                    {
                        Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> Unable to open a writeHandle to the device!");

                        // Attempt to close the writeHandle
                        deviceInformation.WriteHandle.Close();
                        return(false);
                    }

                    // Device is now discovered and ready for use, update the status
                    deviceInformation.IsDeviceAttached = true;
                    return(true);
                }

                //  The device wasn't detected.
                Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> No matching device found!");
                return(false);
            }
            catch (Exception)
            {
                Debug.WriteLine("usbGenericHidCommunication:findTargetDevice() -> EXCEPTION: Unknown - device not found");
                return(false);
            }
        }
Exemplo n.º 8
0
        ///  <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>

        public static Boolean FindTheHid(
            int myVendorID
            , int myProductID
            , ref IntPtr FrmMyHandle
            , ref IntPtr deviceNotificationHandle
            , ref Boolean exclusiveAccess
            , ref String hidUsage
            , ref Boolean myDeviceDetected
            , ref String myDevicePathName
            , ref FileStream fileStreamDeviceData
            , ref SafeFileHandle hidHandle
            , ref DeviceManagement MyDeviceManagement
            , ref Hid MyHid
            , ref string message
            , ref string txtInputReportBufferSize
            )
        {
            Boolean deviceFound = false;

            String[] devicePathName = new String[128];
            Guid     hidGuid        = Guid.Empty;
            Int32    memberIndex    = 0;
            //Int32 myProductID = 0;
            //Int32 myVendorID = 0;
            Boolean success = false;

            try
            {
                myDeviceDetected = false;
                CloseCommunications(
                    ref myDeviceDetected
                    , ref fileStreamDeviceData
                    , ref hidHandle
                    );

                //  Get the device's Vendor ID and Product ID

                //myVendorID = Main.CardReader_VID;
                //myProductID = Main.CardReader_PID;

                //  ***
                //  API function: 'HidD_GetHidGuid
                //  Purpose: Retrieves the interface class GUID for the HID class.
                //  Accepts: 'A System.Guid object for storing the GUID.
                //  ***

                Hid.HidD_GetHidGuid(ref hidGuid);

                //  Fill an array with the device path names of all attached HIDs.
                deviceFound = MyDeviceManagement.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)
                {
                    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 or IntPtr.Zero.
                        //  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 without read or write access.
                        //  This enables obtaining information about all HIDs, even system
                        //  keyboards and mice.
                        //  Separate handles are used for reading and writing.
                        //  ***

                        // Open the handle without read/write access to enable getting information about any HID, even system keyboards and mice.
                        hidHandle = FileIO.CreateFile(devicePathName[memberIndex], 0, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);

                        if (!hidHandle.IsInvalid)
                        {
                            //  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.
                            //  ***

                            success = Hid.HidD_GetAttributes(hidHandle, ref MyHid.DeviceAttributes);

                            if (success)
                            {
                                //  Find out if the device matches the one we're looking for.
                                if ((MyHid.DeviceAttributes.VendorID == myVendorID) && (MyHid.DeviceAttributes.ProductID == myProductID))
                                {
                                    //  Display the information in form's list box.
                                    message = "was found.";

                                    myDeviceDetected = true;

                                    //  Save the DevicePathName for OnDeviceChange().
                                    myDevicePathName = devicePathName[memberIndex];
                                }
                                else
                                {
                                    //  It's not a match, so close the handle.

                                    myDeviceDetected = false;
                                    hidHandle.Close();
                                }
                            }
                            else
                            {
                                //  There was a problem in retrieving the information.

                                //Debug.WriteLine("  Error in filling HIDD_ATTRIBUTES structure.");
                                myDeviceDetected = false;
                                hidHandle.Close();
                            }
                        }

                        //  Keep looking until we find the device or there are no devices left to examine.

                        memberIndex = memberIndex + 1;
                    }while (!((myDeviceDetected || (memberIndex == devicePathName.Length))));
                }

                if (myDeviceDetected)
                {
                    //  The device was detected.
                    //  Register to receive notifications if the device is removed or attached.

                    success = MyDeviceManagement.RegisterForDeviceNotifications(myDevicePathName, FrmMyHandle, hidGuid, ref deviceNotificationHandle);

                    //  Learn the capabilities of the device.

                    MyHid.Capabilities = MyHid.GetDeviceCapabilities(hidHandle);

                    if (success)
                    {
                        //  Find out if the device is a system mouse or keyboard.

                        hidUsage = MyHid.GetHidUsage(MyHid.Capabilities);

                        //  Get the Input report buffer size.

                        GetInputReportBufferSize(
                            ref exclusiveAccess
                            , ref hidHandle
                            , ref MyHid
                            , ref txtInputReportBufferSize
                            );

                        //Close the handle and reopen it with read/write access.

                        hidHandle.Close();
                        hidHandle = FileIO.CreateFile(myDevicePathName, FileIO.GENERIC_READ | FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);

                        if (hidHandle.IsInvalid)
                        {
                            exclusiveAccess = true;
                        }
                        else
                        {
                            if (MyHid.Capabilities.InputReportByteLength > 0)
                            {
                                //  Set the size of the Input report buffer.

                                Byte[] inputReportBuffer = null;
                                inputReportBuffer = new Byte[MyHid.Capabilities.InputReportByteLength];

                                fileStreamDeviceData = new FileStream(hidHandle, FileAccess.Read | FileAccess.Write, inputReportBuffer.Length, false);
                            }

                            if (MyHid.Capabilities.OutputReportByteLength > 0)
                            {
                                Byte[] outputReportBuffer = null;
                                outputReportBuffer = new Byte[MyHid.Capabilities.OutputReportByteLength];
                            }

                            //  Flush any waiting reports in the input buffer. (optional)

                            MyHid.FlushQueue(hidHandle);
                        }
                    }
                }
                else
                {
                    //  The device wasn't detected.
                    myDeviceDetected = false;
                    message          = "not found.";
                }

                return(myDeviceDetected);
            }

            catch (Exception ex)
            {
                DisplayException("FindTheHid", ex);
                //throw;
            }

            return(false);
        }
Exemplo n.º 9
0
        private void _DeviceSearchThread()
        {
            _Logger.Info("Started");
            while (_Running)
            {
                var loopStart = DateTime.Now;

                #region Device enumeration

                var devices = new List <UsbDevice>();

                var detailDataBuffer = IntPtr.Zero;
                var deviceInfoSet    = IntPtr.Zero;
                try
                {
                    int listIndex           = 0;
                    int lastError           = 0;
                    var deviceInterfaceData = new SpDeviceInterfaceData();

                    var systemHidGuid = new Guid();
                    Hid.HidD_GetHidGuid(ref systemHidGuid);
                    deviceInfoSet = SetupApi.SetupDiGetClassDevs(ref systemHidGuid, IntPtr.Zero, IntPtr.Zero, Constants.DigcfPresent | Constants.DigcfDeviceinterface);
                    deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                    while (SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref systemHidGuid, listIndex++, ref deviceInterfaceData) || (lastError = Marshal.GetLastWin32Error()) != Constants.ERROR_NO_MORE_ITEMS)
                    {
                        if (lastError == 0)
                        {
                            int bufferSize = 0;
                            SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
                            detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
                            Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
                            if (SetupApi.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero))
                            {
                                var pDevicePathName = IntPtr.Add(detailDataBuffer, 4);
                                var devicePath      = Marshal.PtrToStringAuto(pDevicePathName);

                                // Get device capabilities (to determine usage page)
                                using (var hidHandle = Kernel32.CreateFile(devicePath, 0, Constants.FileShareRead | Constants.FileShareWrite, IntPtr.Zero, Constants.OpenExisting, 0, 0))
                                {
                                    var preparsedData = IntPtr.Zero;
                                    try
                                    {
                                        preparsedData = new IntPtr();
                                        Hid.HidD_GetPreparsedData(hidHandle, ref preparsedData);
                                        var caps = new HidpCaps();
                                        Hid.HidP_GetCaps(preparsedData, ref caps);

                                        var attrs = new HiddAttributes();
                                        Hid.HidD_GetAttributes(hidHandle, ref attrs);

                                        // Only add the device if it has our VID, PID, and RAW usage page
                                        var deviceClass = FindDeviceClass(attrs.VendorID, attrs.ProductID, attrs.VersionNumber, caps.UsagePage);
                                        if (deviceClass != null)
                                        {
                                            var manufacturer = new StringBuilder(STRING_SIZE_LIMIT);
                                            var product      = new StringBuilder(STRING_SIZE_LIMIT);
                                            var serial       = new StringBuilder(STRING_SIZE_LIMIT);
                                            Hid.HidD_GetManufacturerString(hidHandle, manufacturer, STRING_SIZE_LIMIT);
                                            Hid.HidD_GetProductString(hidHandle, product, STRING_SIZE_LIMIT);
                                            Hid.HidD_GetSerialNumberString(hidHandle, serial, STRING_SIZE_LIMIT);
                                            var device = new UsbDevice(new DeviceInstance(deviceClass, devicePath, manufacturer.ToString(), product.ToString(), serial.ToString()), caps);
                                            devices.Add(device);
                                        }
                                    }
                                    finally
                                    {
                                        // Free up the memory before finishing
                                        if (preparsedData != IntPtr.Zero)
                                        {
                                            Hid.HidD_FreePreparsedData(preparsedData);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    _Logger.Error(ex, "Error scanning for devices:");
                    devices.Clear();
                }
                finally
                {
                    // Clean up the unmanaged memory allocations and free resources held by the windows API
                    if (detailDataBuffer != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(detailDataBuffer);
                    }
                    if (deviceInfoSet != IntPtr.Zero)
                    {
                        SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                    }
                }

                var addedDevices   = devices.Except(_CurrentDevices);
                var removedDevices = _CurrentDevices.Except(devices);

                _CurrentDevices = devices;

                if (DeviceRemoved != null)
                {
                    foreach (var dev in removedDevices)
                    {
                        _Logger.Info("Device removed: {0}", dev);
                        DeviceRemoved(this, new DeviceEventArgs(dev.Instance));
                    }
                }
                if (DeviceAdded != null)
                {
                    foreach (var dev in addedDevices)
                    {
                        _Logger.Info("Device added: {0}", dev);
                        DeviceAdded(this, new DeviceEventArgs(dev.Instance));
                    }
                }

                #endregion

                #region Active device I/O

                // If we receive a request to change the active device while we are processing messages, we need to stop immediately because they are about to become invalid
                {
                    byte[] msg;
                    while (true)
                    {
                        byte[] response = null;

                        // Block until SetActiveDevice finishes
                        lock (_LockObject)
                        {
                            // If we created a new message queue in the call to SetActiveDevice, this will return false and we'll break out of the loop
                            if (_ActiveDevice == null || !_MessageQueue.TryDequeue(out msg))
                            {
                                break;
                            }
                            try
                            {
                                response = SendDeviceRequest(_ActiveDevice, msg);
                            }
                            catch (Exception ex)
                            {
                                _Logger.Error(ex, "Error communicating with device: {0} (0x{1:X8})", ex.Message, ex.HResult);
                            }
                        }

                        if (response != null)
                        {
                            ProcessResponse(msg, response);
                        }
                        else
                        {
                            _Logger.Error("Failed to read data from device. req = {0}", FormatByteArray(msg));
                        }
                    }
                }

                // Get LED config (it may have changed)
                {
                    byte[] response = null;
                    byte[] msg      = CreateSimpleMessage(hid_pkt_req.HID_PKT_REQ_CONFIG_LED_GET);

                    // Block until SetActiveDevice finishes
                    lock (_LockObject)
                    {
                        if (_ActiveDevice != null)
                        {
                            try
                            {
                                response = SendDeviceRequest(_ActiveDevice, msg);
                            }
                            catch (Exception ex)
                            {
                                _Logger.Error(ex, "Error communicating with device: {0} (0x{1:X8})", ex.Message, ex.HResult);
                            }
                        }
                    }

                    if (response != null)
                    {
                        ProcessResponse(msg, response);
                    }
                }

                // Get LED status
                {
                    byte[] response = null;
                    byte[] msg      = new byte[2];
                    msg[0] = (byte)hid_pkt_req.HID_PKT_REQ_LED_STATUS;
                    msg[1] = 0;

                    var ledStatuses = new List <LedColor>();

                    do
                    {
                        lock (_LockObject)
                        {
                            if (_ActiveDevice != null)
                            {
                                try
                                {
                                    response = SendDeviceRequest(_ActiveDevice, msg);
                                }
                                catch (Exception ex)
                                {
                                    _Logger.Error(ex, "Error communicating with device: {0} (0x{1:X8})", ex.Message, ex.HResult);
                                }
                            }
                        }

                        if (response != null)
                        {
                            // Parse response
                            for (byte i = 0; i < response[1] && i < 10; i++)
                            {
                                var led = new LedColor(
                                    response[i * 3 + 2],
                                    response[i * 3 + 3],
                                    response[i * 3 + 4]
                                    );
                                ledStatuses.Add(led);
                            }

                            msg[1] += 10;
                        }
                    } while (response != null && response[0] == (byte)hid_pkt_res.HID_PKT_RES_MORE);

                    LedStatusReceived?.Invoke(this, new LedStatusReceivedEventArgs(ledStatuses));
                }

                #endregion

                // Wait until the entire loop execution is at least 100ms
                var loopTime = DateTime.Now - loopStart;
                if (loopTime < LOOP_DELAY)
                {
                    var waitTime = LOOP_DELAY - loopTime;
                    Thread.Sleep(waitTime);
                }
            }
        }