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); }
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); } }
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); }
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."); } }
/// <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); } } }
// 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); } } }
/// <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); } } }
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); }
/// <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
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)); }