// TODO why do I need this? private static bool IsRealDS4(HidDevice hidGameController) { string deviceInstanceId = HidGameControllers.DevicePathToInstanceId(hidGameController.DevicePath); string numberForUI = HidGameControllers.GetDeviceProperty( deviceInstanceId, NativeMethods.DEVPKEY_Device_UINumber ); return(string.IsNullOrEmpty(numberForUI)); }
public static void FindControllers() { lock (HidGameControllers.devices) // TODO will this be called by multiple threads? why? { var hidGameControllers = HidGameControllers.EnumerateHidControllersMatching(vendorIdProductIdInfoArray: HidGameControllers.dualShock4CompatibleDevices); hidGameControllers = hidGameControllers .Where(hidController => IsRealDS4(hidController)) .OrderBy <HidDevice, ConnectionType>((HidDevice hidGameController) => { // Sort Bluetooth first in case USB is also connected on the same controller. return(DualShock4Controller.HidConnectionType(hidGameController)); }); var tempHidGameControllers = hidGameControllers.ToList(); // TODO it's already an IEnumerable, why tolist()?? Just to create a copy? Why creating a copy? // TODO purgeHiddenExclusiveDevices(); tempHidGameControllers.AddRange(HidGameControllers.disabledDevices); int hidGameControllersCount = tempHidGameControllers.Count(); string devicePlural = "device" + (hidGameControllersCount == 0 || hidGameControllersCount > 1 ? "s" : ""); //Log.LogToGui("Found " + hidGameControllersCount + " possible " + devicePlural + ". Examining " + devicePlural + ".", false); for (int i = 0; i < hidGameControllersCount; i++) //foreach (HidDevice hDevice in hDevices) { var tempHidGameController = tempHidGameControllers[i]; if (tempHidGameController.Description == "HID-compliant vendor-defined device") { continue; // ignore the Nacon Revolution Pro programming interface } if (HidGameControllers.devicePaths.Contains(tempHidGameController.DevicePath)) { continue; // BT/USB endpoint already opened once } if (!tempHidGameController.IsOpen) { tempHidGameController.OpenDevice(HidGameControllers.isExclusiveMode); if (!tempHidGameController.IsOpen && HidGameControllers.isExclusiveMode) { try { // Check if running with elevated permissions // FIXME why check this at each iteration?? WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); bool elevated = principal.IsInRole(WindowsBuiltInRole.Administrator); if (!elevated) { // Tell the client to launch routine to re-enable a device RequestElevationArgs eleArgs = new RequestElevationArgs(HidGameControllers.DevicePathToInstanceId(tempHidGameController.DevicePath)); RequestElevation?.Invoke(eleArgs); if (eleArgs.StatusCode == RequestElevationArgs.STATUS_SUCCESS) { tempHidGameController.OpenDevice(HidGameControllers.isExclusiveMode); } } else { HidGameControllers.ReEnableDevice(HidGameControllers.DevicePathToInstanceId(tempHidGameController.DevicePath)); tempHidGameController.OpenDevice(HidGameControllers.isExclusiveMode); } } catch (Exception) { // FIXME log this! } } // TODO in exclusive mode, try to hold both open when both are connected if (HidGameControllers.isExclusiveMode && !tempHidGameController.IsOpen) { tempHidGameController.OpenDevice(isExclusive: false); } } if (tempHidGameController.IsOpen) { string serial = tempHidGameController.ReadSerial(); bool validSerial = !serial.Equals(HidDevice.blankSerial); if (validSerial && deviceSerials.Contains(serial)) { // happens when the BT endpoint already is open and the USB is plugged into the same host if (HidGameControllers.isExclusiveMode && tempHidGameController.IsExclusive && !HidGameControllers.disabledDevices.Contains(tempHidGameController)) { // Grab reference to exclusively opened HidDevice so device // stays hidden to other processes HidGameControllers.disabledDevices.Add(tempHidGameController); //DevicePaths.Add(tempHidGameController.DevicePath); } continue; } else { var vendorIdProductIdInfo = dualShock4CompatibleDevices.Single( x => x.vendorId == tempHidGameController.Attributes.VendorId && x.productId == tempHidGameController.Attributes.ProductId ); var ds4Device = new DualShock4Controller(tempHidGameController, vendorIdProductIdInfo.name, vendorIdProductIdInfo.featureSet); //ds4Device.Removal += On_Removal; if (!ds4Device.ExitOutputThread) { HidGameControllers.devices.Add(tempHidGameController.DevicePath, ds4Device); HidGameControllers.devicePaths.Add(tempHidGameController.DevicePath); HidGameControllers.deviceSerials.Add(serial); } } } } } }