Ejemplo n.º 1
0
        private static string GetDevicePath(IntPtr deviceInfoSet, ref NativeMethods.SP_DEVICE_INTERFACE_DATA deviceInterfaceData)
        {
            // Final result
            string result = null;

            // Object to store device path
            var deviceInterfaceDetail = new NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA
            {
                cbSize = (IntPtr.Size == 8)
                                        ? 8                                 // 64 bit
                                        : 4 + Marshal.SystemDefaultCharSize // 32 bit
            };

            // Sizes
            uint       requiredSize = 0;
            const uint bufferSize   = 1024;

            // Get device path
            if (NativeMethods.SetupDiGetDeviceInterfaceDetail(deviceInfoSet,
                                                              ref deviceInterfaceData,
                                                              ref deviceInterfaceDetail,
                                                              bufferSize,
                                                              ref requiredSize,
                                                              IntPtr.Zero))
            {
                result = deviceInterfaceDetail.DevicePath;
            }

            // Return
            return(result);
        }
Ejemplo n.º 2
0
        public static IEnumerable <HidDevice> EnumerateDevices()
        {
            // Get GUID for the HID class
            NativeMethods.HidD_GetHidGuid(out Guid hidClassGuid);

            // Pointer to device information set
            IntPtr deviceInfoSet = IntPtr.Zero;

            try
            {
                // Get device information set
                var deviceInfoSetFlags = NativeMethods.DiGetClassFlags.DIGCF_PRESENT | NativeMethods.DiGetClassFlags.DIGCF_DEVICEINTERFACE;
                deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref hidClassGuid, null, IntPtr.Zero, deviceInfoSetFlags);

                // Create SP_DEVINFO_DATA structure
                var deviceInfoData = default(NativeMethods.SP_DEVINFO_DATA);
                deviceInfoData.cbSize = (uint)Marshal.SizeOf(deviceInfoData);

                // Enumerate over device infos
                uint deviceIndex = 0;
                while (NativeMethods.SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex++, ref deviceInfoData))
                {
                    // A device interface in a device information set
                    var deviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
                    deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                    // Enumerate over devices
                    uint memberIndex = 0;
                    while (NativeMethods.SetupDiEnumDeviceInterfaces(deviceInfoSet, ref deviceInfoData, ref hidClassGuid, memberIndex++, ref deviceInterfaceData))
                    {
                        var device = new HidDevice
                        {
                            DevicePath  = GetDevicePath(deviceInfoSet, ref deviceInterfaceData),
                            Description = GetDeviceDescription(deviceInfoSet, ref deviceInfoData)
                        };

                        using (var handle = CreateFileHandle(device.DevicePath))
                        {
                            device.Capabilities = GetDeviceCapabilities(handle);
                            device.Attributes   = GetDeviceAttributes(handle);
                            device.Manufacturer = GetManufacturer(handle);
                            device.Product      = GetProduct(handle);
                        }

                        // Return item
                        yield return(device);
                    }
                }
            }
            finally
            {
                // Deletes a device information set and frees all associated memory
                NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet);
            }
        }
Ejemplo n.º 3
0
        private int EnumDeviceInterfaceDetails(int index, IntPtr devInfoSet, Guid iFaceGuid, out String devPath, NativeMethods.SP_DEVINFO_DATA devInfoData)
        {
            NativeMethods.SP_DEVICE_INTERFACE_DATA interfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();

            if (!NativeMethods.SetupDiEnumDeviceInterfaces(devInfoSet, null, ref iFaceGuid, index, interfaceData))
            {
                int error = Marshal.GetLastWin32Error();
                if (error == NativeMethods.ERROR_NO_MORE_ITEMS)
                {
                    devPath     = String.Empty;
                    devInfoData = null;
                    return(error);
                }
                else
                {
                    throw new Win32Exception(error);
                }
            }

            int requiredSize = 0;

            if (!NativeMethods.SetupDiGetDeviceInterfaceDetail(devInfoSet, interfaceData, IntPtr.Zero, 0, ref requiredSize, devInfoData))
            {
                int error = Marshal.GetLastWin32Error();
                if (error != NativeMethods.ERROR_INSUFFICIENT_BUFFER)
                {
                    throw new Win32Exception(error);
                }
            }

            IntPtr buffer = Marshal.AllocHGlobal(requiredSize);

            NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA detailData = new NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA();
            Marshal.StructureToPtr(detailData, buffer, false);

            if (!NativeMethods.SetupDiGetDeviceInterfaceDetail(devInfoSet, interfaceData, buffer, requiredSize, ref requiredSize, devInfoData))
            {
                int error = Marshal.GetLastWin32Error();
                Marshal.FreeHGlobal(buffer);
                throw new Win32Exception(error);
            }

            IntPtr pDevicePath = (IntPtr)((int)buffer + (int)Marshal.OffsetOf(typeof(NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA), "devicePath"));

            devPath = Marshal.PtrToStringAuto(pDevicePath);
            Marshal.FreeHGlobal(buffer);

            return(NativeMethods.ERROR_SUCCESS);
        }
Ejemplo n.º 4
0
            public static string ResolveDeviceInstanceGUID(Guid guid)
            {
                IntPtr deviceInfoSet = NativeMethods.SetupDiGetClassDevs(
                    ref guid,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    NativeMethods.DIGCF_PRESENT | NativeMethods.DIGCF_DEVICEINTERFACE);

                if (deviceInfoSet != IntPtr.Zero)
                {
                    Int32 memberIndex = 0;
                    NativeMethods.SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
                    deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                    bool isEnumeratedDeviceInterfaces = NativeMethods.SetupDiEnumDeviceInterfaces(
                        deviceInfoSet,
                        IntPtr.Zero,
                        ref guid,
                        memberIndex,
                        ref deviceInterfaceData);

                    if (isEnumeratedDeviceInterfaces)
                    {
                        // Request a structure with the device path name.
                        int    bufferSize = 0;
                        IntPtr detailDataBuffer;

                        // Determine the buffer size.
                        bool hasDeviceInterfaceDetail = NativeMethods.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);

                        // Request the structure again now that the buffer size has been determined.
                        hasDeviceInterfaceDetail = NativeMethods.SetupDiGetDeviceInterfaceDetail(
                            deviceInfoSet,
                            ref deviceInterfaceData,
                            detailDataBuffer,
                            bufferSize,
                            ref bufferSize,
                            IntPtr.Zero);

                        if (hasDeviceInterfaceDetail)
                        {
                            IntPtr ptrDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4);
                            string devicePathName    = Marshal.PtrToStringAuto(ptrDevicePathName);
                            Marshal.FreeHGlobal(detailDataBuffer);
                            NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                            return(devicePathName);
                        }
                        else
                        {
                            throw new ArgumentException("Could not resolve symbolic link from GUID.");
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Could not resolve symbolic link from GUID.");
                    }
                }
                else
                {
                    throw new ArgumentException("Could not resolve symbolic link from GUID.");
                }
            }
