mirror of
https://github.com/ayufan/steam-deck-tools.git
synced 2026-01-05 16:19:56 +01:00
SteamController: Add initial DS4 support (with Gyro, Accel, Trackpads and Haptics)
This commit is contained in:
parent
862d7afec5
commit
70237ad9d4
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
## 0.6.x
|
## 0.6.x
|
||||||
|
|
||||||
|
- SteamController: Add initial `DS4` support (with Gyro, Accel, Trackpads and Haptics)
|
||||||
- PowerControl: Install custom resolutions (EDID) (experimental feature)
|
- PowerControl: Install custom resolutions (EDID) (experimental feature)
|
||||||
- SteamController: Add `X360: No Touchpads` profile
|
- SteamController: Add `X360: No Touchpads` profile
|
||||||
- All: Show `Missing RTSS` button to install RTSS
|
- All: Show `Missing RTSS` button to install RTSS
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ namespace SteamController
|
||||||
|
|
||||||
public Devices.SteamController Steam { get; private set; }
|
public Devices.SteamController Steam { get; private set; }
|
||||||
public Devices.Xbox360Controller X360 { get; private set; }
|
public Devices.Xbox360Controller X360 { get; private set; }
|
||||||
|
public Devices.DS4Controller DS4 { get; private set; }
|
||||||
public Devices.KeyboardController Keyboard { get; private set; }
|
public Devices.KeyboardController Keyboard { get; private set; }
|
||||||
public Devices.MouseController Mouse { get; private set; }
|
public Devices.MouseController Mouse { get; private set; }
|
||||||
|
|
||||||
|
|
@ -25,11 +26,12 @@ namespace SteamController
|
||||||
public bool GameProcessRunning { get; set; }
|
public bool GameProcessRunning { get; set; }
|
||||||
public bool RTSSInForeground { get; set; }
|
public bool RTSSInForeground { get; set; }
|
||||||
public bool SteamUsesX360Controller { get; set; }
|
public bool SteamUsesX360Controller { get; set; }
|
||||||
|
public bool SteamUsesDS4Controller { get; set; }
|
||||||
public bool SteamUsesSteamInput { get; set; }
|
public bool SteamUsesSteamInput { get; set; }
|
||||||
|
|
||||||
public bool IsActive
|
public bool IsActive
|
||||||
{
|
{
|
||||||
get { return RTSSInForeground || GameProcessRunning || SteamUsesX360Controller || SteamUsesSteamInput; }
|
get { return RTSSInForeground || GameProcessRunning || SteamUsesX360Controller || SteamUsesDS4Controller || SteamUsesSteamInput; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|
@ -37,6 +39,7 @@ namespace SteamController
|
||||||
string reason = "state";
|
string reason = "state";
|
||||||
if (GameProcessRunning) reason += " game";
|
if (GameProcessRunning) reason += " game";
|
||||||
if (SteamUsesX360Controller) reason += " steamX360";
|
if (SteamUsesX360Controller) reason += " steamX360";
|
||||||
|
if (SteamUsesDS4Controller) reason += " steamDS4";
|
||||||
if (SteamUsesSteamInput) reason += " steamInput";
|
if (SteamUsesSteamInput) reason += " steamInput";
|
||||||
if (RTSSInForeground) reason += " rtss";
|
if (RTSSInForeground) reason += " rtss";
|
||||||
return reason;
|
return reason;
|
||||||
|
|
@ -78,6 +81,7 @@ namespace SteamController
|
||||||
{
|
{
|
||||||
Steam = new Devices.SteamController();
|
Steam = new Devices.SteamController();
|
||||||
X360 = new Devices.Xbox360Controller();
|
X360 = new Devices.Xbox360Controller();
|
||||||
|
DS4 = new Devices.DS4Controller();
|
||||||
Keyboard = new Devices.KeyboardController();
|
Keyboard = new Devices.KeyboardController();
|
||||||
Mouse = new Devices.MouseController();
|
Mouse = new Devices.MouseController();
|
||||||
|
|
||||||
|
|
@ -92,6 +96,7 @@ namespace SteamController
|
||||||
|
|
||||||
using (Steam) { }
|
using (Steam) { }
|
||||||
using (X360) { }
|
using (X360) { }
|
||||||
|
using (DS4) { }
|
||||||
using (Keyboard) { }
|
using (Keyboard) { }
|
||||||
using (Mouse) { }
|
using (Mouse) { }
|
||||||
}
|
}
|
||||||
|
|
@ -99,6 +104,7 @@ namespace SteamController
|
||||||
public void Tick()
|
public void Tick()
|
||||||
{
|
{
|
||||||
X360.Tick();
|
X360.Tick();
|
||||||
|
DS4.Tick();
|
||||||
|
|
||||||
foreach (var manager in Managers)
|
foreach (var manager in Managers)
|
||||||
{
|
{
|
||||||
|
|
@ -111,6 +117,7 @@ namespace SteamController
|
||||||
{
|
{
|
||||||
Steam.BeforeUpdate();
|
Steam.BeforeUpdate();
|
||||||
X360.BeforeUpdate();
|
X360.BeforeUpdate();
|
||||||
|
DS4.BeforeUpdate();
|
||||||
Keyboard.BeforeUpdate();
|
Keyboard.BeforeUpdate();
|
||||||
Mouse.BeforeUpdate();
|
Mouse.BeforeUpdate();
|
||||||
|
|
||||||
|
|
@ -131,6 +138,7 @@ namespace SteamController
|
||||||
{
|
{
|
||||||
Steam.Update();
|
Steam.Update();
|
||||||
X360.Update();
|
X360.Update();
|
||||||
|
DS4.Update();
|
||||||
Keyboard.Update();
|
Keyboard.Update();
|
||||||
Mouse.Update();
|
Mouse.Update();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ namespace SteamController
|
||||||
items.Add("[LM]");
|
items.Add("[LM]");
|
||||||
|
|
||||||
items.Add(X360.Connected ? "[X360]" : X360.Valid ? "[no-X360]" : "[inv-X360]");
|
items.Add(X360.Connected ? "[X360]" : X360.Valid ? "[no-X360]" : "[inv-X360]");
|
||||||
|
items.Add(DS4.Connected ? "[DS4]" : DS4.Valid ? "[no-DS4]" : "[inv-DS4]");
|
||||||
items.Add(KeyboardMouseValid ? "[KM]" : "[inv-KM]");
|
items.Add(KeyboardMouseValid ? "[KM]" : "[inv-KM]");
|
||||||
|
|
||||||
foreach (var button in Steam.AllButtons)
|
foreach (var button in Steam.AllButtons)
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ namespace SteamController
|
||||||
var nextReset = stopwatch.Elapsed.Add(UpdateResetInterval);
|
var nextReset = stopwatch.Elapsed.Add(UpdateResetInterval);
|
||||||
|
|
||||||
X360.Start();
|
X360.Start();
|
||||||
|
DS4.Start();
|
||||||
|
|
||||||
while (threadRunning)
|
while (threadRunning)
|
||||||
{
|
{
|
||||||
|
|
@ -58,6 +59,7 @@ namespace SteamController
|
||||||
}
|
}
|
||||||
|
|
||||||
X360.Stop();
|
X360.Stop();
|
||||||
|
DS4.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Stop()
|
public void Stop()
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,10 @@ namespace SteamController
|
||||||
new Profiles.Predefined.SteamProfile() { Name = "Steam", Visible = false },
|
new Profiles.Predefined.SteamProfile() { Name = "Steam", Visible = false },
|
||||||
new Profiles.Predefined.SteamWithShorcutsProfile() { Name = "Steam with Shortcuts", Visible = false },
|
new Profiles.Predefined.SteamWithShorcutsProfile() { Name = "Steam with Shortcuts", Visible = false },
|
||||||
new Profiles.Predefined.X360HapticProfile() { Name = "X360", EmulateTouchPads = true },
|
new Profiles.Predefined.X360HapticProfile() { Name = "X360", EmulateTouchPads = true },
|
||||||
new Profiles.Predefined.X360HapticProfile() { Name = "X360: No Touchpads", EmulateTouchPads = false }
|
new Profiles.Predefined.X360HapticProfile() { Name = "X360: No Touchpads", EmulateTouchPads = false },
|
||||||
|
#if DEBUG
|
||||||
|
new Profiles.Predefined.DS4HapticProfile() { Name = "DS4" },
|
||||||
|
#endif
|
||||||
},
|
},
|
||||||
Managers = {
|
Managers = {
|
||||||
new Managers.ProcessManager(),
|
new Managers.ProcessManager(),
|
||||||
|
|
@ -274,8 +277,12 @@ namespace SteamController
|
||||||
Devices.Xbox360Controller.VendorID,
|
Devices.Xbox360Controller.VendorID,
|
||||||
Devices.Xbox360Controller.ProductID
|
Devices.Xbox360Controller.ProductID
|
||||||
);
|
);
|
||||||
|
var blacklistedDS4Controller = Helpers.SteamConfiguration.IsControllerBlacklisted(
|
||||||
|
Devices.DS4Controller.VendorID,
|
||||||
|
Devices.DS4Controller.ProductID
|
||||||
|
);
|
||||||
|
|
||||||
if (blacklistedSteamController is null || blacklistedX360Controller is null)
|
if (blacklistedSteamController is null || blacklistedX360Controller is null || blacklistedDS4Controller is null)
|
||||||
{
|
{
|
||||||
// Appears that Steam is not installed
|
// Appears that Steam is not installed
|
||||||
if (always)
|
if (always)
|
||||||
|
|
@ -291,11 +298,12 @@ namespace SteamController
|
||||||
page.Caption = TitleWithVersion;
|
page.Caption = TitleWithVersion;
|
||||||
page.AllowCancel = true;
|
page.AllowCancel = true;
|
||||||
|
|
||||||
var useX360Controller = page.RadioButtons.Add("Use &X360 Controller with Steam (preferred)");
|
var useXInputController = page.RadioButtons.Add("Use &X360/DS4 Controller with Steam (preferred)");
|
||||||
useX360Controller.Text += "\n- Will always use X360 controller.";
|
useXInputController.Text += "\n- Will always use X360 or DS4 controller.";
|
||||||
useX360Controller.Checked = Settings.Default.EnableSteamDetection == true &&
|
useXInputController.Checked = Settings.Default.EnableSteamDetection == true &&
|
||||||
blacklistedSteamController == true &&
|
blacklistedSteamController == true &&
|
||||||
blacklistedX360Controller == false;
|
blacklistedX360Controller == false &&
|
||||||
|
blacklistedDS4Controller == false;
|
||||||
|
|
||||||
var useSteamInput = page.RadioButtons.Add("Use &Steam Input with Steam (requires configuration)");
|
var useSteamInput = page.RadioButtons.Add("Use &Steam Input with Steam (requires configuration)");
|
||||||
useSteamInput.Text += "\n- Will try to use Steam controls.";
|
useSteamInput.Text += "\n- Will try to use Steam controls.";
|
||||||
|
|
@ -303,13 +311,14 @@ namespace SteamController
|
||||||
useSteamInput.Text += "\n- Click Help for more information.";
|
useSteamInput.Text += "\n- Click Help for more information.";
|
||||||
useSteamInput.Checked = Settings.Default.EnableSteamDetection == true &&
|
useSteamInput.Checked = Settings.Default.EnableSteamDetection == true &&
|
||||||
blacklistedSteamController == false &&
|
blacklistedSteamController == false &&
|
||||||
blacklistedX360Controller == true;
|
blacklistedX360Controller == true &&
|
||||||
|
blacklistedDS4Controller == true;
|
||||||
|
|
||||||
var ignoreSteam = page.RadioButtons.Add("&Ignore Steam (only if you know why you need it)");
|
var ignoreSteam = page.RadioButtons.Add("&Ignore Steam (only if you know why you need it)");
|
||||||
ignoreSteam.Text += "\n- Will revert all previously made changes.";
|
ignoreSteam.Text += "\n- Will revert all previously made changes.";
|
||||||
ignoreSteam.Checked = Settings.Default.EnableSteamDetection == false;
|
ignoreSteam.Checked = Settings.Default.EnableSteamDetection == false;
|
||||||
|
|
||||||
bool valid = ignoreSteam.Checked || useX360Controller.Checked || useSteamInput.Checked;
|
bool valid = ignoreSteam.Checked || useXInputController.Checked || useSteamInput.Checked;
|
||||||
|
|
||||||
// If everything is OK, on subsequent runs nothing to configure
|
// If everything is OK, on subsequent runs nothing to configure
|
||||||
if (valid && !always)
|
if (valid && !always)
|
||||||
|
|
@ -352,16 +361,21 @@ namespace SteamController
|
||||||
var steamControllerUpdate = Helpers.SteamConfiguration.UpdateControllerBlacklist(
|
var steamControllerUpdate = Helpers.SteamConfiguration.UpdateControllerBlacklist(
|
||||||
Devices.SteamController.VendorID,
|
Devices.SteamController.VendorID,
|
||||||
Devices.SteamController.ProductID,
|
Devices.SteamController.ProductID,
|
||||||
useX360Controller.Checked
|
useXInputController.Checked
|
||||||
);
|
);
|
||||||
var x360ControllerUpdate = Helpers.SteamConfiguration.UpdateControllerBlacklist(
|
var x360ControllerUpdate = Helpers.SteamConfiguration.UpdateControllerBlacklist(
|
||||||
Devices.Xbox360Controller.VendorID,
|
Devices.Xbox360Controller.VendorID,
|
||||||
Devices.Xbox360Controller.ProductID,
|
Devices.Xbox360Controller.ProductID,
|
||||||
useSteamInput.Checked
|
useSteamInput.Checked
|
||||||
);
|
);
|
||||||
Settings.Default.EnableSteamDetection = useSteamInput.Checked || useX360Controller.Checked;
|
var ds4ControllerUpdate = Helpers.SteamConfiguration.UpdateControllerBlacklist(
|
||||||
|
Devices.DS4Controller.VendorID,
|
||||||
|
Devices.DS4Controller.ProductID,
|
||||||
|
useSteamInput.Checked
|
||||||
|
);
|
||||||
|
Settings.Default.EnableSteamDetection = useSteamInput.Checked || useXInputController.Checked;
|
||||||
|
|
||||||
if (steamControllerUpdate && x360ControllerUpdate)
|
if (steamControllerUpdate && x360ControllerUpdate && ds4ControllerUpdate)
|
||||||
{
|
{
|
||||||
notifyIcon.ShowBalloonTip(
|
notifyIcon.ShowBalloonTip(
|
||||||
3000, TitleWithVersion,
|
3000, TitleWithVersion,
|
||||||
|
|
@ -399,7 +413,11 @@ namespace SteamController
|
||||||
{
|
{
|
||||||
Desktop = ProfilesSettings.DesktopPanelSettings.Default,
|
Desktop = ProfilesSettings.DesktopPanelSettings.Default,
|
||||||
X360 = ProfilesSettings.X360BackPanelSettings.Default,
|
X360 = ProfilesSettings.X360BackPanelSettings.Default,
|
||||||
X360Haptic = ProfilesSettings.X360HapticSettings.Default,
|
X360Haptic = ProfilesSettings.HapticSettings.X360,
|
||||||
|
#if DEBUG
|
||||||
|
DS4 = ProfilesSettings.DS4BackPanelSettings.Default,
|
||||||
|
DS4Haptic = ProfilesSettings.HapticSettings.DS4,
|
||||||
|
#endif
|
||||||
Application = Settings.Default,
|
Application = Settings.Default,
|
||||||
DEBUG = SettingsDebug.Default
|
DEBUG = SettingsDebug.Default
|
||||||
}
|
}
|
||||||
|
|
|
||||||
304
SteamController/Devices/DS4Controller.cs
Normal file
304
SteamController/Devices/DS4Controller.cs
Normal file
|
|
@ -0,0 +1,304 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Nefarius.ViGEm.Client;
|
||||||
|
using Nefarius.ViGEm.Client.Exceptions;
|
||||||
|
using Nefarius.ViGEm.Client.Targets;
|
||||||
|
using Nefarius.ViGEm.Client.Targets.DualShock4;
|
||||||
|
using Nefarius.ViGEm.Client.Targets.Xbox360;
|
||||||
|
using static CommonHelpers.Log;
|
||||||
|
|
||||||
|
namespace SteamController.Devices
|
||||||
|
{
|
||||||
|
public partial class DS4Controller : IDisposable
|
||||||
|
{
|
||||||
|
public readonly TimeSpan FeedbackTimeout = TimeSpan.FromMilliseconds(1000);
|
||||||
|
public const ushort VendorID = 0x054C;
|
||||||
|
public const ushort ProductID = 0x05C4;
|
||||||
|
|
||||||
|
private const int REPORT_SIZE = 63;
|
||||||
|
private const int TIMESTAMP_HZ = 800;
|
||||||
|
private const int TIMESTAMP_INCREMENT = 188;
|
||||||
|
|
||||||
|
private ViGEmClient? client;
|
||||||
|
private IDualShock4Controller? device;
|
||||||
|
private bool isConnected;
|
||||||
|
private byte[] reportBytes = new byte[REPORT_SIZE];
|
||||||
|
private bool submitReport;
|
||||||
|
private int submittedReports = 0;
|
||||||
|
private Stopwatch stopwatch = new Stopwatch();
|
||||||
|
|
||||||
|
public DS4Controller()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
using (client) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
lock (this) { Fail(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool Tick()
|
||||||
|
{
|
||||||
|
if (this.device is not null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var client = new ViGEmClient();
|
||||||
|
var device = client.CreateDualShock4Controller();
|
||||||
|
device.AutoSubmitReport = false;
|
||||||
|
device.FeedbackReceived += DS4_FeedbackReceived;
|
||||||
|
this.device = device;
|
||||||
|
this.client = client;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (VigemBusNotFoundException)
|
||||||
|
{
|
||||||
|
// ViGem is not installed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Fail()
|
||||||
|
{
|
||||||
|
var client = this.client;
|
||||||
|
|
||||||
|
// unset current device
|
||||||
|
this.isConnected = false;
|
||||||
|
this.client = null;
|
||||||
|
this.device = null;
|
||||||
|
this.stopwatch.Stop();
|
||||||
|
|
||||||
|
try { using (client) { } }
|
||||||
|
catch (Exception) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrepareReport()
|
||||||
|
{
|
||||||
|
var oldReportBytes = reportBytes;
|
||||||
|
|
||||||
|
reportBytes = new byte[63];
|
||||||
|
submitReport = false;
|
||||||
|
|
||||||
|
Counter.Set(reportBytes, (byte)((submittedReports << 2) & 0xFF));
|
||||||
|
BatteryLevel.Set(reportBytes, 255);
|
||||||
|
Timestamp.Set(reportBytes, (ushort)(stopwatch.ElapsedMilliseconds * TIMESTAMP_HZ * TIMESTAMP_INCREMENT / 1000));
|
||||||
|
|
||||||
|
DPadReleased.Set(reportBytes);
|
||||||
|
LeftThumbX.SetScaled(reportBytes, 0);
|
||||||
|
LeftThumbY.SetScaled(reportBytes, 0);
|
||||||
|
RightThumbX.SetScaled(reportBytes, 0);
|
||||||
|
RightThumbY.SetScaled(reportBytes, 0);
|
||||||
|
GyroX.Set(reportBytes, 0);
|
||||||
|
GyroY.Set(reportBytes, 0);
|
||||||
|
GyroZ.Set(reportBytes, 0);
|
||||||
|
AccelX.Set(reportBytes, 0);
|
||||||
|
AccelY.Set(reportBytes, 0);
|
||||||
|
AccelZ.Set(reportBytes, 0);
|
||||||
|
|
||||||
|
// Copy trackpad packets
|
||||||
|
reportBytes[32] = (byte)((reportBytes[32] + 1) & 0x3);
|
||||||
|
Array.Copy(oldReportBytes, 33, reportBytes, 33, 9);
|
||||||
|
Array.Copy(oldReportBytes, 33, reportBytes, 42, 9 * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void BeforeUpdate()
|
||||||
|
{
|
||||||
|
device?.ResetReport();
|
||||||
|
|
||||||
|
if (!isConnected)
|
||||||
|
{
|
||||||
|
FeedbackLargeMotor = null;
|
||||||
|
FeedbackSmallMotor = null;
|
||||||
|
FeedbackReceived = null;
|
||||||
|
LightbarColor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrepareReport();
|
||||||
|
Connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetConnected(bool wantsConnected)
|
||||||
|
{
|
||||||
|
if (wantsConnected == isConnected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (wantsConnected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
device?.Connect();
|
||||||
|
stopwatch.Restart();
|
||||||
|
TraceLine("Connected DS4 Controller.");
|
||||||
|
}
|
||||||
|
catch (System.ComponentModel.Win32Exception e)
|
||||||
|
{
|
||||||
|
// This is expected exception (as sometimes device will fail to connect)
|
||||||
|
// ERROR_SUCCESS, which likely means COM did not succeed
|
||||||
|
if (e.NativeErrorCode == 0)
|
||||||
|
DebugException("DS4", "ConnectExpected", e);
|
||||||
|
else
|
||||||
|
TraceException("DS4", "ConnectExpected", e);
|
||||||
|
Fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
TraceException("DS4", "Connect", e);
|
||||||
|
Fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
device?.Disconnect();
|
||||||
|
stopwatch.Stop();
|
||||||
|
TraceLine("Disconnected DS4 Controller.");
|
||||||
|
}
|
||||||
|
catch (VigemTargetNotPluggedInException)
|
||||||
|
{
|
||||||
|
// everything fine
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
TraceException("DS4", "Disconnect", e);
|
||||||
|
Fail();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isConnected = wantsConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Update()
|
||||||
|
{
|
||||||
|
if (device is not null && Connected != isConnected)
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
SetConnected(Connected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isConnected && submitReport)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
device?.SubmitRawReport(reportBytes);
|
||||||
|
submittedReports++;
|
||||||
|
}
|
||||||
|
catch (VigemInvalidTargetException)
|
||||||
|
{
|
||||||
|
// Device was lost
|
||||||
|
lock (this) { Fail(); }
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
TraceException("DS4", "SubmitReport", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FeedbackReceived is not null && FeedbackReceived.Value.Add(FeedbackTimeout) < DateTime.Now)
|
||||||
|
{
|
||||||
|
FeedbackLargeMotor = null;
|
||||||
|
FeedbackSmallMotor = null;
|
||||||
|
FeedbackReceived = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Valid
|
||||||
|
{
|
||||||
|
get { return device is not null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Connected { get; set; }
|
||||||
|
public byte? FeedbackLargeMotor { get; private set; }
|
||||||
|
public byte? FeedbackSmallMotor { get; private set; }
|
||||||
|
public LightbarColor? LightbarColor { get; private set; }
|
||||||
|
public DateTime? FeedbackReceived { get; private set; }
|
||||||
|
|
||||||
|
public bool this[DualShock4Button button]
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
button.Set(reportBytes, value);
|
||||||
|
submitReport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool this[DualShock4DPadDirection button]
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
button.Set(reportBytes);
|
||||||
|
submitReport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public short this[DualShock4Axis axis]
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
axis.SetScaled(reportBytes, value);
|
||||||
|
submitReport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public short this[DualShock4Slider slider]
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
slider.Set(reportBytes, value);
|
||||||
|
submitReport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public short this[DualShock4Sensor sensor]
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
sensor.Set(reportBytes, value);
|
||||||
|
submitReport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point? this[DualShock4Finger finger]
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
finger.Set(reportBytes, value);
|
||||||
|
submitReport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Overwrite(DualShock4Button button, bool value, int minPressedTime = 0)
|
||||||
|
{
|
||||||
|
button.Set(reportBytes, value);
|
||||||
|
submitReport = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetFeedback()
|
||||||
|
{
|
||||||
|
FeedbackReceived = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DS4_FeedbackReceived(object sender, DualShock4FeedbackReceivedEventArgs e)
|
||||||
|
{
|
||||||
|
FeedbackLargeMotor = e.LargeMotor;
|
||||||
|
FeedbackSmallMotor = e.SmallMotor;
|
||||||
|
LightbarColor = e.LightbarColor;
|
||||||
|
FeedbackReceived = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
212
SteamController/Devices/DS4ControllerActions.cs
Normal file
212
SteamController/Devices/DS4ControllerActions.cs
Normal file
|
|
@ -0,0 +1,212 @@
|
||||||
|
using Nefarius.ViGEm.Client;
|
||||||
|
using Nefarius.ViGEm.Client.Exceptions;
|
||||||
|
using Nefarius.ViGEm.Client.Targets;
|
||||||
|
using Nefarius.ViGEm.Client.Targets.DualShock4;
|
||||||
|
using static CommonHelpers.Log;
|
||||||
|
|
||||||
|
namespace SteamController.Devices
|
||||||
|
{
|
||||||
|
public partial class DS4Controller
|
||||||
|
{
|
||||||
|
public struct DualShock4Axis
|
||||||
|
{
|
||||||
|
public int Offset { get; }
|
||||||
|
public bool Invert { get; }
|
||||||
|
|
||||||
|
public DualShock4Axis(int offset, bool invert)
|
||||||
|
{
|
||||||
|
Offset = offset;
|
||||||
|
Invert = invert;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Set(byte[] report, byte value)
|
||||||
|
{
|
||||||
|
report[Offset] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetScaled(byte[] report, short value)
|
||||||
|
{
|
||||||
|
var valuef = value / 256;
|
||||||
|
if (Invert)
|
||||||
|
valuef = -valuef;
|
||||||
|
Set(report, (byte)(valuef + sbyte.MinValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DualShock4Button
|
||||||
|
{
|
||||||
|
public int Offset { get; }
|
||||||
|
public int Bit { get; }
|
||||||
|
public byte Mask { get => (byte)(1 << Bit); }
|
||||||
|
|
||||||
|
public DualShock4Button(int offset, int bit)
|
||||||
|
{
|
||||||
|
Offset = offset;
|
||||||
|
Bit = bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Set(byte[] report, bool value)
|
||||||
|
{
|
||||||
|
report[Offset] = (byte)((report[Offset] & ~Mask) | (value ? Mask : 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DualShock4DPadDirection
|
||||||
|
{
|
||||||
|
public int Offset { get; }
|
||||||
|
public int Value { get; }
|
||||||
|
public int Mask { get; }
|
||||||
|
|
||||||
|
public DualShock4DPadDirection(int offset, int value, int mask)
|
||||||
|
{
|
||||||
|
Offset = offset;
|
||||||
|
Value = value;
|
||||||
|
Mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Set(byte[] report)
|
||||||
|
{
|
||||||
|
report[Offset] = (byte)((report[Offset] & ~Mask) | Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DualShock4Slider
|
||||||
|
{
|
||||||
|
public int Offset { get; }
|
||||||
|
|
||||||
|
public DualShock4Slider(int offset)
|
||||||
|
{
|
||||||
|
Offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Set(byte[] report, byte value)
|
||||||
|
{
|
||||||
|
report[Offset] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Set(byte[] report, short value)
|
||||||
|
{
|
||||||
|
int result = Math.Clamp(value, (short)0, short.MaxValue) * byte.MaxValue / short.MaxValue;
|
||||||
|
Set(report, (byte)result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DualShock4Sensor
|
||||||
|
{
|
||||||
|
public int Offset { get; }
|
||||||
|
public bool Invert { get; }
|
||||||
|
|
||||||
|
public DualShock4Sensor(int offset, bool invert)
|
||||||
|
{
|
||||||
|
Offset = offset;
|
||||||
|
Invert = invert;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Set(byte[] report, short value)
|
||||||
|
{
|
||||||
|
if (Invert)
|
||||||
|
value = (short)Math.Clamp(-value, short.MinValue, short.MaxValue);
|
||||||
|
|
||||||
|
BitConverter.GetBytes(value).CopyTo(report, Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Set(byte[] report, ushort value)
|
||||||
|
{
|
||||||
|
BitConverter.GetBytes(value).CopyTo(report, Offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DualShock4Finger
|
||||||
|
{
|
||||||
|
public const int MaxX = 1920;
|
||||||
|
public const int MaxY = 942;
|
||||||
|
|
||||||
|
public int Index { get; }
|
||||||
|
private int Offset { get => 34 + Index * 4; }
|
||||||
|
|
||||||
|
public DualShock4Finger(int index)
|
||||||
|
{
|
||||||
|
Index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Set(byte[] report, Point? data)
|
||||||
|
{
|
||||||
|
uint currentValue = BitConverter.ToUInt32(report, Offset);
|
||||||
|
|
||||||
|
// copy report ID
|
||||||
|
uint calculatedValue = (byte)(((currentValue & 0x7F) + 1) & 0x7F);
|
||||||
|
|
||||||
|
if (data.HasValue)
|
||||||
|
{
|
||||||
|
// store coordinates into report
|
||||||
|
int x = Math.Clamp(data.Value.X, 0, MaxX);
|
||||||
|
int y = Math.Clamp(data.Value.Y, 0, MaxY);
|
||||||
|
calculatedValue |= (uint)((x & 0x7FF) << 8);
|
||||||
|
calculatedValue |= (uint)((y & 0x7FF) << 20);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// copy existing coordinates
|
||||||
|
calculatedValue |= 0x80;
|
||||||
|
calculatedValue |= (uint)(currentValue & 0xFFFFFF00);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare position and key status
|
||||||
|
if ((currentValue & 0xFFFFFF80) == (calculatedValue & 0xFFFFFF80))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// increment packet number
|
||||||
|
report[33] = (byte)(report[33] + 1);
|
||||||
|
BitConverter.GetBytes(calculatedValue).CopyTo(report, Offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly static DualShock4Axis LeftThumbX = new DualShock4Axis(0, false);
|
||||||
|
public readonly static DualShock4Axis LeftThumbY = new DualShock4Axis(1, true);
|
||||||
|
public readonly static DualShock4Axis RightThumbX = new DualShock4Axis(2, false);
|
||||||
|
public readonly static DualShock4Axis RightThumbY = new DualShock4Axis(3, true);
|
||||||
|
|
||||||
|
public static DualShock4Slider LeftTrigger = new DualShock4Slider(7);
|
||||||
|
public static DualShock4Slider RightTrigger = new DualShock4Slider(8);
|
||||||
|
|
||||||
|
public static DualShock4Button ThumbRight = new DualShock4Button(5, 7);
|
||||||
|
public static DualShock4Button ThumbLeft = new DualShock4Button(5, 6);
|
||||||
|
public static DualShock4Button Options = new DualShock4Button(5, 5);
|
||||||
|
public static DualShock4Button Share = new DualShock4Button(5, 4);
|
||||||
|
public static DualShock4Button TriggerRight = new DualShock4Button(5, 3);
|
||||||
|
public static DualShock4Button TriggerLeft = new DualShock4Button(5, 2);
|
||||||
|
public static DualShock4Button ShoulderRight = new DualShock4Button(5, 1);
|
||||||
|
public static DualShock4Button ShoulderLeft = new DualShock4Button(5, 0);
|
||||||
|
public static DualShock4Button Triangle = new DualShock4Button(4, 7);
|
||||||
|
public static DualShock4Button Circle = new DualShock4Button(4, 6);
|
||||||
|
public static DualShock4Button Cross = new DualShock4Button(4, 5);
|
||||||
|
public static DualShock4Button Square = new DualShock4Button(4, 4);
|
||||||
|
|
||||||
|
public static DualShock4Button TPadClick = new DualShock4Button(6, 1);
|
||||||
|
public static DualShock4Button PS = new DualShock4Button(6, 0);
|
||||||
|
|
||||||
|
private static DualShock4Sensor Timestamp = new DualShock4Sensor(9, false);
|
||||||
|
private static DualShock4Slider BatteryLevel = new DualShock4Slider(11);
|
||||||
|
private static DualShock4Slider Counter = new DualShock4Slider(6);
|
||||||
|
|
||||||
|
public static DualShock4Sensor GyroX = new DualShock4Sensor(12, false);
|
||||||
|
public static DualShock4Sensor GyroY = new DualShock4Sensor(14, true);
|
||||||
|
public static DualShock4Sensor GyroZ = new DualShock4Sensor(16, false);
|
||||||
|
public static DualShock4Sensor AccelX = new DualShock4Sensor(18, false);
|
||||||
|
public static DualShock4Sensor AccelY = new DualShock4Sensor(20, true);
|
||||||
|
public static DualShock4Sensor AccelZ = new DualShock4Sensor(22, false);
|
||||||
|
|
||||||
|
public static DualShock4DPadDirection DPadReleased = new DualShock4DPadDirection(4, 8, 15);
|
||||||
|
public static DualShock4DPadDirection DPadNorthwest = new DualShock4DPadDirection(4, 7, 15);
|
||||||
|
public static DualShock4DPadDirection DPadWest = new DualShock4DPadDirection(4, 6, 15);
|
||||||
|
public static DualShock4DPadDirection DPadSouthwest = new DualShock4DPadDirection(4, 5, 15);
|
||||||
|
public static DualShock4DPadDirection DPadSouth = new DualShock4DPadDirection(4, 4, 15);
|
||||||
|
public static DualShock4DPadDirection DPadSoutheast = new DualShock4DPadDirection(4, 3, 15);
|
||||||
|
public static DualShock4DPadDirection DPadEast = new DualShock4DPadDirection(4, 2, 15);
|
||||||
|
public static DualShock4DPadDirection DPadNortheast = new DualShock4DPadDirection(4, 1, 15);
|
||||||
|
public static DualShock4DPadDirection DPadNorth = new DualShock4DPadDirection(4, 0, 15);
|
||||||
|
|
||||||
|
public static DualShock4Finger LeftFinger = new DualShock4Finger(0);
|
||||||
|
public static DualShock4Finger RightFinger = new DualShock4Finger(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,6 +30,7 @@ namespace SteamController.Managers
|
||||||
{
|
{
|
||||||
context.State.SteamUsesSteamInput = false;
|
context.State.SteamUsesSteamInput = false;
|
||||||
context.State.SteamUsesX360Controller = false;
|
context.State.SteamUsesX360Controller = false;
|
||||||
|
context.State.SteamUsesDS4Controller = false;
|
||||||
lastState = null;
|
lastState = null;
|
||||||
stateChanged = 0;
|
stateChanged = 0;
|
||||||
return;
|
return;
|
||||||
|
|
@ -58,11 +59,17 @@ namespace SteamController.Managers
|
||||||
Devices.Xbox360Controller.VendorID,
|
Devices.Xbox360Controller.VendorID,
|
||||||
Devices.Xbox360Controller.ProductID
|
Devices.Xbox360Controller.ProductID
|
||||||
) != true;
|
) != true;
|
||||||
|
|
||||||
|
context.State.SteamUsesDS4Controller = Helpers.SteamConfiguration.IsControllerBlacklisted(
|
||||||
|
Devices.DS4Controller.VendorID,
|
||||||
|
Devices.DS4Controller.ProductID
|
||||||
|
) != true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.State.SteamUsesSteamInput = false;
|
context.State.SteamUsesSteamInput = false;
|
||||||
context.State.SteamUsesX360Controller = false;
|
context.State.SteamUsesX360Controller = false;
|
||||||
|
context.State.SteamUsesDS4Controller = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastState = usesController;
|
lastState = usesController;
|
||||||
|
|
@ -70,11 +77,12 @@ namespace SteamController.Managers
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
CommonHelpers.Log.TraceLine(
|
CommonHelpers.Log.TraceLine(
|
||||||
"SteamManager: uses={0}, isRunning={1}, usesSteamInput={2}, usesX360={3}",
|
"SteamManager: uses={0}, isRunning={1}, usesSteamInput={2}, usesX360={3}, usesDS4={4}",
|
||||||
usesController,
|
usesController,
|
||||||
SteamConfiguration.IsRunning,
|
SteamConfiguration.IsRunning,
|
||||||
context.State.SteamUsesSteamInput,
|
context.State.SteamUsesSteamInput,
|
||||||
context.State.SteamUsesX360Controller
|
context.State.SteamUsesX360Controller,
|
||||||
|
context.State.SteamUsesDS4Controller
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
SteamController/Profiles/Predefined/DS4HapticProfile.cs
Normal file
29
SteamController/Profiles/Predefined/DS4HapticProfile.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
using SteamController.ProfilesSettings;
|
||||||
|
using HapticPad = SteamController.Devices.SteamController.HapticPad;
|
||||||
|
|
||||||
|
namespace SteamController.Profiles.Predefined
|
||||||
|
{
|
||||||
|
public class DS4HapticProfile : DS4Profile
|
||||||
|
{
|
||||||
|
private ProfilesSettings.HapticSettings HapticSettings
|
||||||
|
{
|
||||||
|
get { return ProfilesSettings.HapticSettings.DS4; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Status Run(Context context)
|
||||||
|
{
|
||||||
|
if (base.Run(context).IsDone)
|
||||||
|
return Status.Done;
|
||||||
|
|
||||||
|
if (HapticSettings.GetHapticIntensity(context.DS4.FeedbackLargeMotor, HapticSettings.LeftIntensity, out var leftIntensity))
|
||||||
|
context.Steam.SendHaptic(HapticPad.Right, HapticSettings.HapticStyle, leftIntensity);
|
||||||
|
|
||||||
|
if (HapticSettings.GetHapticIntensity(context.DS4.FeedbackSmallMotor, HapticSettings.RightIntensity, out var rightIntensity))
|
||||||
|
context.Steam.SendHaptic(HapticPad.Left, HapticSettings.HapticStyle, rightIntensity);
|
||||||
|
|
||||||
|
context.DS4.ResetFeedback();
|
||||||
|
|
||||||
|
return Status.Continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
106
SteamController/Profiles/Predefined/DS4Profile.cs
Normal file
106
SteamController/Profiles/Predefined/DS4Profile.cs
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
using Nefarius.ViGEm.Client.Targets.Xbox360;
|
||||||
|
using SteamController.Devices;
|
||||||
|
using SteamController.ProfilesSettings;
|
||||||
|
|
||||||
|
namespace SteamController.Profiles.Predefined
|
||||||
|
{
|
||||||
|
public class DS4Profile : Default.BackPanelShortcutsProfile
|
||||||
|
{
|
||||||
|
public override bool Selected(Context context)
|
||||||
|
{
|
||||||
|
return context.Enabled && context.DS4.Valid && context.KeyboardMouseValid && !context.State.SteamUsesSteamInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override ProfilesSettings.BackPanelSettings BackPanelSettings
|
||||||
|
{
|
||||||
|
get { return ProfilesSettings.DS4BackPanelSettings.Default; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Status Run(Context context)
|
||||||
|
{
|
||||||
|
context.Steam.LizardButtons = false;
|
||||||
|
context.Steam.LizardMouse = false;
|
||||||
|
context.DS4.Connected = true;
|
||||||
|
|
||||||
|
// Controls
|
||||||
|
context.DS4.Overwrite(DS4Controller.PS, context.Steam.BtnSteam.Pressed(), 100);
|
||||||
|
context.DS4[DS4Controller.Share] = context.Steam.BtnMenu;
|
||||||
|
context.DS4[DS4Controller.Options] = context.Steam.BtnOptions;
|
||||||
|
|
||||||
|
if (base.Run(context).IsDone)
|
||||||
|
{
|
||||||
|
return Status.Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DPad
|
||||||
|
if (context.Steam.BtnDpadUp && context.Steam.BtnDpadLeft)
|
||||||
|
context.DS4[DS4Controller.DPadNorthwest] = true;
|
||||||
|
else if (context.Steam.BtnDpadUp && context.Steam.BtnDpadRight)
|
||||||
|
context.DS4[DS4Controller.DPadNortheast] = true;
|
||||||
|
else if (context.Steam.BtnDpadDown && context.Steam.BtnDpadLeft)
|
||||||
|
context.DS4[DS4Controller.DPadSouthwest] = true;
|
||||||
|
else if (context.Steam.BtnDpadDown && context.Steam.BtnDpadRight)
|
||||||
|
context.DS4[DS4Controller.DPadSoutheast] = true;
|
||||||
|
else if (context.Steam.BtnDpadUp)
|
||||||
|
context.DS4[DS4Controller.DPadNorth] = true;
|
||||||
|
else if (context.Steam.BtnDpadDown)
|
||||||
|
context.DS4[DS4Controller.DPadSouth] = true;
|
||||||
|
else if (context.Steam.BtnDpadLeft)
|
||||||
|
context.DS4[DS4Controller.DPadWest] = true;
|
||||||
|
else if (context.Steam.BtnDpadRight)
|
||||||
|
context.DS4[DS4Controller.DPadEast] = true;
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
context.DS4[DS4Controller.Cross] = context.Steam.BtnA;
|
||||||
|
context.DS4[DS4Controller.Circle] = context.Steam.BtnB;
|
||||||
|
context.DS4[DS4Controller.Square] = context.Steam.BtnX;
|
||||||
|
context.DS4[DS4Controller.Triangle] = context.Steam.BtnY;
|
||||||
|
|
||||||
|
// Sticks
|
||||||
|
context.DS4[DS4Controller.LeftThumbX] = context.Steam.LeftThumbX;
|
||||||
|
context.DS4[DS4Controller.LeftThumbY] = context.Steam.LeftThumbY;
|
||||||
|
context.DS4[DS4Controller.RightThumbX] = context.Steam.RightThumbX;
|
||||||
|
context.DS4[DS4Controller.RightThumbY] = context.Steam.RightThumbY;
|
||||||
|
context.DS4[DS4Controller.ThumbLeft] = context.Steam.BtnLeftStickPress;
|
||||||
|
context.DS4[DS4Controller.ThumbRight] = context.Steam.BtnRightStickPress;
|
||||||
|
|
||||||
|
// Triggers
|
||||||
|
context.DS4[DS4Controller.LeftTrigger] = context.Steam.LeftTrigger;
|
||||||
|
context.DS4[DS4Controller.RightTrigger] = context.Steam.RightTrigger;
|
||||||
|
context.DS4[DS4Controller.TriggerLeft] = context.Steam.LeftTrigger > short.MaxValue * 3 / 4;
|
||||||
|
context.DS4[DS4Controller.TriggerRight] = context.Steam.RightTrigger > short.MaxValue * 3 / 4;
|
||||||
|
context.DS4[DS4Controller.ShoulderLeft] = context.Steam.BtnL1;
|
||||||
|
context.DS4[DS4Controller.ShoulderRight] = context.Steam.BtnR1;
|
||||||
|
|
||||||
|
// Accel & Gyro
|
||||||
|
context.DS4[DS4Controller.GyroX] = context.Steam.GyroPitch;
|
||||||
|
context.DS4[DS4Controller.GyroY] = context.Steam.GyroRoll;
|
||||||
|
context.DS4[DS4Controller.GyroZ] = context.Steam.GyroYaw;
|
||||||
|
context.DS4[DS4Controller.AccelX] = context.Steam.AccelX;
|
||||||
|
context.DS4[DS4Controller.AccelY] = context.Steam.AccelY;
|
||||||
|
context.DS4[DS4Controller.AccelZ] = context.Steam.AccelZ;
|
||||||
|
|
||||||
|
// Trackpad
|
||||||
|
context.DS4[DS4Controller.TPadClick] = context.Steam.BtnLPadPress || context.Steam.BtnRPadPress;
|
||||||
|
context.DS4[DS4Controller.LeftFinger] = GetTPadPoint(context.Steam.LPadX, context.Steam.LPadY);
|
||||||
|
context.DS4[DS4Controller.RightFinger] = GetTPadPoint(context.Steam.RPadX, context.Steam.RPadY);
|
||||||
|
|
||||||
|
return Status.Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point? GetTPadPoint(SteamAxis x, SteamAxis y)
|
||||||
|
{
|
||||||
|
if (x || y)
|
||||||
|
{
|
||||||
|
return new Point(
|
||||||
|
(int)x.GetDeltaValue(0, 1920, DeltaValueMode.Absolute),
|
||||||
|
(int)y.GetDeltaValue(943 + 488, -488, DeltaValueMode.Absolute)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,9 +5,9 @@ namespace SteamController.Profiles.Predefined
|
||||||
{
|
{
|
||||||
public class X360HapticProfile : X360Profile
|
public class X360HapticProfile : X360Profile
|
||||||
{
|
{
|
||||||
private ProfilesSettings.X360HapticSettings HapticSettings
|
private ProfilesSettings.HapticSettings HapticSettings
|
||||||
{
|
{
|
||||||
get { return ProfilesSettings.X360HapticSettings.Default; }
|
get { return ProfilesSettings.HapticSettings.X360; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Status Run(Context context)
|
public override Status Run(Context context)
|
||||||
|
|
@ -15,26 +15,15 @@ namespace SteamController.Profiles.Predefined
|
||||||
if (base.Run(context).IsDone)
|
if (base.Run(context).IsDone)
|
||||||
return Status.Done;
|
return Status.Done;
|
||||||
|
|
||||||
if (GetHapticIntensity(context.X360.FeedbackLargeMotor, HapticSettings.LeftIntensity, out var leftIntensity))
|
if (HapticSettings.GetHapticIntensity(context.X360.FeedbackLargeMotor, HapticSettings.LeftIntensity, out var leftIntensity))
|
||||||
context.Steam.SendHaptic(HapticPad.Right, HapticSettings.HapticStyle, leftIntensity);
|
context.Steam.SendHaptic(HapticPad.Right, HapticSettings.HapticStyle, leftIntensity);
|
||||||
|
|
||||||
if (GetHapticIntensity(context.X360.FeedbackSmallMotor, HapticSettings.RightIntensity, out var rightIntensity))
|
if (HapticSettings.GetHapticIntensity(context.X360.FeedbackSmallMotor, HapticSettings.RightIntensity, out var rightIntensity))
|
||||||
context.Steam.SendHaptic(HapticPad.Left, HapticSettings.HapticStyle, rightIntensity);
|
context.Steam.SendHaptic(HapticPad.Left, HapticSettings.HapticStyle, rightIntensity);
|
||||||
|
|
||||||
context.X360.ResetFeedback();
|
context.X360.ResetFeedback();
|
||||||
|
|
||||||
return Status.Continue;
|
return Status.Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool GetHapticIntensity(byte? input, sbyte maxIntensity, out sbyte output)
|
|
||||||
{
|
|
||||||
output = default;
|
|
||||||
if (input is null || input.Value == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int value = X360HapticSettings.MinIntensity + (maxIntensity - X360HapticSettings.MinIntensity) * input.Value / 255;
|
|
||||||
output = (sbyte)value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
SteamController/ProfilesSettings/DS4BackPanelSettings.cs
Normal file
16
SteamController/ProfilesSettings/DS4BackPanelSettings.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Configuration;
|
||||||
|
|
||||||
|
namespace SteamController.ProfilesSettings
|
||||||
|
{
|
||||||
|
internal class DS4BackPanelSettings : BackPanelSettings
|
||||||
|
{
|
||||||
|
private const String MappingsDescription = @"Shortcuts are to be changed in future release.";
|
||||||
|
|
||||||
|
public static DS4BackPanelSettings Default { get; } = new DS4BackPanelSettings();
|
||||||
|
|
||||||
|
public DS4BackPanelSettings() : base("DS4BackPanelSettings")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,17 +4,29 @@ using System.Configuration;
|
||||||
namespace SteamController.ProfilesSettings
|
namespace SteamController.ProfilesSettings
|
||||||
{
|
{
|
||||||
[Category("Settings")]
|
[Category("Settings")]
|
||||||
internal sealed class X360HapticSettings : CommonHelpers.BaseSettings
|
internal sealed class HapticSettings : CommonHelpers.BaseSettings
|
||||||
{
|
{
|
||||||
public const sbyte MinIntensity = -2;
|
public const sbyte MinIntensity = -2;
|
||||||
public const sbyte MaxIntensity = 10;
|
public const sbyte MaxIntensity = 10;
|
||||||
|
|
||||||
public static X360HapticSettings Default = new X360HapticSettings();
|
public static HapticSettings X360 = new HapticSettings("X360HapticSettings");
|
||||||
|
public static HapticSettings DS4 = new HapticSettings("DS4HapticSettings");
|
||||||
|
|
||||||
public X360HapticSettings() : base("X360HapticSettings")
|
public HapticSettings(string name) : base(name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool GetHapticIntensity(byte? input, sbyte maxIntensity, out sbyte output)
|
||||||
|
{
|
||||||
|
output = default;
|
||||||
|
if (input is null || input.Value == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int value = MinIntensity + (maxIntensity - MinIntensity) * input.Value / 255;
|
||||||
|
output = (sbyte)value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public Devices.SteamController.HapticStyle HapticStyle
|
public Devices.SteamController.HapticStyle HapticStyle
|
||||||
{
|
{
|
||||||
get { return Get<Devices.SteamController.HapticStyle>("HapticStyle", Devices.SteamController.HapticStyle.Weak); }
|
get { return Get<Devices.SteamController.HapticStyle>("HapticStyle", Devices.SteamController.HapticStyle.Weak); }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue