mirror of
https://github.com/cemu-project/DS4Windows.git
synced 2024-11-26 19:14:20 +01:00
184 lines
8.0 KiB
C#
184 lines
8.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace DS4Windows
|
|
{
|
|
public class HidDevices
|
|
{
|
|
private static Guid _hidClassGuid = Guid.Empty;
|
|
|
|
public static bool IsConnected(string devicePath)
|
|
{
|
|
return EnumerateDevices().Any(x => x.Path == devicePath);
|
|
}
|
|
|
|
public static HidDevice GetDevice(string devicePath)
|
|
{
|
|
return Enumerate(devicePath).FirstOrDefault();
|
|
}
|
|
|
|
public static IEnumerable<HidDevice> Enumerate()
|
|
{
|
|
return EnumerateDevices().Select(x => new HidDevice(x.Path, x.Description));
|
|
}
|
|
|
|
public static IEnumerable<HidDevice> Enumerate(string devicePath)
|
|
{
|
|
return EnumerateDevices().Where(x => x.Path == devicePath).Select(x => new HidDevice(x.Path, x.Description));
|
|
}
|
|
|
|
public static IEnumerable<HidDevice> Enumerate(int vendorId, params int[] productIds)
|
|
{
|
|
return EnumerateDevices().Select(x => new HidDevice(x.Path, x.Description)).Where(x => x.Attributes.VendorId == vendorId &&
|
|
productIds.Contains(x.Attributes.ProductId));
|
|
}
|
|
|
|
public static IEnumerable<HidDevice> Enumerate(int[] vendorIds, params int[] productIds)
|
|
{
|
|
return EnumerateDevices().Select(x => new HidDevice(x.Path, x.Description)).Where(x => vendorIds.Contains(x.Attributes.VendorId) &&
|
|
productIds.Contains(x.Attributes.ProductId));
|
|
}
|
|
|
|
public static IEnumerable<HidDevice> EnumerateDS4(VidPidInfo[] devInfo)
|
|
{
|
|
List<HidDevice> foundDevs = new List<HidDevice>();
|
|
int devInfoLen = devInfo.Length;
|
|
IEnumerable<DeviceInfo> temp = EnumerateDevices();
|
|
for (int i = 0, len = temp.Count(); i < len; i++)
|
|
{
|
|
DeviceInfo x = temp.ElementAt(i);
|
|
HidDevice tempDev = new HidDevice(x.Path, x.Description);
|
|
bool found = false;
|
|
for (int j = 0; !found && j < devInfoLen; j++)
|
|
{
|
|
VidPidInfo tempInfo = devInfo[j];
|
|
if (tempDev.Attributes.VendorId == tempInfo.vid &&
|
|
tempDev.Attributes.ProductId == tempInfo.pid)
|
|
{
|
|
found = true;
|
|
foundDevs.Add(tempDev);
|
|
}
|
|
}
|
|
}
|
|
|
|
return foundDevs;
|
|
}
|
|
|
|
public static IEnumerable<HidDevice> Enumerate(int vendorId)
|
|
{
|
|
return EnumerateDevices().Select(x => new HidDevice(x.Path, x.Description)).Where(x => x.Attributes.VendorId == vendorId);
|
|
}
|
|
|
|
private class DeviceInfo { public string Path { get; set; } public string Description { get; set; } }
|
|
|
|
private static IEnumerable<DeviceInfo> EnumerateDevices()
|
|
{
|
|
var devices = new List<DeviceInfo>();
|
|
var hidClass = HidClassGuid;
|
|
var deviceInfoSet = NativeMethods.SetupDiGetClassDevs(ref hidClass, null, 0, NativeMethods.DIGCF_PRESENT | NativeMethods.DIGCF_DEVICEINTERFACE);
|
|
|
|
if (deviceInfoSet.ToInt64() != NativeMethods.INVALID_HANDLE_VALUE)
|
|
{
|
|
var deviceInfoData = CreateDeviceInfoData();
|
|
var deviceIndex = 0;
|
|
|
|
while (NativeMethods.SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, ref deviceInfoData))
|
|
{
|
|
deviceIndex += 1;
|
|
|
|
var deviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
|
|
deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);
|
|
var deviceInterfaceIndex = 0;
|
|
|
|
while (NativeMethods.SetupDiEnumDeviceInterfaces(deviceInfoSet, ref deviceInfoData, ref hidClass, deviceInterfaceIndex, ref deviceInterfaceData))
|
|
{
|
|
deviceInterfaceIndex++;
|
|
var devicePath = GetDevicePath(deviceInfoSet, deviceInterfaceData);
|
|
var description = GetBusReportedDeviceDescription(deviceInfoSet, ref deviceInfoData) ??
|
|
GetDeviceDescription(deviceInfoSet, ref deviceInfoData);
|
|
devices.Add(new DeviceInfo { Path = devicePath, Description = description });
|
|
}
|
|
}
|
|
NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
|
}
|
|
return devices;
|
|
}
|
|
|
|
private static NativeMethods.SP_DEVINFO_DATA CreateDeviceInfoData()
|
|
{
|
|
var deviceInfoData = new NativeMethods.SP_DEVINFO_DATA();
|
|
|
|
deviceInfoData.cbSize = Marshal.SizeOf(deviceInfoData);
|
|
deviceInfoData.DevInst = 0;
|
|
deviceInfoData.ClassGuid = Guid.Empty;
|
|
deviceInfoData.Reserved = IntPtr.Zero;
|
|
|
|
return deviceInfoData;
|
|
}
|
|
|
|
private static string GetDevicePath(IntPtr deviceInfoSet, NativeMethods.SP_DEVICE_INTERFACE_DATA deviceInterfaceData)
|
|
{
|
|
var bufferSize = 0;
|
|
var interfaceDetail = new NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA { Size = IntPtr.Size == 4 ? 4 + Marshal.SystemDefaultCharSize : 8 };
|
|
|
|
NativeMethods.SetupDiGetDeviceInterfaceDetailBuffer(deviceInfoSet, ref deviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
|
|
|
|
return NativeMethods.SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref deviceInterfaceData, ref interfaceDetail, bufferSize, ref bufferSize, IntPtr.Zero) ?
|
|
interfaceDetail.DevicePath : null;
|
|
}
|
|
|
|
private static Guid HidClassGuid
|
|
{
|
|
get
|
|
{
|
|
if (_hidClassGuid.Equals(Guid.Empty)) NativeMethods.HidD_GetHidGuid(ref _hidClassGuid);
|
|
return _hidClassGuid;
|
|
}
|
|
}
|
|
|
|
private static string GetDeviceDescription(IntPtr deviceInfoSet, ref NativeMethods.SP_DEVINFO_DATA devinfoData)
|
|
{
|
|
var descriptionBuffer = new byte[1024];
|
|
|
|
var requiredSize = 0;
|
|
var type = 0;
|
|
|
|
NativeMethods.SetupDiGetDeviceRegistryProperty(deviceInfoSet,
|
|
ref devinfoData,
|
|
NativeMethods.SPDRP_DEVICEDESC,
|
|
ref type,
|
|
descriptionBuffer,
|
|
descriptionBuffer.Length,
|
|
ref requiredSize);
|
|
|
|
return descriptionBuffer.ToUTF8String();
|
|
}
|
|
|
|
private static string GetBusReportedDeviceDescription(IntPtr deviceInfoSet, ref NativeMethods.SP_DEVINFO_DATA devinfoData)
|
|
{
|
|
var descriptionBuffer = new byte[1024];
|
|
|
|
if (Environment.OSVersion.Version.Major > 5)
|
|
{
|
|
ulong propertyType = 0;
|
|
var requiredSize = 0;
|
|
|
|
var _continue = NativeMethods.SetupDiGetDeviceProperty(deviceInfoSet,
|
|
ref devinfoData,
|
|
ref NativeMethods.DEVPKEY_Device_BusReportedDeviceDesc,
|
|
ref propertyType,
|
|
descriptionBuffer,
|
|
descriptionBuffer.Length,
|
|
ref requiredSize,
|
|
0);
|
|
|
|
if (_continue) return descriptionBuffer.ToUTF16String();
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|