steam-deck-tools/SteamController/Devices/SteamController.cs
Kamil Trzciński e5debff45b SteamController: Use Roslyn Scripting to compile UserProfiles
- This looks into `UserProfiles/` and compiles user profiles
- This exposes a very minimal scripting interface as defined by `Dynamic.Globals`
2023-01-03 11:34:40 +01:00

134 lines
3.6 KiB
C#

using System.Diagnostics;
using static CommonHelpers.Log;
namespace SteamController.Devices
{
public partial class SteamController : IDisposable
{
public const ushort VendorID = 0x28DE;
public const ushort ProductID = 0x1205;
private const int ReadTimeout = 50;
public const int MaxFailures = 10;
private hidapi.HidDevice neptuneDevice;
private Stopwatch stopwatch = new Stopwatch();
private TimeSpan? lastUpdate;
private int failures;
public long ElapsedMilliseconds { get => stopwatch.ElapsedMilliseconds; }
public double DeltaTime { get; private set; }
internal SteamController()
{
InitializeButtons();
InitializeActions();
OpenDevice();
stopwatch.Start();
}
~SteamController()
{
Dispose();
}
public void Dispose()
{
GC.SuppressFinalize(this);
using (neptuneDevice) { }
}
public bool Updated { get; private set; }
private void OpenDevice()
{
using (neptuneDevice) { }
neptuneDevice = new hidapi.HidDevice(VendorID, ProductID, 64);
neptuneDevice.OpenDevice();
}
internal void Fail(bool immediately = false)
{
foreach (var action in AllActions)
action.Reset();
// Try to re-open every MaxFailures
failures++;
if (failures % MaxFailures == 0 || immediately)
{
OpenDevice();
failures = 0;
}
}
private void BeforeUpdate(byte[] buffer)
{
foreach (var action in AllActions)
action.BeforeUpdate(buffer);
}
internal void BeforeUpdate()
{
var ts = stopwatch.Elapsed;
DeltaTime = lastUpdate is not null ? (ts - lastUpdate.Value).TotalSeconds : 0.0;
DeltaTime = Math.Min(DeltaTime, 0.1); // max update is 100ms
lastUpdate = ts;
LizardButtons = true;
LizardMouse = true;
try
{
byte[] data = neptuneDevice.Read(ReadTimeout);
if (data == null)
{
Fail();
Updated = false;
return;
}
BeforeUpdate(data);
Updated = true;
}
catch (hidapi.HidDeviceInvalidException)
{
// Steam might disconnect device
Fail();
Updated = false;
}
catch (Exception e)
{
TraceException("STEAM", "BeforeUpdate", e);
Fail();
Updated = false;
}
}
internal void Update()
{
foreach (var action in AllActions)
action.Update();
try
{
UpdateLizardButtons();
UpdateLizardMouse();
}
catch (hidapi.HidDeviceInvalidException)
{
// Steam might disconnect device
Fail();
}
catch (Exception e)
{
// Steam have disconnected device, which triggered exception
if (e.Message == "Could not send report to hid device. Error: -1")
DebugException("STEAM", "Update", e);
else
TraceException("STEAM", "Update", e);
Fail();
}
}
}
}