LenovoLegionToolkit
92 строки · 3.5 Кб
1using System;
2using System.Threading.Tasks;
3using LenovoLegionToolkit.Lib.Extensions;
4using LenovoLegionToolkit.Lib.System;
5
6namespace LenovoLegionToolkit.Lib.Features;
7
8public class BatteryFeature : AbstractDriverFeature<BatteryState>
9{
10private const string BATTERY_CHARGE_MODE_HIVE = "HKEY_CURRENT_USER";
11private const string BATTERY_CHARGE_MODE_PATH = "Software\\Lenovo\\VantageService\\AddinData\\IdeaNotebookAddin";
12private const string BATTERY_CHARGE_MODE_KEY = "BatteryChargeMode";
13private const string BATTERY_CHARGE_MODE_NORMAL = "Normal";
14private const string BATTERY_CHARGE_MODE_RAPID_CHARGE = "Quick";
15private const string BATTERY_CHARGE_MODE_CONSERVATION = "Storage";
16
17public BatteryFeature() : base(Drivers.GetEnergy, Drivers.IOCTL_ENERGY_BATTERY_CHARGE_MODE) { }
18
19protected override uint GetInBufferValue() => 0xFF;
20
21protected override Task<uint[]> ToInternalAsync(BatteryState state)
22{
23var result = state switch
24{
25BatteryState.Conservation => LastState == BatteryState.RapidCharge ? new uint[] { 0x8, 0x3 } : new uint[] { 0x3 },
26BatteryState.Normal => LastState == BatteryState.Conservation ? new uint[] { 0x5 } : new uint[] { 0x8 },
27BatteryState.RapidCharge => LastState == BatteryState.Conservation ? new uint[] { 0x5, 0x7 } : new uint[] { 0x7 },
28_ => throw new InvalidOperationException("Invalid state.")
29};
30return Task.FromResult(result);
31}
32
33protected override Task<BatteryState> FromInternalAsync(uint state)
34{
35state = state.ReverseEndianness();
36
37if (state.GetNthBit(17)) // Is charging?
38return Task.FromResult(state.GetNthBit(26) ? BatteryState.RapidCharge : BatteryState.Normal);
39
40if (state.GetNthBit(29))
41return Task.FromResult(BatteryState.Conservation);
42
43throw new InvalidOperationException($"Unknown battery state: {state} [bits={Convert.ToString(state, 2)}]");
44}
45
46public override async Task SetStateAsync(BatteryState state)
47{
48await base.SetStateAsync(state).ConfigureAwait(false);
49SetStateInRegistry(state);
50}
51
52public async Task EnsureCorrectBatteryModeIsSetAsync()
53{
54var state = GetStateFromRegistry();
55
56if (!state.HasValue)
57return;
58
59if (await GetStateAsync().ConfigureAwait(false) == state.Value)
60return;
61
62await SetStateAsync(state.Value).ConfigureAwait(false);
63}
64
65private static BatteryState? GetStateFromRegistry()
66{
67var batteryModeString = Registry.GetValue(BATTERY_CHARGE_MODE_HIVE, BATTERY_CHARGE_MODE_PATH, BATTERY_CHARGE_MODE_KEY, string.Empty);
68return batteryModeString switch
69{
70BATTERY_CHARGE_MODE_NORMAL => BatteryState.Normal,
71BATTERY_CHARGE_MODE_RAPID_CHARGE => BatteryState.RapidCharge,
72BATTERY_CHARGE_MODE_CONSERVATION => BatteryState.Conservation,
73_ => null
74};
75}
76
77private static void SetStateInRegistry(BatteryState state)
78{
79var batteryModeString = state switch
80{
81BatteryState.Normal => BATTERY_CHARGE_MODE_NORMAL,
82BatteryState.RapidCharge => BATTERY_CHARGE_MODE_RAPID_CHARGE,
83BatteryState.Conservation => BATTERY_CHARGE_MODE_CONSERVATION,
84_ => null
85};
86
87if (batteryModeString is null)
88return;
89
90Registry.SetValue(BATTERY_CHARGE_MODE_HIVE, BATTERY_CHARGE_MODE_PATH, BATTERY_CHARGE_MODE_KEY, batteryModeString);
91}
92}
93