Extend performance overlay to include FT and others

This commit is contained in:
Kamil Trzciński 2022-11-13 14:39:29 +01:00
parent 059d64827f
commit 01f0d6b366
21 changed files with 198 additions and 63 deletions

View file

@ -16,6 +16,10 @@
<PackageReference Include="TaskScheduler" Version="2.10.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CommonHelpers\CommonHelpers.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>

View file

@ -1,4 +1,4 @@
using FanControl.FromLibreHardwareMonitor;
using CommonHelpers.FromLibreHardwareMonitor;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@ -17,7 +17,10 @@ namespace FanControl
public partial class FanControlForm : Form
{
private FanController fanControl = new FanController();
private StartupManager startupManager = new StartupManager();
private StartupManager startupManager = new StartupManager(
"Steam Deck Fan Control",
"Starts Steam Deck Fan Control on Windows startup."
);
public FanControlForm()
{

View file

@ -8,6 +8,7 @@ using System.Diagnostics.Metrics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommonHelpers;
namespace FanControl
{

View file

@ -29,7 +29,7 @@ namespace FanControl
FanMode.Max, new FanSensor.Profile()
{
Type = FanSensor.Profile.ProfileType.Constant,
MinRPM = Vlv0100.MAX_FAN_RPM
MinRPM = CommonHelpers.Vlv0100.MAX_FAN_RPM
}
},
{

View file

@ -1,185 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Copyright (C) LibreHardwareMonitor and Contributors.
// Partial Copyright (C) Michael Möller <mmoeller@openhardwaremonitor.org> and Contributors.
// All Rights Reserved.
using System;
using System.IO;
using System.Linq;
using System.Security;
using System.Security.Principal;
using System.Windows.Forms;
using Microsoft.Win32;
using Microsoft.Win32.TaskScheduler;
using Action = Microsoft.Win32.TaskScheduler.Action;
using Task = Microsoft.Win32.TaskScheduler.Task;
namespace FanControl.FromLibreHardwareMonitor
{
public class StartupManager
{
private const string RegistryPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
private bool _startup;
public const string Description = "Starts Steam Deck Fan Control on Windows startup.";
public const string NameOf = "Steam Deck Fan Control";
public StartupManager()
{
if (Environment.OSVersion.Platform >= PlatformID.Unix)
{
IsAvailable = false;
return;
}
if (IsAdministrator() && TaskService.Instance.Connected)
{
IsAvailable = true;
Task task = GetTask();
if (task != null)
{
foreach (Action action in task.Definition.Actions)
{
if (action.ActionType == TaskActionType.Execute && action is ExecAction execAction)
{
if (execAction.Path.Equals(Application.ExecutablePath, StringComparison.OrdinalIgnoreCase))
_startup = true;
}
}
}
}
else
{
try
{
using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(RegistryPath))
{
string value = (string)registryKey?.GetValue(NameOf);
if (value != null)
_startup = value == Application.ExecutablePath;
}
IsAvailable = true;
}
catch (SecurityException)
{
IsAvailable = false;
}
}
}
public bool IsAvailable { get; }
public bool Startup
{
get { return _startup; }
set
{
if (_startup != value)
{
if (IsAvailable)
{
if (TaskService.Instance.Connected)
{
if (value)
CreateTask();
else
DeleteTask();
_startup = value;
}
else
{
try
{
if (value)
CreateRegistryKey();
else
DeleteRegistryKey();
_startup = value;
}
catch (UnauthorizedAccessException)
{
throw new InvalidOperationException();
}
}
}
else
{
throw new InvalidOperationException();
}
}
}
}
private static bool IsAdministrator()
{
try
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch
{
return false;
}
}
private static Task GetTask()
{
try
{
return TaskService.Instance.AllTasks.FirstOrDefault(x => x.Name.Equals(NameOf, StringComparison.OrdinalIgnoreCase));
}
catch
{
return null;
}
}
private void CreateTask()
{
TaskDefinition taskDefinition = TaskService.Instance.NewTask();
taskDefinition.RegistrationInfo.Description = Description;
taskDefinition.Triggers.Add(new LogonTrigger());
taskDefinition.Settings.StartWhenAvailable = true;
taskDefinition.Settings.DisallowStartIfOnBatteries = false;
taskDefinition.Settings.StopIfGoingOnBatteries = false;
taskDefinition.Settings.ExecutionTimeLimit = TimeSpan.Zero;
taskDefinition.Settings.AllowHardTerminate = false;
taskDefinition.Principal.RunLevel = TaskRunLevel.Highest;
taskDefinition.Principal.LogonType = TaskLogonType.InteractiveToken;
taskDefinition.Actions.Add(new ExecAction(Application.ExecutablePath, "", Path.GetDirectoryName(Application.ExecutablePath)));
TaskService.Instance.RootFolder.RegisterTaskDefinition(NameOf, taskDefinition);
}
private static void DeleteTask()
{
Task task = GetTask();
task?.Folder.DeleteTask(task.Name, false);
}
private static void CreateRegistryKey()
{
RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(RegistryPath);
registryKey?.SetValue(NameOf, Application.ExecutablePath);
}
private static void DeleteRegistryKey()
{
RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(RegistryPath);
registryKey?.DeleteValue(NameOf);
}
}
}

View file

@ -1,55 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace FanControl
{
internal class InpOut
{
[DllImport("inpoutx64.dll", EntryPoint = "MapPhysToLin", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr MapPhysToLin(IntPtr pbPhysAddr, uint dwPhysSize, out IntPtr pPhysicalMemoryHandle);
[DllImport("inpoutx64.dll", EntryPoint = "UnmapPhysicalMemory", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnmapPhysicalMemory(IntPtr PhysicalMemoryHandle, IntPtr pbLinAddr);
[DllImport("inpoutx64.dll", EntryPoint = "DlPortReadPortUchar", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern byte DlPortReadPortUchar(ushort port);
[DllImport("inpoutx64.dll", EntryPoint = "DlPortWritePortUchar", CallingConvention = CallingConvention.StdCall)]
public static extern byte DlPortWritePortUchar(ushort port, byte vlaue);
public static byte[] ReadMemory(IntPtr baseAddress, uint size)
{
IntPtr pdwLinAddr = MapPhysToLin(baseAddress, size, out IntPtr pPhysicalMemoryHandle);
if (pdwLinAddr != IntPtr.Zero)
{
byte[] bytes = new byte[size];
Marshal.Copy(pdwLinAddr, bytes, 0, bytes.Length);
UnmapPhysicalMemory(pPhysicalMemoryHandle, pdwLinAddr);
return bytes;
}
return null;
}
public static bool WriteMemory(IntPtr baseAddress, byte[] data)
{
IntPtr pdwLinAddr = MapPhysToLin(baseAddress, (uint)data.Length, out IntPtr pPhysicalMemoryHandle);
if (pdwLinAddr != IntPtr.Zero)
{
Marshal.Copy(data, 0, pdwLinAddr, data.Length);
UnmapPhysicalMemory(pPhysicalMemoryHandle, pdwLinAddr);
return true;
}
return false;
}
}
}

View file

@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LibreHardwareMonitor.Hardware;
using CommonHelpers;
namespace FanControl
{

View file

@ -1,122 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
namespace FanControl
{
internal class Vlv0100
{
// Those addresses are taken from DSDT for VLV0100
// and might change at any time with a BIOS update
// Purpose: https://lore.kernel.org/lkml/20220206022023.376142-1-andrew.smirnov@gmail.com/
// Addresses: DSDT.txt
static IntPtr FSLO_FSHI = new IntPtr(0xFE700B00 + 0x92);
static IntPtr GNLO_GNHI = new IntPtr(0xFE700B00 + 0x95);
static IntPtr FRPR = new IntPtr(0xFE700B00 + 0x97);
static IntPtr FNRL_FNRH = new IntPtr(0xFE700300 + 0xB0);
static IntPtr FNCK = new IntPtr(0xFE700300 + 0x9F);
static IntPtr BATH_BATL = new IntPtr(0xFE700400 + 0x6E);
static IntPtr PDFV = new IntPtr(0xFE700C00 + 0x4C);
static IntPtr XBID = new IntPtr(0xFE700300 + 0xBD);
static IntPtr PDCT = new IntPtr(0xFE700C00 + 0x01);
static ushort IO6C = 0x6C;
public const ushort MAX_FAN_RPM = 0x1C84;
public static readonly ushort[] SupportedFirmwares = {
0xB030 // 45104
};
public static readonly byte[] SupportedBoardID = {
6
};
public static readonly byte[] SupportedPDCS = {
0x2B // 43
};
public static bool IsSupported()
{
var firmwareVersion = GetFirmwareVersion();
var boardID = GetBoardID();
var pdcs = GetPDCS();
return SupportedFirmwares.Contains(firmwareVersion) &&
SupportedBoardID.Contains(boardID);
}
public static ushort GetFirmwareVersion()
{
byte[] data = InpOut.ReadMemory(PDFV, 2);
return BitConverter.ToUInt16(data);
}
public static byte GetBoardID()
{
byte[] data = InpOut.ReadMemory(XBID, 1);
return data[0];
}
public static byte GetPDCS()
{
byte[] data = InpOut.ReadMemory(PDCT, 1);
return data[0];
}
public static ushort GetFanDesiredRPM()
{
byte[] data = InpOut.ReadMemory(FSLO_FSHI, 2);
return BitConverter.ToUInt16(data);
}
public static ushort GetFanRPM()
{
byte[] data = InpOut.ReadMemory(FNRL_FNRH, 2);
return BitConverter.ToUInt16(data);
}
public static void SetFanControl(Boolean userControlled)
{
SetGain(10);
SetRampRate(userControlled ? (byte)10 : (byte)20);
InpOut.DlPortWritePortUchar(IO6C, userControlled ? (byte)0xCC : (byte)0xCD);
}
public static void SetFanDesiredRPM(ushort rpm)
{
if (rpm > MAX_FAN_RPM)
rpm = MAX_FAN_RPM;
byte[] data = BitConverter.GetBytes(rpm);
InpOut.WriteMemory(FSLO_FSHI, data);
}
public static bool GetFanCheck()
{
byte[] data = InpOut.ReadMemory(FNCK, 1);
return (data[0] & 0x1) != 0;
}
public static float GetBattTemperature()
{
byte[] data = InpOut.ReadMemory(BATH_BATL, 2);
int value = (data[0] << 8) + data[1];
return (float)(value - 0x0AAC) / 10.0f;
}
private static void SetGain(ushort gain)
{
byte[] data = BitConverter.GetBytes(gain);
InpOut.WriteMemory(GNLO_GNHI, data);
}
private static void SetRampRate(byte rampRate)
{
byte[] data = BitConverter.GetBytes(rampRate);
InpOut.WriteMemory(FRPR, data);
}
}
}

Binary file not shown.