Ejemplo n.º 5
0
        ///  <summary>
        ///  Use SetupDi API functions to retrieve the device path name of an
        ///  attached device that belongs to a device interface class.
        ///  </summary>
        ///
        ///  <param name="myGuid"> an interface class GUID. </param>
        ///  <param name="devicePathName"> a pointer to the device path name
        ///  of an attached device. </param>
        ///
        ///  <returns>
        ///   True if a device is found, False if not.
        ///  </returns>

        internal Boolean FindDeviceFromGuid(Guid myGuid, ref String[] devicePathName)
        {
            Int32   bufferSize            = 0;
            var     deviceInfoSet         = new IntPtr();
            Boolean lastDevice            = false;
            var     myDeviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();

            traceSource.TraceEvent(TraceEventType.Verbose, 1, "FindDeviceFromGuid");

            try
            {
                Int32 memberIndex;

                // ***
                //  API function

                //  summary
                //  Retrieves a device information set for a specified group of devices.
                //  SetupDiEnumDeviceInterfaces uses the device information set.

                //  parameters
                //  Interface class GUID.
                //  Null to retrieve information for all device instances.
                //  Optional handle to a top-level window (unused here).
                //  Flags to limit the returned information to currently present devices
                //  and devices that expose interfaces in the class specified by the GUID.

                //  Returns
                //  Handle to a device information set for the devices.
                // ***

                deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.DIGCF_PRESENT | NativeMethods.DIGCF_DEVICEINTERFACE);

                bool deviceFound = false;
                memberIndex = 0;

                // The cbSize element of the MyDeviceInterfaceData structure must be set to
                // the structure's size in bytes.
                // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.

                myDeviceInterfaceData.cbSize = Marshal.SizeOf(myDeviceInterfaceData);

                do
                {
                    // Begin with 0 and increment through the device information set until
                    // no more devices are available.

                    // ***
                    //  API function

                    //  summary
                    //  Retrieves a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
                    //  On return, MyDeviceInterfaceData contains the handle to a
                    //  SP_DEVICE_INTERFACE_DATA structure for a detected device.

                    //  parameters
                    //  DeviceInfoSet returned by SetupDiGetClassDevs.
                    //  Optional SP_DEVINFO_DATA structure that defines a device instance
                    //  that is a member of a device information set.
                    //  Device interface GUID.
                    //  Index to specify a device in a device information set.
                    //  Pointer to a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.

                    //  Returns
                    //  True on success.
                    // ***

                    Boolean success = NativeMethods.SetupDiEnumDeviceInterfaces
                                          (deviceInfoSet,
                                          IntPtr.Zero,
                                          ref myGuid,
                                          memberIndex,
                                          ref myDeviceInterfaceData);

                    // Find out if a device information set was retrieved.

                    if (!success)
                    {
                        lastDevice = true;
                    }
                    else
                    {
                        // A device is present.

                        // ***
                        //  API function:

                        //  summary:
                        //  Retrieves an SP_DEVICE_INTERFACE_DETAIL_DATA structure
                        //  containing information about a device.
                        //  To retrieve the information, call this function twice.
                        //  The first time returns the size of the structure.
                        //  The second time returns a pointer to the data.

                        //  parameters
                        //  DeviceInfoSet returned by SetupDiGetClassDevs
                        //  SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces
                        //  A returned pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA
                        //  Structure to receive information about the specified interface.
                        //  The size of the SP_DEVICE_INTERFACE_DETAIL_DATA structure.
                        //  Pointer to a variable that will receive the returned required size of the
                        //  SP_DEVICE_INTERFACE_DETAIL_DATA structure.
                        //  Returned pointer to an SP_DEVINFO_DATA structure to receive information about the device.

                        //  Returns
                        //  True on success.
                        // ***

                        NativeMethods.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref myDeviceInterfaceData,
                            IntPtr.Zero,
                            0,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.

                        IntPtr detailDataBuffer = Marshal.AllocHGlobal(bufferSize);

                        // Store cbSize in the first bytes of the array. Adjust for 32- and 64-bit systems.

                        Int32 cbsize;

                        if (IntPtr.Size == 4)
                        {
                            cbsize = 4 + Marshal.SystemDefaultCharSize;
                        }
                        else
                        {
                            cbsize = 8;
                        }

                        Marshal.WriteInt32(detailDataBuffer, cbsize);

                        // Call SetupDiGetDeviceInterfaceDetail again.
                        // This time, pass a pointer to DetailDataBuffer
                        // and the returned required buffer size.

                        NativeMethods.SetupDiGetDeviceInterfaceDetail
                            (deviceInfoSet,
                            ref myDeviceInterfaceData,
                            detailDataBuffer,
                            bufferSize,
                            ref bufferSize,
                            IntPtr.Zero);

                        // Get the address of the devicePathName.

                        var pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);

                        // Get the String containing the devicePathName.

                        devicePathName[memberIndex] = Marshal.PtrToStringAuto(pDevicePathName);

                        if (detailDataBuffer != IntPtr.Zero)
                        {
                            // Free the memory allocated previously by AllocHGlobal.

                            Marshal.FreeHGlobal(detailDataBuffer);
                        }
                        deviceFound = true;
                    }
                    memberIndex = memberIndex + 1;
                }while (!lastDevice);

                return(deviceFound);
            }
            finally
            {
                // ***
                //  API function

                //  summary
                //  Frees the memory reserved for the DeviceInfoSet returned by SetupDiGetClassDevs.

                //  parameters
                //  DeviceInfoSet returned by SetupDiGetClassDevs.

                //  returns
                //  True on success.
                // ***

                if (deviceInfoSet != IntPtr.Zero)
                {
                    NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                }
            }
        }
