diff --git a/ControllerService/ControllerService.cs b/ControllerService/ControllerService.cs index c3d260b0b..d92908f14 100644 --- a/ControllerService/ControllerService.cs +++ b/ControllerService/ControllerService.cs @@ -19,11 +19,10 @@ namespace ControllerService public class ControllerService : IHostedService { // controllers vars - public XInputController PhysicalController; - private IVirtualGamepad VirtualController; + private ViGEmClient VirtualClient; + public XInputController XInputController; private XInputGirometer Gyrometer; private XInputAccelerometer Accelerometer; - private ViGEmClient VirtualClient; private PipeServer PipeServer; private DSUServer DSUServer; @@ -87,53 +86,34 @@ public ControllerService(ILogger logger) Hidder = new HidHide(CurrentPathCli, logger, this); Hidder.RegisterApplication(CurrentExe); - // initialize controller - switch (HIDmode) - { - default: - case "DualShock4Controller": - VirtualController = VirtualClient.CreateDualShock4Controller(); - break; - case "Xbox360Controller": - VirtualController = VirtualClient.CreateXbox360Controller(); - break; - } - - if (VirtualController == null) - { - logger.LogCritical("No Virtual controller detected. Application will stop"); - throw new InvalidOperationException(); - } - // prepare physical controller DirectInput dinput = new DirectInput(); IList dinstances = dinput.GetDevices(DeviceClass.GameControl, DeviceEnumerationFlags.AttachedOnly); - for (int i = (int)UserIndex.One; i <= (int)UserIndex.Three; i++) + foreach (UserIndex idx in (UserIndex[])Enum.GetValues(typeof(UserIndex))) { - XInputController tmpController = new XInputController((UserIndex)i, HIDrate, logger); + Controller controller = new Controller(idx); + if (!controller.IsConnected) + continue; - if (tmpController.controller.IsConnected) - { - PhysicalController = tmpController; - PhysicalController.instance = dinstances[i]; - break; - } + XInputController = new XInputController(controller, idx, HIDrate, HIDmode, logger); + XInputController.instance = dinstances[(int)idx]; + break; } - if (PhysicalController == null) + if (XInputController == null) { logger.LogCritical("No physical controller detected. Application will stop"); throw new InvalidOperationException(); } // default is 10ms rating - Gyrometer = new XInputGirometer(PhysicalController, logger); + Gyrometer = new XInputGirometer(XInputController, logger); if (Gyrometer.sensor == null) logger.LogWarning("No Gyrometer detected"); // default is 10ms rating - Accelerometer = new XInputAccelerometer(PhysicalController, logger); + Accelerometer = new XInputAccelerometer(XInputController, logger); if (Accelerometer.sensor == null) logger.LogWarning("No Accelerometer detected"); @@ -180,20 +160,20 @@ private void OnClientMessage(object sender, PipeMessage message) switch (cursor.action) { case 0: // up - PhysicalController.touch.OnMouseUp((short)cursor.x, (short)cursor.y, cursor.button); + XInputController.target.touch.OnMouseUp((short)cursor.x, (short)cursor.y, cursor.button); break; case 1: // down - PhysicalController.touch.OnMouseDown((short)cursor.x, (short)cursor.y, cursor.button); + XInputController.target.touch.OnMouseDown((short)cursor.x, (short)cursor.y, cursor.button); break; case 2: // move - PhysicalController.touch.OnMouseMove((short)cursor.x, (short)cursor.y, cursor.button); + XInputController.target.touch.OnMouseMove((short)cursor.x, (short)cursor.y, cursor.button); break; } break; case PipeCode.CLIENT_SCREEN: PipeClientScreen screen = (PipeClientScreen)message; - PhysicalController.touch.UpdateRatio(screen.width, screen.height); + XInputController.target.touch.UpdateRatio(screen.width, screen.height); break; case PipeCode.CLIENT_SETTINGS: @@ -219,7 +199,7 @@ private void OnClientMessage(object sender, PipeMessage message) private void OnClientDisconnected(object sender) { - PhysicalController.touch.OnMouseUp(-1, -1, 1048576 /* MouseButtons.Left */); + XInputController.target.touch.OnMouseUp(-1, -1, 1048576 /* MouseButtons.Left */); } private void OnClientConnected(object sender) @@ -227,10 +207,10 @@ private void OnClientConnected(object sender) // send controller details PipeServer.SendMessage(new PipeServerController() { - ProductName = PhysicalController.instance.ProductName, - InstanceGuid = PhysicalController.instance.InstanceGuid, - ProductGuid = PhysicalController.instance.ProductGuid, - ProductIndex = (int)PhysicalController.index + ProductName = XInputController.instance.ProductName, + InstanceGuid = XInputController.instance.InstanceGuid, + ProductGuid = XInputController.instance.ProductGuid, + ProductIndex = (int)XInputController.index }); // send server settings @@ -239,7 +219,7 @@ private void OnClientConnected(object sender) internal void UpdateProfile(Profile profile) { - PhysicalController.profile = profile; + XInputController.target.profile = profile; } public void UpdateSettings(Dictionary args) @@ -312,10 +292,10 @@ private void ApplySetting(string name, object prev_value, object value) // todo break; case "HIDrate": - PhysicalController.SetPollRate((int)value); + XInputController.SetPollRate((int)value); break; case "HIDstrength": - PhysicalController.SetVibrationStrength((int)value); + XInputController.SetVibrationStrength((int)value); break; case "DSUEnabled": switch ((bool)value) @@ -343,14 +323,12 @@ public Task StartAsync(CancellationToken cancellationToken) // turn on the cloaking Hidder.SetCloaking(HIDcloaked); - VirtualController.Connect(); - logger.LogInformation("Virtual {0} connected", VirtualController.GetType().Name); - - PhysicalController.SetDSUServer(DSUServer); - PhysicalController.SetVirtualController(VirtualController); - PhysicalController.SetGyroscope(Gyrometer); - PhysicalController.SetAccelerometer(Accelerometer); - PhysicalController.SetVibrationStrength(HIDstrength); + // initialize virtual controller + XInputController.SetTarget(VirtualClient); + XInputController.SetDSUServer(DSUServer); + XInputController.SetGyroscope(Gyrometer); + XInputController.SetAccelerometer(Accelerometer); + XInputController.SetVibrationStrength(HIDstrength); // start the Pipe Server PipeServer.Start(); @@ -358,7 +336,7 @@ public Task StartAsync(CancellationToken cancellationToken) // send notification PipeServer.SendMessage(new PipeServerToast { - title = $"{VirtualController.GetType().Name}", + title = $"{XInputController.target.GetType().Name}", content = "Virtual device is now connected" }); @@ -369,15 +347,15 @@ public Task StopAsync(CancellationToken cancellationToken) { try { - if (VirtualController != null) + if (XInputController.target != null) { - VirtualController.Disconnect(); - logger.LogInformation("Virtual {0} disconnected", VirtualController.GetType().Name); + XInputController.target.Disconnect(); + logger.LogInformation("Virtual {0} disconnected", XInputController.target.GetType().Name); // send notification PipeServer.SendMessage(new PipeServerToast { - title = $"{VirtualController.GetType().Name}", + title = $"{XInputController.target.GetType().Name}", content = "Virtual device is now disconnected" }); } @@ -398,8 +376,8 @@ public Dictionary GetSettings() foreach (SettingsProperty s in Properties.Settings.Default.Properties) settings.Add(s.Name, Properties.Settings.Default[s.Name].ToString()); - settings.Add("gyrometer", $"{PhysicalController.gyrometer.sensor != null}"); - settings.Add("accelerometer", $"{PhysicalController.accelerometer.sensor != null}"); + settings.Add("gyrometer", $"{XInputController.gyrometer.sensor != null}"); + settings.Add("accelerometer", $"{XInputController.accelerometer.sensor != null}"); return settings; } diff --git a/ControllerService/DSUServer.cs b/ControllerService/DSUServer.cs index 754fb7d7f..bac455838 100644 --- a/ControllerService/DSUServer.cs +++ b/ControllerService/DSUServer.cs @@ -1,4 +1,5 @@ using ControllerCommon; +using ControllerService.Targets; using Force.Crc32; using Microsoft.Extensions.Logging; using SharpDX.XInput; @@ -537,63 +538,63 @@ public void Stop() Stopped?.Invoke(this); } - private bool ReportToBuffer(XInputController hidReport, byte[] outputData, long microseconds, ref int outIdx) + private bool ReportToBuffer(ViGEmTarget hidReport, byte[] outputData, long microseconds, ref int outIdx) { unchecked { outputData[outIdx] = 0; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft)) outputData[outIdx] |= 0x80; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown)) outputData[outIdx] |= 0x40; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight)) outputData[outIdx] |= 0x20; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp)) outputData[outIdx] |= 0x10; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft)) outputData[outIdx] |= 0x80; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown)) outputData[outIdx] |= 0x40; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight)) outputData[outIdx] |= 0x20; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp)) outputData[outIdx] |= 0x10; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.Start)) outputData[outIdx] |= 0x08; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.RightThumb)) outputData[outIdx] |= 0x04; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftThumb)) outputData[outIdx] |= 0x02; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.Back)) outputData[outIdx] |= 0x01; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.Start)) outputData[outIdx] |= 0x08; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.RightThumb)) outputData[outIdx] |= 0x04; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftThumb)) outputData[outIdx] |= 0x02; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.Back)) outputData[outIdx] |= 0x01; outputData[++outIdx] = 0; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.X)) outputData[outIdx] |= 0x80; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.A)) outputData[outIdx] |= 0x40; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.B)) outputData[outIdx] |= 0x20; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.Y)) outputData[outIdx] |= 0x10; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.X)) outputData[outIdx] |= 0x80; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.A)) outputData[outIdx] |= 0x40; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.B)) outputData[outIdx] |= 0x20; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.Y)) outputData[outIdx] |= 0x10; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.RightShoulder)) outputData[outIdx] |= 0x08; - if (hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftShoulder)) outputData[outIdx] |= 0x04; - if (hidReport.gamepad.RightTrigger == byte.MaxValue) outputData[outIdx] |= 0x02; - if (hidReport.gamepad.LeftTrigger == byte.MaxValue) outputData[outIdx] |= 0x01; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.RightShoulder)) outputData[outIdx] |= 0x08; + if (hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftShoulder)) outputData[outIdx] |= 0x04; + if (hidReport.Gamepad.RightTrigger == byte.MaxValue) outputData[outIdx] |= 0x02; + if (hidReport.Gamepad.LeftTrigger == byte.MaxValue) outputData[outIdx] |= 0x01; outputData[++outIdx] = (byte)0; // (hidReport.PS) ? (byte)1 : outputData[++outIdx] = (byte)0; // (hidReport.TouchButton) ? (byte)1 : //Left stick - outputData[++outIdx] = Utils.NormalizeInput(hidReport.gamepad.LeftThumbX); - outputData[++outIdx] = Utils.NormalizeInput(hidReport.gamepad.LeftThumbY); + outputData[++outIdx] = Utils.NormalizeInput(hidReport.Gamepad.LeftThumbX); + outputData[++outIdx] = Utils.NormalizeInput(hidReport.Gamepad.LeftThumbY); outputData[outIdx] = (byte)(byte.MaxValue - outputData[outIdx]); //invert Y by convention //Right stick - outputData[++outIdx] = Utils.NormalizeInput(hidReport.gamepad.RightThumbX); - outputData[++outIdx] = Utils.NormalizeInput(hidReport.gamepad.RightThumbY); + outputData[++outIdx] = Utils.NormalizeInput(hidReport.Gamepad.RightThumbX); + outputData[++outIdx] = Utils.NormalizeInput(hidReport.Gamepad.RightThumbY); outputData[outIdx] = (byte)(byte.MaxValue - outputData[outIdx]); //invert Y by convention //we don't have analog buttons on DS4 :( - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.X) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.A) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.B) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.Y) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.X) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.A) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.B) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.Y) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.RightShoulder) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftShoulder) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.RightShoulder) ? (byte)0xFF : (byte)0x00; + outputData[++outIdx] = hidReport.Gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftShoulder) ? (byte)0xFF : (byte)0x00; - outputData[++outIdx] = hidReport.gamepad.RightTrigger; - outputData[++outIdx] = hidReport.gamepad.LeftTrigger; + outputData[++outIdx] = hidReport.Gamepad.RightTrigger; + outputData[++outIdx] = hidReport.Gamepad.LeftTrigger; outIdx++; @@ -657,13 +658,13 @@ private bool ReportToBuffer(XInputController hidReport, byte[] outputData, long return true; } - public void NewReportIncoming(XInputController hidReport, long microseconds) + public void NewReportIncoming(ViGEmTarget hidReport) { if (!running) return; // update status - padMeta.IsActive = hidReport.controller.IsConnected; + padMeta.IsActive = hidReport.Controller.IsConnected; var clientsList = new List(); var now = DateTime.UtcNow; @@ -750,7 +751,7 @@ public void NewReportIncoming(XInputController hidReport, long microseconds) Array.Copy(BitConverter.GetBytes((uint)udpPacketCount++), 0, outputData, outIdx, 4); outIdx += 4; - if (!ReportToBuffer(hidReport, outputData, microseconds, ref outIdx)) + if (!ReportToBuffer(hidReport, outputData, hidReport.microseconds, ref outIdx)) return; else FinishPacket(outputData); diff --git a/ControllerService/HidHide.cs b/ControllerService/HidHide.cs index 85f030540..000095369 100644 --- a/ControllerService/HidHide.cs +++ b/ControllerService/HidHide.cs @@ -116,7 +116,7 @@ public void SetCloaking(bool status) process.WaitForExit(); process.StandardOutput.ReadToEnd(); - logger.LogInformation("{0} cloak status set to {1}", service.PhysicalController.instance.ProductName, status); + logger.LogInformation("{0} cloak status set to {1}", service.XInputController.instance.ProductName, status); } public void RegisterDevice(string deviceInstancePath) diff --git a/ControllerService/Targets/DualShock4Target.cs b/ControllerService/Targets/DualShock4Target.cs new file mode 100644 index 000000000..32f0772ee --- /dev/null +++ b/ControllerService/Targets/DualShock4Target.cs @@ -0,0 +1,200 @@ +using ControllerCommon; +using Nefarius.ViGEm.Client; +using Nefarius.ViGEm.Client.Targets; +using Nefarius.ViGEm.Client.Targets.DualShock4; +using SharpDX.XInput; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Timers; + +namespace ControllerService.Targets +{ + internal class DualShock4Target : ViGEmTarget + { + private static readonly List ButtonMap = new List + { + DualShock4Button.ThumbRight, + DualShock4Button.ThumbLeft, + DualShock4Button.Options, + DualShock4Button.Share, + DualShock4Button.TriggerRight, + DualShock4Button.TriggerLeft, + DualShock4Button.ShoulderRight, + DualShock4Button.ShoulderLeft, + DualShock4Button.Triangle, + DualShock4Button.Circle, + DualShock4Button.Cross, + DualShock4Button.Square, + DualShock4SpecialButton.Ps, + DualShock4SpecialButton.Touchpad + }; + + private static readonly List AxisMap = new List + { + DualShock4Axis.LeftThumbX, + DualShock4Axis.LeftThumbY, + DualShock4Axis.RightThumbX, + DualShock4Axis.RightThumbY + }; + + private static readonly List SliderMap = new List + { + DualShock4Slider.LeftTrigger, + DualShock4Slider.RightTrigger + }; + + private DS4_REPORT_EX outDS4Report; + + private const float F_ACC_RES_PER_G = 8192.0f; + private const float F_GYRO_RES_IN_DEG_SEC = 16.0f; + + private new IDualShock4Controller vcontroller; + + public DualShock4Target(ViGEmClient client, Controller controller, int index) : base(client, controller, index) + { + // initialize controller + vcontroller = client.CreateDualShock4Controller(); + vcontroller.AutoSubmitReport = false; + + vcontroller.Connect(); + } + + public new void Disconnect() + { + vcontroller.Disconnect(); + } + + public new unsafe void UpdateReport() + { + if (!Controller.IsConnected) + return; + + base.UpdateReport(); + + // reset vars + byte[] rawOutReportEx = new byte[63]; + ushort tempButtons = 0; + ushort tempSpecial = 0; + DualShock4DPadDirection tempDPad = DualShock4DPadDirection.None; + + outDS4Report.bThumbLX = 127; + outDS4Report.bThumbLY = 127; + outDS4Report.bThumbRX = 127; + outDS4Report.bThumbRY = 127; + + unchecked + { + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.A)) + tempButtons |= DualShock4Button.Cross.Value; + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.B)) + tempButtons |= DualShock4Button.Circle.Value; + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.X)) + tempButtons |= DualShock4Button.Square.Value; + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.Y)) + tempButtons |= DualShock4Button.Triangle.Value; + + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.Start)) + tempButtons |= DualShock4Button.Options.Value; + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.Back)) + tempButtons |= DualShock4Button.Share.Value; + + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.RightThumb)) + tempButtons |= DualShock4Button.ThumbRight.Value; + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftThumb)) + tempButtons |= DualShock4Button.ThumbLeft.Value; + + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.RightShoulder)) + tempButtons |= DualShock4Button.ShoulderRight.Value; + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftShoulder)) + tempButtons |= DualShock4Button.ShoulderLeft.Value; + + if (Gamepad.LeftTrigger > 0) + tempButtons |= DualShock4Button.TriggerLeft.Value; + if (Gamepad.RightTrigger > 0) + tempButtons |= DualShock4Button.TriggerRight.Value; + + if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp) && + Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight)) + tempDPad = DualShock4DPadDirection.Northeast; + else if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp) && + Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft)) + tempDPad = DualShock4DPadDirection.Northwest; + else if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp)) + tempDPad = DualShock4DPadDirection.North; + else if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight) && + Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown)) + tempDPad = DualShock4DPadDirection.Southeast; + else if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight)) + tempDPad = DualShock4DPadDirection.East; + else if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown) && + Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft)) + tempDPad = DualShock4DPadDirection.Southwest; + else if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown)) + tempDPad = DualShock4DPadDirection.South; + else if (Gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft)) + tempDPad = DualShock4DPadDirection.West; + + if ((state_s.wButtons & 0x0400) == 0x0400) + tempSpecial |= DualShock4SpecialButton.Ps.Value; + if (touch.OutputClickButton) + tempSpecial |= DualShock4SpecialButton.Touchpad.Value; + + outDS4Report.bSpecial = (byte)(tempSpecial | (0 << 2)); + } + + if (!profile.whitelisted) + { + outDS4Report.wButtons = tempButtons; + outDS4Report.wButtons |= tempDPad.Value; + + outDS4Report.bTriggerL = Gamepad.LeftTrigger; + outDS4Report.bTriggerR = Gamepad.RightTrigger; + + outDS4Report.bThumbLX = Utils.NormalizeInput(LeftThumbX); + outDS4Report.bThumbLY = (byte)(byte.MaxValue - Utils.NormalizeInput(LeftThumbY)); + outDS4Report.bThumbRX = Utils.NormalizeInput(RightThumbX); + outDS4Report.bThumbRY = (byte)(byte.MaxValue - Utils.NormalizeInput(RightThumbY)); + } + + unchecked + { + outDS4Report.bTouchPacketsN = 0x01; + outDS4Report.sCurrentTouch.bPacketCounter = touch.TouchPacketCounter; + outDS4Report.sCurrentTouch.bIsUpTrackingNum1 = touch.TrackPadTouch0.RawTrackingNum; + outDS4Report.sCurrentTouch.bTouchData1[0] = (byte)(touch.TrackPadTouch0.X & 0xFF); + outDS4Report.sCurrentTouch.bTouchData1[1] = + (byte)(((touch.TrackPadTouch0.X >> 8) & 0x0F) | ((touch.TrackPadTouch0.Y << 4) & 0xF0)); + outDS4Report.sCurrentTouch.bTouchData1[2] = (byte)(touch.TrackPadTouch0.Y >> 4); + + outDS4Report.sCurrentTouch.bIsUpTrackingNum2 = touch.TrackPadTouch1.RawTrackingNum; + outDS4Report.sCurrentTouch.bTouchData2[0] = (byte)(touch.TrackPadTouch1.X & 0xFF); + outDS4Report.sCurrentTouch.bTouchData2[1] = + (byte)(((touch.TrackPadTouch1.X >> 8) & 0x0F) | ((touch.TrackPadTouch1.Y << 4) & 0xF0)); + outDS4Report.sCurrentTouch.bTouchData2[2] = (byte)(touch.TrackPadTouch1.Y >> 4); + } + + outDS4Report.wGyroX = (short)(AngularVelocity.X * F_GYRO_RES_IN_DEG_SEC); // gyroPitchFull + outDS4Report.wGyroY = (short)(-AngularVelocity.Y * F_GYRO_RES_IN_DEG_SEC); // gyroYawFull + outDS4Report.wGyroZ = (short)(AngularVelocity.Z * F_GYRO_RES_IN_DEG_SEC); // gyroRollFull + + outDS4Report.wAccelX = (short)(-Acceleration.X * F_ACC_RES_PER_G); // accelXFull + outDS4Report.wAccelY = (short)(-Acceleration.Y * F_ACC_RES_PER_G); // accelYFull + outDS4Report.wAccelZ = (short)(Acceleration.Z * F_ACC_RES_PER_G); // accelZFull + + // digest previous value + // AngularVelocity = new(); + // Acceleration = new(); + + outDS4Report.bBatteryLvlSpecial = 11; + + outDS4Report.wTimestamp = (ushort)(microseconds / 5.33f); + + DS4OutDeviceExtras.CopyBytes(ref outDS4Report, rawOutReportEx); + vcontroller.SubmitRawReport(rawOutReportEx); + } + } +} diff --git a/ControllerService/Targets/ViGEmTarget.cs b/ControllerService/Targets/ViGEmTarget.cs new file mode 100644 index 000000000..85b450be1 --- /dev/null +++ b/ControllerService/Targets/ViGEmTarget.cs @@ -0,0 +1,123 @@ +using ControllerCommon; +using Nefarius.ViGEm.Client; +using Nefarius.ViGEm.Client.Targets; +using SharpDX.XInput; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Numerics; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Timers; + +namespace ControllerService.Targets +{ + public abstract class ViGEmTarget + { + #region imports + [StructLayout(LayoutKind.Sequential)] + protected struct XInputStateSecret + { + public uint eventCount; + public ushort wButtons; + public byte bLeftTrigger; + public byte bRightTrigger; + public short sThumbLX; + public short sThumbLY; + public short sThumbRX; + public short sThumbRY; + } + + [DllImport("xinput1_3.dll", EntryPoint = "#100")] + protected static extern int XInputGetStateSecret13(int playerIndex, out XInputStateSecret struc); + [DllImport("xinput1_4.dll", EntryPoint = "#100")] + protected static extern int XInputGetStateSecret14(int playerIndex, out XInputStateSecret struc); + #endregion + + public Profile profile; + public Controller Controller; + public Gamepad Gamepad; + public DS4Touch touch; + + public Vector3 AngularVelocity; + public Vector3 Acceleration; + + protected ViGEmClient Client { get; } + protected IVirtualGamepad vcontroller; + + protected XInputStateSecret state_s; + + public long microseconds; + protected readonly Stopwatch stopwatch; + protected int index; + + protected ViGEmTarget(ViGEmClient client, Controller controller, int index) + { + // initialize vectors + AngularVelocity = new(); + Acceleration = new(); + + // initialize profile + profile = new(); + touch = new(); + + // initialize secret state + state_s = new(); + + Client = client; + Controller = controller; + + stopwatch = new Stopwatch(); + } + + protected short LeftThumbX, LeftThumbY, RightThumbX, RightThumbY; + + public void UpdateReport() + { + // update timestamp + microseconds = (long)(stopwatch.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L))); + + // get current gamepad state + XInputGetStateSecret13(index, out state_s); + State state = Controller.GetState(); + Gamepad = state.Gamepad; + + // get buttons values + ushort buttons = (ushort)Gamepad.Buttons; + buttons |= (Gamepad.LeftTrigger > 0 ? (ushort)1024 : (ushort)0); + buttons |= (Gamepad.RightTrigger > 0 ? (ushort)2048 : (ushort)0); + + // get sticks values + LeftThumbX = Gamepad.LeftThumbX; + LeftThumbY = Gamepad.LeftThumbY; + RightThumbX = Gamepad.RightThumbX; + RightThumbY = Gamepad.RightThumbY; + + if (profile.umc_enabled && ((buttons + ProfileButton.AlwaysOn.Value) & profile.umc_trigger) != 0) + { + float intensity = profile.GetIntensity(); + float sensivity = profile.GetSensiviy(); + + switch (profile.umc_input) + { + default: + case InputStyle.RightStick: + RightThumbX = Utils.ComputeInput(RightThumbX, -AngularVelocity.Z * 1.5f, sensivity, intensity); + RightThumbY = Utils.ComputeInput(RightThumbY, AngularVelocity.X, sensivity, intensity); + break; + case InputStyle.LeftStick: + LeftThumbX = Utils.ComputeInput(LeftThumbX, -AngularVelocity.Z * 1.5f, sensivity, intensity); + LeftThumbY = Utils.ComputeInput(LeftThumbY, AngularVelocity.X, sensivity, intensity); + break; + } + } + } + + internal void Disconnect() + { + throw new NotImplementedException(); + } + } +} diff --git a/ControllerService/Targets/Xbox360Target.cs b/ControllerService/Targets/Xbox360Target.cs new file mode 100644 index 000000000..fa7842b8d --- /dev/null +++ b/ControllerService/Targets/Xbox360Target.cs @@ -0,0 +1,91 @@ +using Nefarius.ViGEm.Client; +using Nefarius.ViGEm.Client.Targets; +using Nefarius.ViGEm.Client.Targets.Xbox360; +using SharpDX.XInput; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Timers; + +namespace ControllerService.Targets +{ + internal partial class Xbox360Target : ViGEmTarget + { + private static readonly List ButtonMap = new List + { + Xbox360Button.Up, + Xbox360Button.Down, + Xbox360Button.Left, + Xbox360Button.Right, + Xbox360Button.Start, + Xbox360Button.Back, + Xbox360Button.LeftThumb, + Xbox360Button.RightThumb, + Xbox360Button.LeftShoulder, + Xbox360Button.RightShoulder, + Xbox360Button.Guide, + Xbox360Button.A, + Xbox360Button.B, + Xbox360Button.X, + Xbox360Button.Y + }; + + private static readonly List AxisMap = new List + { + Xbox360Axis.LeftThumbX, + Xbox360Axis.LeftThumbY, + Xbox360Axis.RightThumbX, + Xbox360Axis.RightThumbY + }; + + private static readonly List SliderMap = new List + { + Xbox360Slider.LeftTrigger, + Xbox360Slider.RightTrigger + }; + + private new IXbox360Controller vcontroller; + + public Xbox360Target(ViGEmClient client, Controller controller, int index) : base(client, controller, index) + { + // initialize controller + vcontroller = client.CreateXbox360Controller(); + vcontroller.AutoSubmitReport = false; + + vcontroller.Connect(); + } + + public new void Disconnect() + { + vcontroller.Disconnect(); + } + + public new unsafe void UpdateReport() + { + if (!Controller.IsConnected) + return; + + base.UpdateReport(); + + vcontroller.SetAxisValue(Xbox360Axis.LeftThumbX, LeftThumbX); + vcontroller.SetAxisValue(Xbox360Axis.LeftThumbY, LeftThumbY); + vcontroller.SetAxisValue(Xbox360Axis.RightThumbX, RightThumbX); + vcontroller.SetAxisValue(Xbox360Axis.RightThumbY, RightThumbY); + + foreach (Xbox360Button button in (Xbox360Button[])Enum.GetValues(typeof(Xbox360Button))) + { + GamepadButtonFlags value = (GamepadButtonFlags)button.Value; + vcontroller.SetButtonState(button, Gamepad.Buttons.HasFlag(value)); + } + + vcontroller.SetSliderValue(Xbox360Slider.LeftTrigger, Gamepad.LeftTrigger); + vcontroller.SetSliderValue(Xbox360Slider.RightTrigger, Gamepad.RightTrigger); + + if (!profile.whitelisted) + vcontroller.SubmitReport(); + } + } +} diff --git a/ControllerService/XInputAccelerometer.cs b/ControllerService/XInputAccelerometer.cs index bb6e7132e..888aa49dd 100644 --- a/ControllerService/XInputAccelerometer.cs +++ b/ControllerService/XInputAccelerometer.cs @@ -53,10 +53,13 @@ void AcceleroReadingChanged(Accelerometer sender, AccelerometerReadingChangedEve this.reading.Y = (float)accelFilter.axis1Filter.Filter(reading.AccelerationZ, rate); this.reading.Z = (float)accelFilter.axis1Filter.Filter(reading.AccelerationY, rate); - this.reading *= controller.profile.accelerometer; + if (controller.target != null) + { + this.reading *= controller.target.profile.accelerometer; - this.reading.Z = (controller.profile.inverthorizontal ? -1.0f : 1.0f) * this.reading.Z; - this.reading.X = (controller.profile.invertvertical ? -1.0f : 1.0f) * this.reading.X; + this.reading.Z = (controller.target.profile.inverthorizontal ? -1.0f : 1.0f) * this.reading.Z; + this.reading.X = (controller.target.profile.invertvertical ? -1.0f : 1.0f) * this.reading.X; + } // raise event ReadingChanged?.Invoke(this, this.reading); diff --git a/ControllerService/XInputController.cs b/ControllerService/XInputController.cs index b47e699a1..01ed3f305 100644 --- a/ControllerService/XInputController.cs +++ b/ControllerService/XInputController.cs @@ -1,8 +1,10 @@ using ControllerCommon; +using ControllerService.Targets; using Microsoft.Extensions.Logging; using Nefarius.ViGEm.Client; using Nefarius.ViGEm.Client.Targets; using Nefarius.ViGEm.Client.Targets.DualShock4; +using Nefarius.ViGEm.Client.Targets.Xbox360; using SharpDX.DirectInput; using SharpDX.XInput; using System; @@ -10,109 +12,56 @@ using System.Diagnostics; using System.Numerics; using System.Runtime.InteropServices; +using System.Threading.Tasks; using System.Timers; using static ControllerCommon.Utils; -using Timer = System.Timers.Timer; namespace ControllerService { public class XInputController { - #region imports - [StructLayout(LayoutKind.Sequential)] - public struct XInputStateSecret - { - public uint eventCount; - public ushort wButtons; - public byte bLeftTrigger; - public byte bRightTrigger; - public short sThumbLX; - public short sThumbLY; - public short sThumbRX; - public short sThumbRY; - } - - [DllImport("xinput1_3.dll", EntryPoint = "#100")] - private static extern int XInputGetStateSecret13(int playerIndex, out XInputStateSecret struc); - [DllImport("xinput1_4.dll", EntryPoint = "#100")] - private static extern int XInputGetStateSecret14(int playerIndex, out XInputStateSecret struc); - #endregion + public Controller Controller; + public ViGEmTarget target; - private const float F_ACC_RES_PER_G = 8192.0f; - private const float F_GYRO_RES_IN_DEG_SEC = 16.0f; - - public Controller controller; - public Gamepad gamepad; - public XInputStateSecret state_s; public DeviceInstance instance; private DSUServer server; - private IVirtualGamepad vcontroller; public XInputGirometer gyrometer; public XInputAccelerometer accelerometer; - public DS4Touch touch; - - public Vector3 AngularVelocity; - public Vector3 Acceleration; private readonly Timer UpdateTimer; private float strength; public UserIndex index; - public Profile profile; - - public long microseconds; - private readonly Stopwatch stopwatch; - - private readonly object updateLock = new(); - - private DS4_REPORT_EX outDS4Report; + private object updateLock = new(); private readonly ILogger logger; + private readonly string HIDmode; - public XInputController(UserIndex _idx, int HIDrate, ILogger logger) + public XInputController(Controller controller, UserIndex index, int HIDrate, string HIDmode, ILogger logger) { this.logger = logger; + this.HIDmode = HIDmode; // initilize controller - controller = new Controller(_idx); - index = _idx; - - if (!controller.IsConnected) - return; - - // initialize profile - profile = new(); - - // initialize vectors - AngularVelocity = new(); - Acceleration = new(); - - // initialize secret state - state_s = new(); - - // initialize stopwatch - stopwatch = new(); - stopwatch.Start(); + this.Controller = controller; + this.index = index; // initialize timers UpdateTimer = new Timer(HIDrate) { Enabled = false, AutoReset = true }; - - // initialize touch - touch = new(); } public void SetPollRate(int HIDrate) { UpdateTimer.Interval = HIDrate; - logger.LogInformation("Virtual {0} report interval set to {1}ms", vcontroller.GetType().Name, UpdateTimer.Interval); + logger.LogInformation("Virtual {0} report interval set to {1}ms", target.GetType().Name, UpdateTimer.Interval); } public void SetVibrationStrength(float strength) { this.strength = strength / 100.0f; - logger.LogInformation("Virtual {0} vibration strength set to {1}%", vcontroller.GetType().Name, strength); + logger.LogInformation("Virtual {0} vibration strength set to {1}%", target.GetType().Name, strength); } public Dictionary ToArgs() @@ -125,40 +74,30 @@ public Dictionary ToArgs() }; } - public void SetVirtualController(IVirtualGamepad _controller) + private void XBOX_FeedbackReceived(object sender, Xbox360FeedbackReceivedEventArgs e) { - vcontroller = _controller; - vcontroller.AutoSubmitReport = false; + if (!Controller.IsConnected) + return; - switch (vcontroller.GetType().FullName) + Vibration inputMotor = new() { - case "Nefarius.ViGEm.Client.Targets.DualShock4Controller": - UpdateTimer.Elapsed += DS4_UpdateReport; - ((IDualShock4Controller)vcontroller).FeedbackReceived += DS4_FeedbackReceived; - break; - case "Nefarius.ViGEm.Client.Targets.Xbox360Controller": - throw new NotImplementedException(); - break; - } - - UpdateTimer.Enabled = true; - UpdateTimer.Start(); - - logger.LogInformation("Virtual {0} attached to {1} on slot {2}", vcontroller.GetType().Name, instance.InstanceName, index); - logger.LogInformation("Virtual {0} report interval set to {1}ms", vcontroller.GetType().Name, UpdateTimer.Interval); + LeftMotorSpeed = (ushort)((e.LargeMotor * ushort.MaxValue / byte.MaxValue) * strength), + RightMotorSpeed = (ushort)((e.SmallMotor * ushort.MaxValue / byte.MaxValue) * strength), + }; + Controller.SetVibration(inputMotor); } private void DS4_FeedbackReceived(object sender, DualShock4FeedbackReceivedEventArgs e) { - if (controller.IsConnected) + if (!Controller.IsConnected) + return; + + Vibration inputMotor = new() { - Vibration inputMotor = new() - { - LeftMotorSpeed = (ushort)((e.LargeMotor * ushort.MaxValue / byte.MaxValue) * strength), - RightMotorSpeed = (ushort)((e.SmallMotor * ushort.MaxValue / byte.MaxValue) * strength), - }; - controller.SetVibration(inputMotor); - } + LeftMotorSpeed = (ushort)((e.LargeMotor * ushort.MaxValue / byte.MaxValue) * strength), + RightMotorSpeed = (ushort)((e.SmallMotor * ushort.MaxValue / byte.MaxValue) * strength), + }; + Controller.SetVibration(inputMotor); } public void SetGyroscope(XInputGirometer _gyrometer) @@ -180,178 +119,61 @@ public void SetDSUServer(DSUServer _server) private void Accelerometer_ReadingChanged(object sender, Vector3 acceleration) { - Acceleration = acceleration; + target.Acceleration = acceleration; } private void Girometer_ReadingChanged(object sender, Vector3 angularvelocity) { - AngularVelocity = angularvelocity; + target.AngularVelocity = angularvelocity; } - private unsafe void DS4_UpdateReport(object sender, ElapsedEventArgs e) + public void SetTarget(ViGEmClient client) { - if (!controller.IsConnected) - return; - - lock (updateLock) + switch (HIDmode) { - // update timestamp - microseconds = (long)(stopwatch.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L))); - - // get current gamepad state - State state = controller.GetState(); - gamepad = state.Gamepad; - - XInputGetStateSecret13((int)index, out state_s); - - // send report to server - server?.NewReportIncoming(this, microseconds); - - // reset vars - byte[] rawOutReportEx = new byte[63]; - ushort tempButtons = 0; - ushort tempSpecial = 0; - DualShock4DPadDirection tempDPad = DualShock4DPadDirection.None; - - outDS4Report.bThumbLX = 127; - outDS4Report.bThumbLY = 127; - outDS4Report.bThumbRX = 127; - outDS4Report.bThumbRY = 127; - - short LeftThumbX = gamepad.LeftThumbX; - short LeftThumbY = gamepad.LeftThumbY; - short RightThumbX = gamepad.RightThumbX; - short RightThumbY = gamepad.RightThumbY; - - unchecked - { - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.A)) - tempButtons |= DualShock4Button.Cross.Value; - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.B)) - tempButtons |= DualShock4Button.Circle.Value; - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.X)) - tempButtons |= DualShock4Button.Square.Value; - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.Y)) - tempButtons |= DualShock4Button.Triangle.Value; - - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.Start)) - tempButtons |= DualShock4Button.Options.Value; - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.Back)) - tempButtons |= DualShock4Button.Share.Value; - - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.RightThumb)) - tempButtons |= DualShock4Button.ThumbRight.Value; - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftThumb)) - tempButtons |= DualShock4Button.ThumbLeft.Value; - - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.RightShoulder)) - tempButtons |= DualShock4Button.ShoulderRight.Value; - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.LeftShoulder)) - tempButtons |= DualShock4Button.ShoulderLeft.Value; - - if (gamepad.LeftTrigger > 0) - tempButtons |= DualShock4Button.TriggerLeft.Value; - if (gamepad.RightTrigger > 0) - tempButtons |= DualShock4Button.TriggerRight.Value; - - if (gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp) && - gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight)) - tempDPad = DualShock4DPadDirection.Northeast; - else if (gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp) && - gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft)) - tempDPad = DualShock4DPadDirection.Northwest; - else if (gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadUp)) - tempDPad = DualShock4DPadDirection.North; - else if (gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight) && - gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown)) - tempDPad = DualShock4DPadDirection.Southeast; - else if (gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadRight)) - tempDPad = DualShock4DPadDirection.East; - else if (gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown) && - gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft)) - tempDPad = DualShock4DPadDirection.Southwest; - else if (gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadDown)) - tempDPad = DualShock4DPadDirection.South; - else if (gamepad.Buttons.HasFlag(GamepadButtonFlags.DPadLeft)) - tempDPad = DualShock4DPadDirection.West; - - if ((state_s.wButtons & 0x0400) == 0x0400) - tempSpecial |= DualShock4SpecialButton.Ps.Value; - if (touch.OutputClickButton) - tempSpecial |= DualShock4SpecialButton.Touchpad.Value; - - outDS4Report.bSpecial = (byte)(tempSpecial | (0 << 2)); - } - - if (profile.umc_enabled && ((tempButtons + ProfileButton.AlwaysOn.Value) & profile.umc_trigger) != 0) - { - float intensity = profile.GetIntensity(); - float sensivity = profile.GetSensiviy(); - - switch (profile.umc_input) - { - default: - case InputStyle.RightStick: - RightThumbX = ComputeInput(RightThumbX, -AngularVelocity.Z * 1.5f, sensivity, intensity); - RightThumbY = ComputeInput(RightThumbY, AngularVelocity.X, sensivity, intensity); - break; - case InputStyle.LeftStick: - LeftThumbX = ComputeInput(LeftThumbX, -AngularVelocity.Z * 1.5f, sensivity, intensity); - LeftThumbY = ComputeInput(LeftThumbY, AngularVelocity.X, sensivity, intensity); - break; - } - } + default: + case "DualShock4Controller": + target = new DualShock4Target(client, Controller, (int)index); + break; + case "Xbox360Controller": + target = new Xbox360Target(client, Controller, (int)index); + break; + } - if (!profile.whitelisted) - { - outDS4Report.wButtons = tempButtons; - outDS4Report.wButtons |= tempDPad.Value; + if (target == null) + { + logger.LogCritical("No Virtual controller detected. Application will stop"); + throw new InvalidOperationException(); + } - outDS4Report.bTriggerL = gamepad.LeftTrigger; - outDS4Report.bTriggerR = gamepad.RightTrigger; + UpdateTimer.Elapsed += async (sender, e) => await UpdateReport(); + UpdateTimer.Enabled = true; + UpdateTimer.Start(); - outDS4Report.bThumbLX = NormalizeInput(LeftThumbX); - outDS4Report.bThumbLY = (byte)(byte.MaxValue - NormalizeInput(LeftThumbY)); - outDS4Report.bThumbRX = NormalizeInput(RightThumbX); - outDS4Report.bThumbRY = (byte)(byte.MaxValue - NormalizeInput(RightThumbY)); - } + logger.LogInformation("Virtual {0} connected", target.GetType().Name); + logger.LogInformation("Virtual {0} attached to {1} on slot {2}", target.GetType().Name, instance.InstanceName, index); + logger.LogInformation("Virtual {0} report interval set to {1}ms", target.GetType().Name, UpdateTimer.Interval); + } - unchecked + private Task UpdateReport() + { + lock (updateLock) + { + // that suxx ! + switch (HIDmode) { - outDS4Report.bTouchPacketsN = 0x01; - outDS4Report.sCurrentTouch.bPacketCounter = touch.TouchPacketCounter; - outDS4Report.sCurrentTouch.bIsUpTrackingNum1 = touch.TrackPadTouch0.RawTrackingNum; - outDS4Report.sCurrentTouch.bTouchData1[0] = (byte)(touch.TrackPadTouch0.X & 0xFF); - outDS4Report.sCurrentTouch.bTouchData1[1] = - (byte)(((touch.TrackPadTouch0.X >> 8) & 0x0F) | ((touch.TrackPadTouch0.Y << 4) & 0xF0)); - outDS4Report.sCurrentTouch.bTouchData1[2] = (byte)(touch.TrackPadTouch0.Y >> 4); - - outDS4Report.sCurrentTouch.bIsUpTrackingNum2 = touch.TrackPadTouch1.RawTrackingNum; - outDS4Report.sCurrentTouch.bTouchData2[0] = (byte)(touch.TrackPadTouch1.X & 0xFF); - outDS4Report.sCurrentTouch.bTouchData2[1] = - (byte)(((touch.TrackPadTouch1.X >> 8) & 0x0F) | ((touch.TrackPadTouch1.Y << 4) & 0xF0)); - outDS4Report.sCurrentTouch.bTouchData2[2] = (byte)(touch.TrackPadTouch1.Y >> 4); + default: + case "DualShock4Controller": + ((DualShock4Target)target)?.UpdateReport(); + break; + case "Xbox360Controller": + ((Xbox360Target)target)?.UpdateReport(); + break; } - - outDS4Report.wGyroX = (short)(AngularVelocity.X * F_GYRO_RES_IN_DEG_SEC); // gyroPitchFull - outDS4Report.wGyroY = (short)(-AngularVelocity.Y * F_GYRO_RES_IN_DEG_SEC); // gyroYawFull - outDS4Report.wGyroZ = (short)(AngularVelocity.Z * F_GYRO_RES_IN_DEG_SEC); // gyroRollFull - - outDS4Report.wAccelX = (short)(-Acceleration.X * F_ACC_RES_PER_G); // accelXFull - outDS4Report.wAccelY = (short)(-Acceleration.Y * F_ACC_RES_PER_G); // accelYFull - outDS4Report.wAccelZ = (short)(Acceleration.Z * F_ACC_RES_PER_G); // accelZFull - - // digest previous value - // AngularVelocity = new(); - // Acceleration = new(); - - outDS4Report.bBatteryLvlSpecial = 11; - - outDS4Report.wTimestamp = (ushort)(microseconds / 5.33f); - - DS4OutDeviceExtras.CopyBytes(ref outDS4Report, rawOutReportEx); - ((IDualShock4Controller)vcontroller).SubmitRawReport(rawOutReportEx); + server?.NewReportIncoming(target); } + + return Task.CompletedTask; } } } diff --git a/ControllerService/XInputGirometer.cs b/ControllerService/XInputGirometer.cs index 4e6b16bc8..0eb33141d 100644 --- a/ControllerService/XInputGirometer.cs +++ b/ControllerService/XInputGirometer.cs @@ -54,10 +54,13 @@ void GyroReadingChanged(Gyrometer sender, GyrometerReadingChangedEventArgs args) this.reading.Y = (float)gyroFilter.axis1Filter.Filter(reading.AngularVelocityZ, rate); this.reading.Z = (float)gyroFilter.axis1Filter.Filter(reading.AngularVelocityY, rate); - this.reading *= controller.profile.gyrometer; + if (controller.target != null) + { + this.reading *= controller.target.profile.gyrometer; - this.reading.Z = (controller.profile.inverthorizontal ? -1.0f : 1.0f) * this.reading.Z; - this.reading.X = (controller.profile.invertvertical ? -1.0f : 1.0f) * this.reading.X; + this.reading.Z = (controller.target.profile.inverthorizontal ? -1.0f : 1.0f) * this.reading.Z; + this.reading.X = (controller.target.profile.invertvertical ? -1.0f : 1.0f) * this.reading.X; + } // raise event ReadingChanged?.Invoke(this, this.reading);