public ViGEmNavMergeX360Sink() { _deviceCount = 0; _Nav0Report = null; _Nav1Report = null; _btnMap0 = new Dictionary <DualShock3Buttons, Xbox360Button> { { DualShock3Buttons.LeftThumb, Xbox360Button.LeftThumb }, { DualShock3Buttons.LeftShoulder, Xbox360Button.LeftShoulder }, { DualShock3Buttons.Circle, Xbox360Button.Start }, { DualShock3Buttons.Cross, Xbox360Button.Back }, { DualShock3Buttons.DPadUp, Xbox360Button.Up }, { DualShock3Buttons.DPadDown, Xbox360Button.Down }, { DualShock3Buttons.DPadLeft, Xbox360Button.Left }, { DualShock3Buttons.DPadRight, Xbox360Button.Right }, { DualShock3Buttons.Ps, Xbox360Button.Guide } }; _btnMap1 = new Dictionary <DualShock3Buttons, Xbox360Button> { { DualShock3Buttons.LeftThumb, Xbox360Button.RightThumb }, { DualShock3Buttons.LeftShoulder, Xbox360Button.RightShoulder }, { DualShock3Buttons.Circle, Xbox360Button.B }, { DualShock3Buttons.Cross, Xbox360Button.A }, { DualShock3Buttons.DPadUp, Xbox360Button.Y }, { DualShock3Buttons.DPadDown, Xbox360Button.A }, { DualShock3Buttons.DPadLeft, Xbox360Button.X }, { DualShock3Buttons.DPadRight, Xbox360Button.B }, { DualShock3Buttons.Ps, Xbox360Button.Guide } }; _client = new ViGEmClient(); }
protected override void RequestInputReportWorker(object cancellationToken) { var token = (CancellationToken)cancellationToken; var buffer = new byte[0x32]; var unmanagedBuffer = Marshal.AllocHGlobal(buffer.Length); try { while (!token.IsCancellationRequested) { var ret = DeviceHandle.OverlappedDeviceIoControl( IOCTL_BTHPS3_HID_INTERRUPT_READ, IntPtr.Zero, 0, unmanagedBuffer, buffer.Length, out _ ); if (!ret) { OnDisconnected(); return; } Marshal.Copy(unmanagedBuffer, buffer, 0, buffer.Length); /* * When connected via Bluetooth the Sixaxis occasionally sends * a report with the second byte 0xff and the rest zeroed. * * This report does not reflect the actual state of the * controller must be ignored to avoid generating false input * events. */ if (buffer[2] == 0xff) { continue; } try { OnInputReport(DualShock3InputReport.FromBuffer(buffer.Skip(1).ToArray())); } catch (InvalidDataException ide) { Log.Warning("Malformed input report received: {Exception}", ide); } } } catch (Exception ex) { Log.Error("{Exception}", ex); } finally { Marshal.FreeHGlobal(unmanagedBuffer); } }
protected override void RequestInputReportWorker(object cancellationToken) { var token = (CancellationToken)cancellationToken; var requestSize = Marshal.SizeOf <AirBenderHost.AirbenderGetDs3InputReport>(); var requestBuffer = Marshal.AllocHGlobal(requestSize); Marshal.StructureToPtr( new AirBenderHost.AirbenderGetDs3InputReport { ClientAddress = ClientAddress.ToNativeBdAddr() }, requestBuffer, false); try { while (!token.IsCancellationRequested) { // // This call blocks until the driver supplies new data. // var ret = HostDevice.DeviceHandle.OverlappedDeviceIoControl( AirBenderHost.IoctlAirbenderGetDs3InputReport, requestBuffer, requestSize, requestBuffer, requestSize, out _); if (!ret) { throw new AirBenderGetDs3InputReportFailedException("Input Report Request failed.", new Win32Exception(Marshal.GetLastWin32Error())); } var resp = Marshal.PtrToStructure <AirBenderHost.AirbenderGetDs3InputReport>(requestBuffer); try { OnInputReport(DualShock3InputReport.FromBuffer(resp.ReportBuffer)); } catch (InvalidDataException ide) { Log.Warning("Malformed input report received: {Exception}", ide); } } } catch (Exception ex) { Log.Error("{Exception}", ex); } finally { Marshal.FreeHGlobal(requestBuffer); } }
protected override void RequestInputReportWorker(object cancellationToken) { var token = (CancellationToken)cancellationToken; var buffer = new byte[512]; var unmanagedBuffer = Marshal.AllocHGlobal(buffer.Length); try { while (!token.IsCancellationRequested) { var ret = DeviceHandle.OverlappedReadFile( unmanagedBuffer, buffer.Length, out var bytesReturned); if (!ret) { var nex = new Win32Exception(Marshal.GetLastWin32Error()); // Valid exception in case the device got surprise-removed, end worker if (nex.NativeErrorCode == Win32ErrorCode.ERROR_OPERATION_ABORTED) { return; } throw new FireShockReadInputReportFailedException( "Failed to read input report.", nex); } Marshal.Copy(unmanagedBuffer, buffer, 0, bytesReturned); try { OnInputReport(DualShock3InputReport.FromBuffer(buffer)); } catch (InvalidDataException ide) { Log.Warning("Malformed input report received: {Exception}", ide); } } } catch (Exception ex) { Log.Error("{Exception}", ex); } finally { Marshal.FreeHGlobal(unmanagedBuffer); } }
protected void OnInputReport(IInputReport report) { if (report == null) { return; } // Pull battery state from report DualShock3InputReport ds3_report = (DualShock3InputReport)report; BatteryState = ds3_report.BatteryState; InputReportReceived?.Invoke(this, new InputReportEventArgs(report)); }
protected override void RequestInputReportWorker(object cancellationToken) { var token = (CancellationToken)cancellationToken; var buffer = new byte[0x32]; var unmanagedBuffer = Marshal.AllocHGlobal(buffer.Length); try { while (!token.IsCancellationRequested) { var ret = DeviceHandle.OverlappedDeviceIoControl( IOCTL_BTHPS3_HID_INTERRUPT_READ, IntPtr.Zero, 0, unmanagedBuffer, buffer.Length, out _ ); if (!ret) { OnDisconnected(); return; } Marshal.Copy(unmanagedBuffer, buffer, 0, buffer.Length); try { OnInputReport(DualShock3InputReport.FromBuffer(buffer.Skip(1).ToArray())); } catch (InvalidDataException ide) { Log.Warning("Malformed input report received: {Exception}", ide); } } } catch (Exception ex) { Log.Error("{Exception}", ex); } finally { Marshal.FreeHGlobal(unmanagedBuffer); } }
public void InputReportReceived(IDualShockDevice device, IInputReport report) { _target.ResetReport(); //This may be able to be optimized, look into later... // Convert report to DS3 format and store latest report for this device var ds3Report = (DualShock3InputReport)report; if (device.DeviceIndex == 0) { _Nav0Report = ds3Report; } if (device.DeviceIndex == 1) { _Nav1Report = ds3Report; } // Only combine reports and submit if we've seen input from each controller at least once if (_Nav0Report != null && _Nav1Report != null) { // Map buttons from Navigation #1 into input report _target.SetAxisValue(Xbox360Axis.LeftThumbX, Scale(_Nav0Report[DualShock3Axes.LeftThumbX], false)); _target.SetAxisValue(Xbox360Axis.LeftThumbY, Scale(_Nav0Report[DualShock3Axes.LeftThumbY], true)); _target.SetAxisValue(Xbox360Axis.RightThumbX, Scale(_Nav1Report[DualShock3Axes.LeftThumbX], false)); _target.SetAxisValue(Xbox360Axis.RightThumbY, Scale(_Nav1Report[DualShock3Axes.LeftThumbY], true)); _target.SetSliderValue(Xbox360Slider.LeftTrigger, _Nav0Report[DualShock3Axes.LeftTrigger]); _target.SetSliderValue(Xbox360Slider.RightTrigger, _Nav1Report[DualShock3Axes.LeftTrigger]); foreach (var button in _btnMap0.Where(m => _Nav0Report.EngagedButtons.Contains(m.Key)) .Select(m => m.Value)) { _target.SetButtonState(button, true); } foreach (var button in _btnMap1.Where(m => _Nav1Report.EngagedButtons.Contains(m.Key)) .Select(m => m.Value)) { _target.SetButtonState(button, true); } _target.SubmitReport(); } }
public void DeviceRemoved(IDualShockDevice device) { Log.Information("ViGEmNavMergeX360: Device with index {Index} detached", device.DeviceIndex); // Only remove the virtual 360 controller if we only had one controller left connected if (_deviceCount == 1) { _target.Disconnect(); _target = null; } _deviceCount--; if (device.DeviceIndex == 0) { _Nav0Report = null; } if (device.DeviceIndex == 1) { _Nav1Report = null; } }