Ejemplo n.º 6
0
        // Get connected device paths:
        private static bool GetDevicePathsByGuid(Guid hidClassGuid, ref string[] connectedDevicePaths)
        {
            var diDetailDataSize = 0;
            var deviceIndex      = 0;
            var ptrDeviceInfoSet = IntPtr.Zero;

            try
            {
                // Get handle to device information set for enumerated hid devices:
                ptrDeviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref hidClassGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.DIGCF_PRESENT | NativeMethods.DIGCF_DEVICEINTERFACE);

                // Instantiate an empty DEVICE_INTERFACE_DATA structure and set its size field:
                var diData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
                diData.CbSize = Marshal.SizeOf(diData);

                while (true)
                {
                    // Populates DEVICE_INTERFACE_DATA structure:
                    var isSuccess = NativeMethods.SetupDiEnumDeviceInterfaces(ptrDeviceInfoSet, IntPtr.Zero, ref hidClassGuid, deviceIndex, ref diData);
                    if (!isSuccess && Marshal.GetLastWin32Error() == NativeMethods.ERROR_NO_MORE_ITEMS)
                    {
                        break;                                                                                  // end of enumerated hid devices.
                    }
                    // Call first time to retrieve size of DEVICE_INTERFACE_DETAIL_DATA structure:
                    NativeMethods.SetupDiGetDeviceInterfaceDetail(ptrDeviceInfoSet, ref diData, IntPtr.Zero, 0, ref diDetailDataSize, IntPtr.Zero);

                    // Instantiate an empty DEVICE_INTERFACE_DETAIL_DATA structure and set its size field:
                    var diDetailData = Marshal.AllocHGlobal(diDetailDataSize);
                    Marshal.WriteInt32(diDetailData, (IntPtr.Size == 4 ? Marshal.SystemDefaultCharSize + 4 : 8));

                    // Call second time to retrieve populated DEVICE_INTERFACE_DETAIL_DATA structure:
                    NativeMethods.SetupDiGetDeviceInterfaceDetail(ptrDeviceInfoSet, ref diData, diDetailData, diDetailDataSize, ref diDetailDataSize, IntPtr.Zero);

                    // Get device path from DEVICE_INTERFACE_DETAIL_DATA structure:
                    var pDevicePath = new IntPtr(diDetailData.ToInt32() + 4);
                    connectedDevicePaths[deviceIndex] = Marshal.PtrToStringAuto(pDevicePath);

                    // Free memory previously allocated by AllocHGlobal:
                    if (diDetailData != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(diDetailData);
                    }

                    deviceIndex++;
                }
                return(true);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return(false);
            }
            finally
            {
                //  Free memory reserved for device information set by SetupDiGetClassDevs:
                if (ptrDeviceInfoSet != IntPtr.Zero)
                {
                    NativeMethods.SetupDiDestroyDeviceInfoList(ptrDeviceInfoSet);
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Use SetupDi API functions to retrieve the device path name of an
        ///  attached device that belongs to a device interface class.
        /// </summary>
        /// <param name="myGuid">
        /// An interface class GUID. 
        /// </param>
        /// <param name="devicePathName">
        /// A pointer to the device path name 
        ///  of an attached device. 
        /// </param>
        /// <returns>
        /// True if a device is found, False if not. 
        /// </returns>
        internal bool FindDeviceFromGuid(Guid myGuid, ref string[] devicePathName)
        {
            var bufferSize = 0;
            var deviceInfoSet = new IntPtr();
            bool lastDevice = false;
            var myDeviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();

            try
            {
                // ***
                //  API function

                //  summary 
                //  Retrieves a device information set for a specified group of devices.
                //  SetupDiEnumDeviceInterfaces uses the device information set.

                //  parameters 
                //  Interface class GUID.
                //  Null to retrieve information for all device instances.
                //  Optional handle to a top-level window (unused here).
                //  Flags to limit the returned information to currently present devices 
                //  and devices that expose interfaces in the class specified by the GUID.

                //  Returns
                //  Handle to a device information set for the devices.
                // ***
                deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.DIGCF_PRESENT | NativeMethods.DIGCF_DEVICEINTERFACE);

                bool deviceFound = false;
                int memberIndex = 0;

                // The cbSize element of the MyDeviceInterfaceData structure must be set to
                // the structure's size in bytes. 
                // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.

                myDeviceInterfaceData.cbSize = Marshal.SizeOf(myDeviceInterfaceData);

                do
                {
                    // Begin with 0 and increment through the device information set until
                    // no more devices are available.

                    // ***
                    //  API function

                    //  summary
                    //  Retrieves a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
                    //  On return, MyDeviceInterfaceData contains the handle to a
                    //  SP_DEVICE_INTERFACE_DATA structure for a detected device.

                    //  parameters
                    //  DeviceInfoSet returned by SetupDiGetClassDevs.
                    //  Optional SP_DEVINFO_DATA structure that defines a device instance 
                    //  that is a member of a device information set.
                    //  Device interface GUID.
                    //  Index to specify a device in a device information set.
                    //  Pointer to a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.

                    //  Returns
                    //  True on success.
                    // ***

                    var success = NativeMethods.SetupDiEnumDeviceInterfaces(
                        deviceInfoSet,
                        IntPtr.Zero,
                        ref myGuid,
                         memberIndex,
                         ref myDeviceInterfaceData);

                    // Find out if a device information set was retrieved.

                    if (!success)
                    {
                        lastDevice = true;
                    }
                    else
                    {
                        // A device is present.

                        // ***
                        //  API function: 

                        //  summary:
                        //  Retrieves an SP_DEVICE_INTERFACE_DETAIL_DATA structure
                        //  containing information about a device.
                        //  To retrieve the information, call this function twice.
                        //  The first time returns the size of the structure.
                        //  The second time returns a pointer to the data.

                        //  parameters
                        //  DeviceInfoSet returned by SetupDiGetClassDevs
                        //  SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces
                        //  A returned pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA 
                        //  Structure to receive information about the specified interface.
                        //  The size of the SP_DEVICE_INTERFACE_DETAIL_DATA structure.
                        //  Pointer to a variable that will receive the returned required size of the 
                        //  SP_DEVICE_INTERFACE_DETAIL_DATA structure.
                        //  Returned pointer to an SP_DEVINFO_DATA structure to receive information about the device.

                        //  Returns
                        //  True on success.
                        // ***                     

                        NativeMethods.SetupDiGetDeviceInterfaceDetail(
                            deviceInfoSet,
                            ref myDeviceInterfaceData,
                            IntPtr.Zero,
                             0,
                             ref bufferSize,
                             IntPtr.Zero);

                        // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.

                        //IntPtr detailDataBuffer = new IntPtr(100);/////// 
                        var detailDataBuffer = AllocHGlobal((IntPtr)bufferSize);

                        // Store cbSize in the first bytes of the array. Adjust for 32- and 64-bit systems.

                        int cbsize;

                        if (IntPtr.Size == 4)
                        {
                            cbsize = 4 + Marshal.SystemDefaultCharSize;
                        }
                        else
                        {
                            cbsize = 8;
                        }

                        Marshal.WriteInt32(detailDataBuffer, cbsize);

                        // Call SetupDiGetDeviceInterfaceDetail again.
                        // This time, pass a pointer to DetailDataBuffer
                        // and the returned required buffer size.

                        NativeMethods.SetupDiGetDeviceInterfaceDetail(
                            deviceInfoSet,
                            ref myDeviceInterfaceData,
                            detailDataBuffer,
                             bufferSize,
                             ref bufferSize,
                             IntPtr.Zero);

                        // Get the address of the devicePathName.

                        var pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);

                        // Get the String containing the devicePathName.

                        devicePathName[memberIndex] = Marshal.PtrToStringUni(pDevicePathName);

                        Debug.WriteLine(devicePathName[memberIndex]);

                        if (detailDataBuffer != IntPtr.Zero)
                        {
                            // Free the memory allocated previously by AllocHGlobal.
                            FreeHGlobal(detailDataBuffer);
                        }
                        deviceFound = true;
                    }
                    memberIndex = memberIndex + 1;
                }
                while (!lastDevice);

                return deviceFound;
            }
            finally
            {
                // ***
                //  API function

                //  summary
                //  Frees the memory reserved for the DeviceInfoSet returned by SetupDiGetClassDevs.

                //  parameters
                //  DeviceInfoSet returned by SetupDiGetClassDevs.

                //  returns
                //  True on success.
                // ***

                if (deviceInfoSet != IntPtr.Zero)
                {
                    NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                }
            }
        }
