public SixaxisDevice(string path, Kernel32.SafeObjectHandle handle, int index) : base(path, handle, index) { DeviceType = DualShockDeviceType.DualShock3; // // Remote MAC address is encoded in path as InstanceId // This is a lazy approach but saves an I/O request ;) // ClientAddress = PhysicalAddress.Parse(path.Substring(path.LastIndexOf('&') + 1, 12)); // // Initialize default output report native buffer // FillMemory(OutputReportBuffer, OutputReportBufferSize, 0); Marshal.Copy(HidOutputReport, 0, OutputReportBuffer, HidOutputReport.Length); // // Crude way to assign device index as LED number // if (index >= 0 && index < 4) { Marshal.WriteByte(OutputReportBuffer, 11, _ledOffsets[index]); } // // Send the start command to remote device // var unmanagedBuffer = Marshal.AllocHGlobal(_hidEnableCommand.Length); Marshal.Copy(_hidEnableCommand, 0, unmanagedBuffer, _hidEnableCommand.Length); try { var ret = handle.OverlappedDeviceIoControl( IOCTL_BTHPS3_HID_CONTROL_WRITE, unmanagedBuffer, _hidEnableCommand.Length, IntPtr.Zero, 0, out _ ); if (!ret) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { Marshal.FreeHGlobal(unmanagedBuffer); } SendHidCommand(OutputReportBuffer, OutputReportBufferSize); }
private void InvertedCallSupplierWorker(object cancellationToken) { Policy.Handle <Win32Exception>().Retry(3, (exception, i, ctx) => { Log.Error("Inverted Call Thread died with exception {@Exception}, trying to restart...", exception); }).Execute(() => { var token = (CancellationToken)cancellationToken; var invertedCallSize = Marshal.SizeOf <HidGuardianGetCreateRequest>(); var invertedCallBuffer = Marshal.AllocHGlobal(invertedCallSize); var authCallSize = Marshal.SizeOf <HidGuardianSetCreateRequest>(); var authCallBuffer = Marshal.AllocHGlobal(authCallSize); try { while (!token.IsCancellationRequested) { // Create random value to match request/response pair var requestId = (uint)_randGen.Next(); // Craft inverted call packet Marshal.StructureToPtr( new HidGuardianGetCreateRequest { Size = (uint)invertedCallSize, RequestId = requestId }, invertedCallBuffer, false); // Send inverted call (this will block until the driver receives an open request) var ret = _deviceHandle.OverlappedDeviceIoControl( IoctlHidguardianGetCreateRequest, invertedCallBuffer, invertedCallSize, invertedCallBuffer, invertedCallSize, out var _); if (!ret) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // Get back modified values from driver var request = Marshal.PtrToStructure <HidGuardianGetCreateRequest>(invertedCallBuffer); // Invoke open permission request so we know what to do next var eventArgs = new OpenPermissionRequestedEventArgs(ExtractHardwareIds(request), (int)request.ProcessId); OpenPermissionRequested?.Invoke(this, eventArgs); // Craft authentication request packet Marshal.StructureToPtr( new HidGuardianSetCreateRequest { RequestId = request.RequestId, DeviceIndex = request.DeviceIndex, IsAllowed = eventArgs.IsAllowed, IsSticky = eventArgs.IsPermanent }, authCallBuffer, false); // This request will dequeue the pending request and either complete it successfully or fail it ret = _deviceHandle.OverlappedDeviceIoControl( IoctlHidguardianSetCreateRequest, authCallBuffer, authCallSize, authCallBuffer, authCallSize, out var _); if (!ret) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } } finally { Marshal.FreeHGlobal(invertedCallBuffer); } }); }