diff --git a/SteamController/Devices/SteamControllerHaptic.cs b/SteamController/Devices/SteamControllerHaptic.cs index 9b7dcca..34ef6c5 100644 --- a/SteamController/Devices/SteamControllerHaptic.cs +++ b/SteamController/Devices/SteamControllerHaptic.cs @@ -8,10 +8,16 @@ namespace SteamController.Devices { public partial class SteamController { - private bool[] hapticEnabled = new bool[byte.MaxValue]; + private bool[] feedbackEnabled = new bool[byte.MaxValue]; - private bool sendHaptic(byte position, ushort amplitude, ushort period, ushort count = 0) + public bool SetFeedback(byte position, ushort amplitude, ushort period, ushort count = 0) { + // do not send repeated haptic queries if was disabled + bool enabled = amplitude != 0 && period != 0; + if (!feedbackEnabled[position] && !enabled) + return false; + feedbackEnabled[position] = enabled; + var haptic = new SDCHapticPacket() { packet_type = (byte)SDCPacketType.PT_FEEDBACK, @@ -22,7 +28,7 @@ namespace SteamController.Devices count = count }; - Log.TraceLine("STEAM: Haptic: pos={0}, amplitude={1}, period={2}, count={3}", + Log.TraceLine("STEAM: Feedback: pos={0}, amplitude={1}, period={2}, count={3}", position, amplitude, period, count); var bytes = new byte[Marshal.SizeOf()]; @@ -34,21 +40,56 @@ namespace SteamController.Devices return true; } catch (Exception e) + { + Log.TraceLine("STEAM: Feedback: Exception: {0}", e); + return false; + } + } + + [StructLayout(LayoutKind.Sequential)] + private struct SDCHapticPacket2 + { + public byte packet_type = 0xea; + public byte len = 0xd; + public byte position = 0x00; + public byte amplitude = 0x2; // + public byte unsure2 = 0x0; + public sbyte intensity = 0x00; // -7..5 => -2dB..10dB + public byte unsure3 = 0x4; + public int tsA = 0; // timestamp? + public int tsB = 0; + + public SDCHapticPacket2() { } + } + + public bool SendHaptic(byte position, sbyte intensity) + { + var ts = Random.Shared.Next(); + + var haptic = new SDCHapticPacket2() + { + position = position, + intensity = intensity, + tsA = ts, + tsB = ts + }; + + Log.TraceLine("STEAM: Haptic: pos={0}, intensity={1}", + position, intensity); + + var bytes = new byte[Marshal.SizeOf()]; + var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); + try + { + Marshal.StructureToPtr(haptic, handle.AddrOfPinnedObject(), false); + neptuneDevice.RequestFeatureReport(bytes); + return true; + } + catch (Exception e) { Log.TraceLine("STEAM: Haptic: Exception: {0}", e); return false; } } - - public bool SetHaptic(byte position, ushort amplitude, ushort period, ushort count = 0) - { - // do not send repeated haptic queries if was disabled - bool enabled = amplitude != 0 && period != 0; - if (!hapticEnabled[position] && !enabled) - return false; - hapticEnabled[position] = enabled; - - return sendHaptic(position, amplitude, period, count); - } } } diff --git a/SteamController/Profiles/X360RumbleProfile.cs b/SteamController/Profiles/X360RumbleProfile.cs index 912f259..afa2a4c 100644 --- a/SteamController/Profiles/X360RumbleProfile.cs +++ b/SteamController/Profiles/X360RumbleProfile.cs @@ -21,17 +21,29 @@ namespace SteamController.Profiles return Status.Done; } +#if false + if (context.X360.FeedbackLargeMotor.GetValueOrDefault() > 0) + { + context.Steam.SetHaptic2(1, 0); + } + + if (context.X360.FeedbackSmallMotor.GetValueOrDefault() > 0) + { + context.Steam.SetHaptic2(0, 0); + } +#else if (context.X360.FeedbackLargeMotor.HasValue) { - context.Steam.SetHaptic( + context.Steam.SetFeedback( 1, GetHapticAmplitude(context.X360.FeedbackLargeMotor), RumbleSettings.Period, FeedbackCount); } if (context.X360.FeedbackSmallMotor.HasValue) { - context.Steam.SetHaptic( + context.Steam.SetFeedback( 0, GetHapticAmplitude(context.X360.FeedbackSmallMotor), RumbleSettings.Period, FeedbackCount); } +#endif context.X360.ResetFeedback(); @@ -40,7 +52,9 @@ namespace SteamController.Profiles private ushort GetHapticAmplitude(byte? value) { - if (RumbleSettings.FixedAmplitude > 0) + if (value == 0) + return 0; + else if (RumbleSettings.FixedAmplitude > 0) return value is not null ? (ushort)RumbleSettings.FixedAmplitude : (ushort)0; else return (ushort)(RumbleSettings.MaxAmplitude * (value ?? 0) / byte.MaxValue);