Skip to content

Commit

Permalink
Prevent crash when waking PC up from sleep (#1806)
Browse files Browse the repository at this point in the history
  • Loading branch information
Koseng authored Aug 7, 2024
1 parent 313bc69 commit 6d91e67
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 25 deletions.
20 changes: 17 additions & 3 deletions MobiFlight/Joysticks/JoystickManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ private JoystickDefinition GetDefinitionByInstanceName(String instanceName)
return Definitions.Find(definition => definition.InstanceName == instanceName);
}

/// <summary>
/// Finds a JoystickDefinition by the device's vendor and product id.
/// </summary>
/// <param name="vendorId">The vendor id of the device.</param>
/// <param name="productId">The product id of the device.</param>
/// <returns>The first definition matching the product id, or null if none found.</returns>
private JoystickDefinition GetDefinitionByProductId(int vendorId, int productId)
{
return Definitions.Find(def => (def.ProductId == productId && def.VendorId == vendorId));
}

/// <summary>
/// Loads all joystick definitions from disk.
/// </summary>
Expand Down Expand Up @@ -158,16 +169,19 @@ public async void Connect()

Joystick js;
var diJoystick = new SharpDX.DirectInput.Joystick(di, d.InstanceGuid);
var productId = diJoystick.Properties.ProductId;
var vendorId = diJoystick.Properties.VendorId;
if (d.InstanceName == "Octavi" || d.InstanceName == "IFR1")
{
// statically set this to Octavi until we might support (Octavi|IFR1) or similar
js = new Octavi(diJoystick, GetDefinitionByInstanceName("Octavi"));
}
else if (diJoystick.Properties.VendorId == 0x4098 && diJoystick.Properties.ProductId == 0xBB10)
else if (vendorId == 0x4098 && productId == 0xBB10)
{
js = new WinwingFcu(diJoystick, GetDefinitionByInstanceName("WINWING FCU"));
var joystickDef = GetDefinitionByProductId(vendorId, productId);
js = new WinwingFcu(diJoystick, joystickDef, productId);
}
else if (diJoystick.Properties.VendorId == 0x231D)
else if (vendorId == 0x231D)
{
// VKB devices are highly configurable. DirectInput names can have old values cached in the registry, but HID names seem to be immune to that.
// Also trim the extraneous whitespaces on VKB device names.
Expand Down
53 changes: 32 additions & 21 deletions MobiFlight/Joysticks/WinwingFcu/WinwingFcu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ internal class HidBuffer

internal class WinwingFcu : Joystick
{
readonly uint VendorId = 0x4098;
readonly uint ProductId = 0xBB10;
private readonly int VendorId = 0x4098;
private int ProductId = 0xBB10;
IHidDevice Device { get; set; }

private const int SPD_DEC = 10;
Expand All @@ -40,15 +40,17 @@ internal class WinwingFcu : Joystick
private WinwingFcuReport CurrentReport = new WinwingFcuReport();
private WinwingFcuReport PreviousReport = new WinwingFcuReport();
private HidBuffer HidDataBuffer = new HidBuffer();
private WinwingDisplayControl DisplayControl = new WinwingDisplayControl();
private WinwingDisplayControl DisplayControl;

private List<IBaseDevice> LcdDevices = new List<IBaseDevice>();
private List<ListItem<IBaseDevice>> LedDevices = new List<ListItem<IBaseDevice>>();
public WinwingFcu(SharpDX.DirectInput.Joystick joystick, JoystickDefinition definition) : base(joystick, definition)


public WinwingFcu(SharpDX.DirectInput.Joystick joystick, JoystickDefinition def, int productId) : base(joystick, def)
{
Definition = definition;
Definition = def;
ProductId = productId;
DisplayControl = new WinwingDisplayControl(productId);
var displayNames = DisplayControl.GetDisplayNames();
var ledNames = DisplayControl.GetLedNames();

Expand Down Expand Up @@ -79,7 +81,7 @@ public async override void Connect(IntPtr handle)
base.Connect(handle);
DisplayControl.Connect();

var hidFactory = new FilterDeviceDefinition(vendorId: VendorId, productId: ProductId).CreateWindowsHidDeviceFactory();
var hidFactory = new FilterDeviceDefinition(vendorId: (uint)VendorId, productId: (uint)ProductId).CreateWindowsHidDeviceFactory();
var deviceDefinitions = (await hidFactory.GetConnectedDeviceDefinitionsAsync().ConfigureAwait(false)).ToList();
Device = (IHidDevice)await hidFactory.GetDeviceAsync(deviceDefinitions.First()).ConfigureAwait(false);
await Device.InitializeAsync().ConfigureAwait(false);
Expand Down Expand Up @@ -126,21 +128,20 @@ protected override void EnumerateDevices()
}
}

private bool IsBitSet(uint intToCheck, int buttonId)
{
int pos = buttonId - 1;
return (intToCheck & (1 << pos)) != 0;
}

private void CheckForButtonTrigger(uint changes, MobiFlightButton.InputEvent inputEvent)
private void CheckForButtonTrigger(uint changes, MobiFlightButton.InputEvent inputEvent, int offset)
{
if (changes > 0)
{
foreach (var button in ButtonsToTrigger)
for (int i = 0; i < 32; i++)
{
if (IsBitSet(intToCheck: changes, buttonId: button.Key))
if ((changes & (1 << i)) != 0) // IsBitSet
{
TriggerButtonPress(button.Value, inputEvent);
// Button IDs start with 1
bool hasValue = ButtonsToTrigger.TryGetValue((i + offset + 1), out var button);
if (hasValue)
{
TriggerButtonPress(button, inputEvent);
}
}
}
}
Expand Down Expand Up @@ -188,14 +189,24 @@ private void InputReportReceived(HidBuffer hidBuffer)
{
CurrentReport.CopyTo(PreviousReport);
PreviousReport.ButtonState = ~PreviousReport.ButtonState; // to retrigger
PreviousReport.ButtonState2 = ~PreviousReport.ButtonState2; // to retrigger
PreviousReport.ButtonState3 = ~PreviousReport.ButtonState3; // to retrigger
DoInitialize = false;
}

// Detect and Trigger Button Events
uint pressed = CurrentReport.ButtonState & ~PreviousReport.ButtonState; // rising edges
uint released = PreviousReport.ButtonState & ~CurrentReport.ButtonState; // falling edges
CheckForButtonTrigger(pressed, MobiFlightButton.InputEvent.PRESS);
CheckForButtonTrigger(released, MobiFlightButton.InputEvent.RELEASE);
uint pressed2 = CurrentReport.ButtonState2 & ~PreviousReport.ButtonState2; // rising edges
uint released2 = PreviousReport.ButtonState2 & ~CurrentReport.ButtonState2; // falling edges
uint pressed3 = CurrentReport.ButtonState3 & ~PreviousReport.ButtonState3; // rising edges
uint released3 = PreviousReport.ButtonState3 & ~CurrentReport.ButtonState3; // falling edges
CheckForButtonTrigger(pressed, MobiFlightButton.InputEvent.PRESS, 0);
CheckForButtonTrigger(released, MobiFlightButton.InputEvent.RELEASE, 0);
CheckForButtonTrigger(pressed2, MobiFlightButton.InputEvent.PRESS, 32);
CheckForButtonTrigger(released2, MobiFlightButton.InputEvent.RELEASE, 32);
CheckForButtonTrigger(pressed3, MobiFlightButton.InputEvent.PRESS, 64);
CheckForButtonTrigger(released3, MobiFlightButton.InputEvent.RELEASE, 64);

// Detect and Trigger Encoder Turns
int spdIncrement = CurrentReport.SpdEncoderValue - PreviousReport.SpdEncoderValue;
Expand Down
12 changes: 11 additions & 1 deletion MobiFlight/Joysticks/WinwingFcu/WinwingFcuReport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ internal class WinwingFcuReport
{
public uint ReportId { get; set; }
public uint ButtonState { get; set; }
public uint ButtonState2 { get; set; }
public uint ButtonState3 { get; set; }
public ushort SpdEncoderValue { get; set; }
public ushort HdgEncoderValue { get; set; }
public ushort AltEncoderValue { get; set; }
Expand All @@ -19,6 +21,8 @@ public void CopyTo(WinwingFcuReport targetReport)
{
targetReport.ReportId = this.ReportId;
targetReport.ButtonState = this.ButtonState;
targetReport.ButtonState2 = this.ButtonState2;
targetReport.ButtonState3 = this.ButtonState3;
targetReport.SpdEncoderValue = this.SpdEncoderValue;
targetReport.AltEncoderValue = this.AltEncoderValue;
targetReport.HdgEncoderValue = this.HdgEncoderValue;
Expand All @@ -33,6 +37,8 @@ public void ParseReport(HidBuffer hidBuffer)
{
// get 32 bit Button report field - First 4 bytes: uint: [3][2][1][0]
ButtonState = ((uint)data[0] + ((uint)data[1] << 8) + ((uint)data[2] << 16) + ((uint)data[3] << 24));
ButtonState2 = ((uint)data[4] + ((uint)data[5] << 8) + ((uint)data[6] << 16) + ((uint)data[7] << 24));
ButtonState3 = ((uint)data[8] + ((uint)data[9] << 8) + ((uint)data[10] << 16) + ((uint)data[11] << 24));

if (IsFirmwareGreaterOrEqual_1_16) // Since firmware v1.16
{
Expand All @@ -54,13 +60,17 @@ public void ParseReport(HidBuffer hidBuffer)
// Is firmware report
if (data[5] == 0x02 && data[4] == 0x05 && data[0] == 0x10)
{
Log.Instance.log($"WINWING FCU Firmware: v{data[9].ToString("X2")}.{data[8].ToString("X2")}", LogSeverity.Debug);
LogFirmware(data, "WINWING FCU");
if (data[9] == 1 && data[8] < 0x16)
{
IsFirmwareGreaterOrEqual_1_16 = false;
}
}
}
}
private void LogFirmware(byte[] data, string device)
{
Log.Instance.log($"{device} Firmware: v{data[9].ToString("X2")}.{data[8].ToString("X2")}", LogSeverity.Debug);
}
}
}
Binary file modified lib/MobiFlightWwFcu.dll
Binary file not shown.

0 comments on commit 6d91e67

Please sign in to comment.