Exemplo n.º 1
0
        public IEnumerable <HidDeviceInfo> CollectInfo()
        {
            var result = new List <HidDeviceInfo>();

            Guid hidGuid;

            Hid.HidD_GetHidGuid(out hidGuid);

            var deviceInfoList = SetupApi.SetupDiGetClassDevs(ref hidGuid, null, IntPtr.Zero,
                                                              Constants.DIGCF_DEVICEINTERFACE | Constants.DIGCF_PRESENT);

            if (deviceInfoList != IntPtr.Zero && deviceInfoList != Constants.INVALID_HANDLE_VALUE)
            {
                var deviceInfo = new SetupApi.SP_DEVICE_INTERFACE_DATA();
                deviceInfo.cbSize = Marshal.SizeOf(deviceInfo);

                for (var i = 0; ; i++)
                {
                    if (!SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoList, 0, ref hidGuid, Convert.ToUInt32(i),
                                                              ref deviceInfo))
                    {
                        break;
                    }

                    var path = this.GetPath(deviceInfoList, deviceInfo);

                    var device = new HidDevice();

                    if (device.Open(path))
                    {
                        var attributes = device.GetAttributes();
                        var vendor     = device.GetVendorString();
                        var product    = device.GetProductString();

                        result.Add(new HidDeviceInfo(
                                       path,
                                       attributes.VendorID,
                                       attributes.ProductID,
                                       attributes.VersionString,
                                       vendor,
                                       product));

                        device.Close();
                    }
                }

                SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoList);
            }

            return(result);
        }
Exemplo n.º 2
0
        public static bool FindHidDevices(ref List <string> DevicePathNames)
        {
            Debug.WriteLine("findHidDevices() -> Method called");

            // Initialize the internal variables required for performing the search
            var  bufferSize       = 0;
            var  detailDataBuffer = IntPtr.Zero;
            bool deviceFound;
            var  deviceInfoSet = new IntPtr();
            var  lastDevice    = false;
            int  listIndex;
            var  deviceInterfaceData = new SpDeviceInterfaceData();

            // Get the required GUID
            var systemHidGuid = new Guid();

            Hid.HidD_GetHidGuid(ref systemHidGuid);
            Debug.WriteLine(string.Format("findHidDevices() -> Fetched GUID for HID devices ({0})", systemHidGuid.ToString()));

            try
            {
                // Here we populate a list of plugged-in devices matching our class GUID (DIGCF_PRESENT specifies that the list
                // should only contain devices which are plugged in)
                Debug.WriteLine("findHidDevices() -> Using SetupDiGetClassDevs to get all devices with the correct GUID");
                deviceInfoSet = SetupApi.SetupDiGetClassDevs(ref systemHidGuid, IntPtr.Zero, IntPtr.Zero, Constants.DigcfPresent | Constants.DigcfDeviceinterface);

                // Reset the deviceFound flag and the memberIndex counter
                deviceFound = false;
                listIndex   = 0;

                deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                // Look through the retrieved list of class GUIDs looking for a match on our interface GUID
                do
                {
                    //Debug.WriteLine("usbGenericHidCommunication:findHidDevices() -> Enumerating devices");
                    var success = SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref systemHidGuid, listIndex, ref deviceInterfaceData);

                    if (!success)
                    {
                        //Debug.WriteLine("usbGenericHidCommunication:findHidDevices() -> No more devices left - giving up");
                        lastDevice = true;
                    }
                    else
                    {
                        // The target device has been found, now we need to retrieve the device path so we can open
                        // the read and write handles required for USB communication

                        // First call is just to get the required buffer size for the real request
                        SetupApi.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref deviceInterfaceData,
                            IntPtr.Zero,
                            0,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Allocate some memory for the buffer
                        detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
                        Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                        // Second call gets the detailed data buffer
                        //Debug.WriteLine("usbGenericHidCommunication:findHidDevices() -> Getting details of the device");
                        SetupApi.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref deviceInterfaceData,
                            detailDataBuffer,
                            bufferSize,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Skip over cbsize (4 bytes) to get the address of the devicePathName.
                        var pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4);

                        // Get the String containing the devicePathName.
                        DevicePathNames.Add(Marshal.PtrToStringAuto(pDevicePathName));

                        //Debug.WriteLine(string.Format("usbGenericHidCommunication:findHidDevices() -> Found matching device (memberIndex {0})", memberIndex));
                        deviceFound = true;
                    }
                    listIndex += 1;
                }while (lastDevice != true);
            }
            catch (Exception)
            {
                // Something went badly wrong... output some debug and return false to indicated device discovery failure
                Debug.WriteLine("findHidDevices() -> EXCEPTION: Something went south whilst trying to get devices with matching GUIDs - giving up!");
                return(false);
            }
            finally
            {
                // Clean up the unmanaged memory allocations
                if (detailDataBuffer != IntPtr.Zero)
                {
                    // Free the memory allocated previously by AllocHGlobal.
                    Marshal.FreeHGlobal(detailDataBuffer);
                }

                if (deviceInfoSet != IntPtr.Zero)
                {
                    SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                }
            }

            if (deviceFound)
            {
                Debug.WriteLine(string.Format("findHidDevices() -> Found {0} devices with matching GUID", (DevicePathNames.Count).ToString(CultureInfo.InvariantCulture)));
            }
            else
            {
                Debug.WriteLine("findHidDevices() -> No matching devices found");
            }

            return(deviceFound);
        }