Ejemplo n.º 8
0
        IList <string> FindHidDevicePathList()
        {
            // TODO: MUSTDO: fix for multiple device connection
            // Use UpdateDevicePathIfDevicePathIsNullOrEmpty() in normal use case.
            // Because if you always use this method in every HID access, CPU usage increase from <1% to 5%-10%.
            // And the UpdateDevicePath() occupies 87.8% of all application CPU times.

            // TODO: MUSTDO: GetInstalledDeviceDevicePathListByInterfaceClassGuid duplicated.  This is not deleted because this code may be faster since it does not get Capability and this was correct.
            // TODO: MUSTDO: Like GetInstalledDeviceDevicePathListByInterfaceClassGuid, it should detect when the app starts and device connection status changes.
            var ret = new List <string>();

            // TODO: MUSTDO: ProductIdは0xA001に統一される。
            foreach (var targetHidGuid in TargetHidGuidList)
            {
                int index = 0;
                // copy
                Guid hidGuid = targetHidGuid;
                NativeMethods.SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
                deviceInterfaceData.cbSize = (uint)Marshal.SizeOf(deviceInterfaceData);

                // Enumerate devices.
                var hDevInfo = NativeMethods.SetupDiGetClassDevs(ref hidGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.DIGCF_DEVICEINTERFACE | NativeMethods.DIGCF_PRESENT);

                while (NativeMethods.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref hidGuid, index, ref deviceInterfaceData))
                {
                    UInt32 size;
                    NativeMethods.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref deviceInterfaceData, IntPtr.Zero, 0, out size, IntPtr.Zero);
                    NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = new NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA();
                    deviceInterfaceDetailData.cbSize = (uint)(IntPtr.Size == 8 ? 8 : 5);
                    // Get detail information
                    NativeMethods.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref deviceInterfaceData, ref deviceInterfaceDetailData, size, out size, IntPtr.Zero);
                    //Debug.WriteLine(index + " " + deviceInterfaceDetailData.DevicePath + " " + Marshal.GetLastWin32Error());

                    // open a read/write handle to our device using the DevicePath returned
                    SafeFileHandle handle = null;
                    try
                    {
                        handle = NativeMethods.CreateFile(deviceInterfaceDetailData.DevicePath, 0, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, NativeMethods.EFileAttributes.Overlapped, IntPtr.Zero);
                        // create an attributes struct and initialize the size
                        NativeMethods.HIDD_ATTRIBUTES attrib = new NativeMethods.HIDD_ATTRIBUTES();
                        attrib.Size = (uint)Marshal.SizeOf(attrib);
                        // get the attributes of the current device
                        if (NativeMethods.HidD_GetAttributes(handle.DangerousGetHandle(), ref attrib))
                        {
                            //Debug.WriteLine(deviceInterfaceDetailData.DevicePath + " " + attrib.VendorID +" / " +attrib.ProductID);

                            // if the vendor and product IDs match up
                            if (attrib.VendorID != VendorId)
                            {
                                continue;
                            }
                            if (attrib.ProductID != ProductId)
                            {
                                continue;
                            }
                            var lowered = deviceInterfaceDetailData.DevicePath.ToLower(System.Globalization.CultureInfo.InvariantCulture);
                            if (lowered.Contains(HidEgsGestureInterfaceTag) == false)
                            {
                                continue;
                            }
                            if (lowered.Contains(HidEgsGestureInterface_VendorSpecificCollectionTag) == false)
                            {
                                continue;
                            }
                            ret.Add(deviceInterfaceDetailData.DevicePath);
                        }
                    }
                    finally
                    {
                        handle.Close();
                        index++;
                    }
                }
            }
            return(ret);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Use SetupDi API functions to retrieve the device path name of an attached device that belongs to a device interface class.
        /// </summary>
        /// <param name="interfaceClassGuid"> an interface class GUID. </param>
        internal List <string> GetInstalledDeviceDevicePathListByInterfaceClassGuid(Guid interfaceClassGuid)
        {
            uint   bufferSize       = 0;
            IntPtr detailDataBuffer = IntPtr.Zero;
            IntPtr deviceInfoSet    = new System.IntPtr();
            bool   lastDevice       = false;
            int    memberIndex      = 0;

            NativeMethods.SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
            bool success;
            var  newInstalledDeviceDevicePathList = new List <string>();

            try
            {
                // ***
                //  API function

                //  summary
                //  Retrieves a device information set for a specified group of devices.
                //  SetupDiEnumDeviceInterfaces uses the device information set.

                //  parameters
                //  Interface class GUID.
                //  Null to retrieve information for all device instances.
                //  Optional handle to a top-level window (unused here).
                //  Flags to limit the returned information to currently present devices
                //  and devices that expose interfaces in the class specified by the GUID.

                //  Returns
                //  Handle to a device information set for the devices.
                // ***
                deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref interfaceClassGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.DIGCF_PRESENT | NativeMethods.DIGCF_DEVICEINTERFACE);
                memberIndex   = 0;

                // The cbSize element of the deviceInterfaceData structure must be set to
                // the structure's size in bytes.
                // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
                deviceInterfaceData.cbSize = (uint)Marshal.SizeOf(deviceInterfaceData);

                do
                {
                    // Begin with 0 and increment through the device information set until
                    // no more devices are available.

                    // ***
                    //  API function

                    //  summary
                    //  Retrieves a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
                    //  On return, deviceInterfaceData contains the handle to a
                    //  SP_DEVICE_INTERFACE_DATA structure for a detected device.

                    //  parameters
                    //  DeviceInfoSet returned by SetupDiGetClassDevs.
                    //  Optional SP_DEVINFO_DATA structure that defines a device instance
                    //  that is a member of a device information set.
                    //  Device interface GUID.
                    //  Index to specify a device in a device information set.
                    //  Pointer to a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.

                    //  Returns
                    //  True on success.
                    // ***
                    success = NativeMethods.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref interfaceClassGuid, memberIndex, ref deviceInterfaceData);

                    // Find out if a device information set was retrieved.

                    if (!success)
                    {
                        lastDevice = true;
                    }
                    else
                    {
                        // A device is present.

                        // ***
                        //  API function:

                        //  summary:
                        //  Retrieves an SP_DEVICE_INTERFACE_DETAIL_DATA structure
                        //  containing information about a device.
                        //  To retrieve the information, call this function twice.
                        //  The first time returns the size of the structure.
                        //  The second time returns a pointer to the data.

                        //  parameters
                        //  DeviceInfoSet returned by SetupDiGetClassDevs
                        //  SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces
                        //  A returned pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA
                        //  Structure to receive information about the specified interface.
                        //  The size of the SP_DEVICE_INTERFACE_DETAIL_DATA structure.
                        //  Pointer to a variable that will receive the returned required size of the
                        //  SP_DEVICE_INTERFACE_DETAIL_DATA structure.
                        //  Returned pointer to an SP_DEVINFO_DATA structure to receive information about the device.

                        //  Returns
                        //  True on success.
                        // ***
                        success = NativeMethods.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, out bufferSize, IntPtr.Zero);

                        // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
                        detailDataBuffer = Marshal.AllocHGlobal((int)bufferSize);

                        // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
                        Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);

                        // Call SetupDiGetDeviceInterfaceDetail again.
                        // This time, pass a pointer to DetailDataBuffer and the returned required buffer size.
                        success = NativeMethods.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, detailDataBuffer, bufferSize, out bufferSize, IntPtr.Zero);

                        // Skip over cbsize (4 bytes) to get the address of the devicePathList.
                        IntPtr pDevicePathName = new IntPtr(((IntPtr.Size == 4) ? detailDataBuffer.ToInt32() : detailDataBuffer.ToInt64()) + 4);

                        // Get the string containing the devicePathList.
                        string newDevicePath = Marshal.PtrToStringAuto(pDevicePathName);
                        newInstalledDeviceDevicePathList.Add(newDevicePath);

                        // Free the memory allocated previously by AllocHGlobal.
                        if (detailDataBuffer != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(detailDataBuffer);
                        }
                    }
                    memberIndex = memberIndex + 1;
                }while (!((lastDevice == true)));
                return(newInstalledDeviceDevicePathList);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
            finally
            {
                if (deviceInfoSet != IntPtr.Zero)
                {
                    NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                }
            }
        }
        ///  <summary>
        ///  Use SetupDi API functions to retrieve the device path name of an attached device that belongs to a device interface class.
        ///  </summary>
        ///
        ///  <returns>
        ///   True if a device is found, False if not.
        ///  </returns>
        ///

        /*
         *  API function:   SetupDiGetClassDevs
         *  summary :
         *                  Retrieves a device information set for a specified group of devices.
         *                  SetupDiEnumDeviceInterfaces uses the device information set.
         *  parameters:
         *                  Interface class GUID.
         *                  Null to retrieve information for all device instances.
         *                  Optional handle to a top-level window (unused here).
         *                  Flags to limit the returned information to currently present devices and devices that expose interfaces in the class specified by the GUID.
         *  Returns:
         *                  Handle to a device information set for the devices.
         */
        ///

        /*
         *  API function:   SetupDiEnumDeviceInterfaces
         *  summary:        Retrieves a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
         *                  On return, MyDeviceInterfaceData contains the handle to a SP_DEVICE_INTERFACE_DATA structure for a detected device.
         *
         *  parameters:
         *                  DeviceInfoSet returned by SetupDiGetClassDevs.
         *                  Optional SP_DEVINFO_DATA structure that defines a device instance that is a member of a device information set.
         *                  Device interface GUID.
         *                  Index to specify a device in a device information set.
         *                  Pointer to a handle to a SP_DEVICE_INTERFACE_DATA structure for a device.
         *
         *  Returns:        True on success.
         */
        ///

        /*
         *  API function:   SetupDiGetDeviceInterfaceDetail
         *  summary:
         *                  Retrieves an SP_DEVICE_INTERFACE_DETAIL_DATA structure containing information about a device.
         *                  To retrieve the information, call this function twice.
         *                  The first time returns the size of the structure.
         *                  The second time returns a pointer to the data.
         *  parameters:
         *                  DeviceInfoSet returned by SetupDiGetClassDevs SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces
         *                  A returned pointer to an SP_DEVICE_INTERFACE_DETAIL_DATA Structure to receive information about the specified interface.
         *                  The size of the SP_DEVICE_INTERFACE_DETAIL_DATA structure.
         *                  Pointer to a variable that will receive the returned required size of the SP_DEVICE_INTERFACE_DETAIL_DATA structure.
         *                  Returned pointer to an SP_DEVINFO_DATA structure to receive information about the device.
         *
         *  Returns:        True on success.
         */
        internal Boolean FindDeviceFromGuid(Guid myGuid, ref String[] devicePathName)
        {
            Int32   bufferSize            = 0;
            var     deviceInfoSet         = new IntPtr();
            Boolean lastDevice            = false;
            var     myDeviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();

            try
            {
                Int32 memberIndex;
                deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.DIGCF_PRESENT | NativeMethods.DIGCF_DEVICEINTERFACE);

                bool deviceFound = false;
                memberIndex = 0;

                // The cbSize element of the MyDeviceInterfaceData structure must be set to the structure's size in bytes.
                // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
                myDeviceInterfaceData.cbSize = Marshal.SizeOf(myDeviceInterfaceData);
                do
                {                   //Begin with 0 and increment through the device information set until no more devices are available.
                    Boolean success = NativeMethods.SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref myDeviceInterfaceData);

                    // Find out if a device information set was retrieved.
                    if (!success)
                    {
                        lastDevice = true;
                    }
                    else// A device is present.
                    {
                        NativeMethods.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref myDeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);

                        // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
                        IntPtr detailDataBuffer = Marshal.AllocHGlobal(bufferSize);

                        // Store cbSize in the first bytes of the array. Adjust for 32- and 64-bit systems.
                        Int32 cbsize;

                        if (IntPtr.Size == 4)
                        {
                            cbsize = 4 + Marshal.SystemDefaultCharSize;
                        }
                        else
                        {
                            cbsize = 8;
                        }

                        Marshal.WriteInt32(detailDataBuffer, cbsize);

                        // Call SetupDiGetDeviceInterfaceDetail again.
                        // This time, pass a pointer to DetailDataBuffer and the returned required buffer size.
                        NativeMethods.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref myDeviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero);

                        // Get the address of the devicePathName.
                        var pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);

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

                        if (detailDataBuffer != IntPtr.Zero)
                        {
                            // Free the memory allocated previously by AllocHGlobal.
                            Marshal.FreeHGlobal(detailDataBuffer);
                        }
                        deviceFound = true;
                    }
                    memberIndex = memberIndex + 1;
                }while (!lastDevice);

                return(deviceFound);
            }
            finally
            {
                if (deviceInfoSet != IntPtr.Zero)
                {
                    NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet);
                }
            }
        }//FindDeviceFromGuid
