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); }
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); }
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); }