Exemplo n.º 3
0
        /// <summary>
        /// registerForDeviceNotification - registers the window (identified by the windowHandle) for
        /// device notification messages from Windows
        /// </summary>
        public bool RegisterForDeviceNotifications(IntPtr windowHandle1)
        {
            Debug.WriteLine("usbGenericHidCommunication:registerForDeviceNotifications() -> Method called");

            // A DEV_BROADCAST_DEVICEINTERFACE header holds information about the request.
            var devBroadcastDeviceInterface       = new DevBroadcastDeviceinterface();
            var devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;

            // Get the required GUID
            var systemHidGuid = new Guid();

            Hid.HidD_GetHidGuid(ref systemHidGuid);

            try
            {
                // Set the parameters in the DEV_BROADCAST_DEVICEINTERFACE structure.
                var size = Marshal.SizeOf(devBroadcastDeviceInterface);
                devBroadcastDeviceInterface.dbcc_size       = size;
                devBroadcastDeviceInterface.dbcc_devicetype = Constants.DbtDevtypDeviceinterface;
                devBroadcastDeviceInterface.dbcc_reserved   = 0;
                devBroadcastDeviceInterface.dbcc_classguid  = systemHidGuid;

                devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size);
                Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);
                // Register for notifications and store the returned handle
                DeviceNotificationHandle = User32.RegisterDeviceNotification(Handle, devBroadcastDeviceInterfaceBuffer, Constants.DeviceNotifyWindowHandle);

                Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);

                if ((DeviceNotificationHandle.ToInt32() == IntPtr.Zero.ToInt32()))
                {
                    Debug.WriteLine(
                        "usbGenericHidCommunication:registerForDeviceNotifications() -> Notification registration failed");
                    return(false);
                }
                else
                {
                    Debug.WriteLine(
                        "usbGenericHidCommunication:registerForDeviceNotifications() -> Notification registration succeded");
                    return(true);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(
                    "usbGenericHidCommunication:registerForDeviceNotifications() -> EXCEPTION: An unknown exception has occured!");
                Debug.WriteLine(ex.Message);
            }
            finally
            {
                // Free the memory allocated previously by AllocHGlobal.
                if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
                {
                    try
                    {
                        Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }
                }
            }

            return(false);
        }
        /// <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 FindHidDevices(ref string[] listOfDevicePathNames, ref int numberOfDevicesFound)
        {
            TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 开始查找所有HID设备");

            // Initialise the internal variables required for performing the search
            var  bufferSize       = 0;
            var  detailDataBuffer = IntPtr.Zero;
            bool deviceFound;
            var  deviceInfoSet = new IntPtr();
            var  lastDevice    = false;
            int  listIndex;
            var  deviceInterfaceData = new SpDeviceInterfaceData();

            // Get the required GUID
            var systemHidGuid = new Guid();

            Hid.HidD_GetHidGuid(ref systemHidGuid);
            TmoShare.WriteLog(string.Format("DeviceDiscovery:findHidDevices() -> 找到HID设备全局 GUID {0}", systemHidGuid));

            try
            {
                // Here we populate a list of plugged-in devices matching our class GUID (DIGCF_PRESENT specifies that the list
                // should only contain devices which are plugged in)
                TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 获取所有HID设备句柄");
                deviceInfoSet = SetupApi.SetupDiGetClassDevs(ref systemHidGuid, IntPtr.Zero, IntPtr.Zero, Constants.DigcfPresent | Constants.DigcfDeviceinterface);

                // Reset the deviceFound flag and the memberIndex counter
                deviceFound = false;
                listIndex   = 0;

                deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                // Look through the retrieved list of class GUIDs looking for a match on our interface GUID
                do
                {
                    TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 获取设备信息");
                    var success = SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref systemHidGuid, listIndex, ref deviceInterfaceData);

                    if (!success)
                    {
                        TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 已经找到最后一个-停止");
                        lastDevice = true;
                    }
                    else
                    {
                        // The target device has been found, now we need to retrieve the device path so we can open
                        // the read and write handles required for USB communication

                        // First call is just to get the required buffer size for the real request
                        SetupApi.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref deviceInterfaceData,
                            IntPtr.Zero,
                            0,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Allocate some memory for the buffer
                        detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
                        Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                        // Second call gets the detailed data buffer
                        TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 获取设备详细信息");
                        SetupApi.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref deviceInterfaceData,
                            detailDataBuffer,
                            bufferSize,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Skip over cbsize (4 bytes) to get the address of the devicePathName.
                        var pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4);

                        // Get the String containing the devicePathName.
                        listOfDevicePathNames[listIndex] = Marshal.PtrToStringAuto(pDevicePathName).ToUpper();

                        TmoShare.WriteLog(string.Format("DeviceDiscovery:findHidDevices() -> 将找到的设备添加进列表 (索引 {0})", listIndex));
                        deviceFound = true;
                        listIndex++;
                    }
                }while (lastDevice != true);
            }
            catch (Exception ex)
            {
                // Something went badly wrong... output some debug and return false to indicated device discovery failure
                TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 发生异常: " + ex.Message);
                return(false);
            }
            finally
            {
                // Clean up the unmanaged memory allocations
                if (detailDataBuffer != IntPtr.Zero)
                {
                    // Free the memory allocated previously by AllocHGlobal.
                    Marshal.FreeHGlobal(detailDataBuffer);
                }

                if (deviceInfoSet != IntPtr.Zero)
                {
                    SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                }
            }

            if (deviceFound)
            {
                TmoShare.WriteLog(String.Format("DeviceDiscovery:findHidDevices() -> 一共找到{0}个HID设备", listIndex));
                numberOfDevicesFound = listIndex;
            }
            else
            {
                TmoShare.WriteLog("DeviceDiscovery:findHidDevices() -> 没有找到HID设备");
            }

            return(deviceFound);
        }
        ///  <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 List <string> FindAllHidDevices()
        {
            var listOfDevicePathNames = new List <string>();
            var detailDataBuffer      = IntPtr.Zero;
            int listIndex             = 0;
            var deviceInterfaceData   = new SpDeviceInterfaceData();

            int lasterror = 0;

            // Get the required HID class GUID
            var systemHidGuid = new Guid();

            Hid.HidD_GetHidGuid(ref systemHidGuid);

            IntPtr deviceInfoSet = SetupDiGetClassDevs(ref systemHidGuid);

            deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

            try
            {
                // Look through the retrieved list of class GUIDs looking for a match on our interface GUID
                // SetupDiEnumDeviceInterfaces will return false if it fails for any reason, including when no more items are left
                // so we need to keep looping until the last thrown error is ERROR_NO_MORE_ITEMS
                // Note: we post increment lastIndex so each subsequent call refers to a new device
                while (SetupApi.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref systemHidGuid, listIndex++, ref deviceInterfaceData) || (lasterror = Marshal.GetLastWin32Error()) != Constants.ERROR_NO_MORE_ITEMS)
                {
                    if (lasterror != 0)
                    {
                        // SetupDiEnumDeviceInterfaces failed and it wasn't ERROR_NO_MORE_ITEMS as this would have stopped the loop
                        Debug.WriteLine("SetupDiEnumDeviceInterfaces failed for run {0} with error {1}", listIndex, lasterror);
                        continue;
                    }

                    int bufferSize = 0;

                    // The target device has been found, now we need to retrieve the device path so we can open
                    // the read and write handles required for USB communication

                    // First call fails with ERROR_INSUFFICIENT_BUFFER and is used just to get the required buffer size for the real request
                    var success = SetupApi.SetupDiGetDeviceInterfaceDetail(
                        deviceInfoSet,
                        ref deviceInterfaceData,
                        IntPtr.Zero,
                        0,
                        ref bufferSize,
                        IntPtr.Zero
                        );

                    // Allocate some memory for the buffer
                    detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
                    Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                    // Second call gets the detailed data buffer
                    success = SetupApi.SetupDiGetDeviceInterfaceDetail(
                        deviceInfoSet,
                        ref deviceInterfaceData,
                        detailDataBuffer,
                        bufferSize,
                        ref bufferSize,
                        IntPtr.Zero
                        );

                    if (!success)
                    {
                        Debug.WriteLine("SetupDiGetDeviceInterfaceDetail failed for run {0} with error {1}", listIndex, Marshal.GetLastWin32Error());
                        continue;
                    }

                    // Skip over cbsize (4 bytes) to get the address of the devicePathName.
                    var pDevicePathName = IntPtr.Add(detailDataBuffer, 4);

                    // Get the String containing the devicePathName.
                    listOfDevicePathNames.Add(Marshal.PtrToStringAuto(pDevicePathName));
                }
            }
            catch (Exception)
            {
                // Something went badly wrong...
                listOfDevicePathNames.Clear();
            }
            finally
            {
                // Clean up the unmanaged memory allocations and free resources held by the windows API
                Marshal.FreeHGlobal(detailDataBuffer);
                SetupApi.SetupDiDestroyDeviceInfoList(deviceInfoSet);
            }

            return(listOfDevicePathNames);
        }
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);
                }
            }
        }