Ejemplo n.º 11
0
        protected override string GetStreamPath(OpenConfiguration openConfig)
        {
            var service = GetService(openConfig);

            if (service == null)
            {
                throw DeviceException.CreateIOException(this, "BLE service not specified.");
            }
            if (service.Device != this)
            {
                throw DeviceException.CreateIOException(this, "BLE service is on a different device.");
            }

            uint devInst;

            if (0 == NativeMethods.CM_Locate_DevNode(out devInst, _id))
            {
                if (0 == NativeMethods.CM_Get_Child(out devInst, devInst))
                {
                    do
                    {
                        string serviceDeviceID;
                        if (0 == NativeMethods.CM_Get_Device_ID(devInst, out serviceDeviceID))
                        {
                            NativeMethods.HDEVINFO devInfo = NativeMethods.SetupDiGetClassDevs(
                                service.Uuid, serviceDeviceID, IntPtr.Zero,
                                NativeMethods.DIGCF.DeviceInterface | NativeMethods.DIGCF.Present
                                );

                            if (devInfo.IsValid)
                            {
                                try
                                {
                                    NativeMethods.SP_DEVINFO_DATA dvi = new NativeMethods.SP_DEVINFO_DATA();
                                    dvi.Size = Marshal.SizeOf(dvi);

                                    for (int j = 0; NativeMethods.SetupDiEnumDeviceInfo(devInfo, j, ref dvi); j++)
                                    {
                                        NativeMethods.SP_DEVICE_INTERFACE_DATA did = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
                                        did.Size = Marshal.SizeOf(did);

                                        for (int k = 0; NativeMethods.SetupDiEnumDeviceInterfaces(devInfo, ref dvi, service.Uuid, k, ref did); k++)
                                        {
                                            string devicePath;
                                            if (NativeMethods.SetupDiGetDeviceInterfaceDevicePath(devInfo, ref did, out devicePath))
                                            {
                                                // FIXME: Take the attribute handle into account as well.
                                                //        Right now, if there are multiple services with the same GUID, we do not distinguish between them.
                                                return(devicePath);
                                            }
                                        }
                                    }
                                }
                                finally
                                {
                                    NativeMethods.SetupDiDestroyDeviceInfoList(devInfo);
                                }
                            }
                        }
                    }while (0 == NativeMethods.CM_Get_Sibling(out devInst, devInst));
                }
            }

            throw DeviceException.CreateIOException(this, string.Format("BLE service {0} not found.", service.Uuid));
        }