LenovoLegionToolkit

Форк
0
108 строк · 3.4 Кб
1
using System;
2
using System.Runtime.InteropServices;
3
using System.Threading.Tasks;
4
using LenovoLegionToolkit.Lib.Extensions;
5
using LenovoLegionToolkit.Lib.Utils;
6
using Microsoft.Win32.SafeHandles;
7

8
namespace LenovoLegionToolkit.Lib.Features;
9

10
public abstract class AbstractDriverFeature<T> : IFeature<T> where T : struct, Enum, IComparable
11
{
12
    protected readonly uint ControlCode;
13
    protected readonly Func<SafeFileHandle> DriverHandle;
14

15
    protected T LastState;
16

17
    protected AbstractDriverFeature(Func<SafeFileHandle> driverHandleHandle, uint controlCode)
18
    {
19
        DriverHandle = driverHandleHandle;
20
        ControlCode = controlCode;
21
    }
22

23
    public virtual async Task<bool> IsSupportedAsync()
24
    {
25
        try
26
        {
27
            _ = await GetStateAsync().ConfigureAwait(false);
28
            return true;
29
        }
30
        catch
31
        {
32
            return false;
33
        }
34
    }
35

36
    public Task<T[]> GetAllStatesAsync() => Task.FromResult(Enum.GetValues<T>());
37

38
    public virtual async Task<T> GetStateAsync()
39
    {
40
        if (Log.Instance.IsTraceEnabled)
41
            Log.Instance.Trace($"Getting state... [feature={GetType().Name}]");
42

43
        var outBuffer = await SendCodeAsync(DriverHandle(), ControlCode, GetInBufferValue()).ConfigureAwait(false);
44

45
        if (Log.Instance.IsTraceEnabled)
46
            Log.Instance.Trace($"Buffer value: {outBuffer} [feature={GetType().Name}]");
47

48
        var state = await FromInternalAsync(outBuffer).ConfigureAwait(false);
49
        LastState = state;
50

51
        if (Log.Instance.IsTraceEnabled)
52
            Log.Instance.Trace($"State is {state} [feature={GetType().Name}]");
53

54
        return state;
55
    }
56

57
    public virtual async Task SetStateAsync(T state)
58
    {
59
        if (Log.Instance.IsTraceEnabled)
60
            Log.Instance.Trace($"Setting state to {state}... [feature={GetType().Name}]");
61

62
        var codes = await ToInternalAsync(state).ConfigureAwait(false);
63
        foreach (var code in codes)
64
            await SendCodeAsync(DriverHandle(), ControlCode, code).ConfigureAwait(false);
65
        LastState = state;
66

67
        await VerifyStateSetAsync(state).ConfigureAwait(false);
68

69
        if (Log.Instance.IsTraceEnabled)
70
            Log.Instance.Trace($"State set to {state} [feature={GetType().Name}]");
71
    }
72

73
    protected abstract Task<T> FromInternalAsync(uint state);
74

75
    protected abstract uint GetInBufferValue();
76

77
    protected abstract Task<uint[]> ToInternalAsync(T state);
78

79
    protected Task<uint> SendCodeAsync(SafeFileHandle handle, uint controlCode, uint inBuffer) => Task.Run(() =>
80
    {
81
        if (PInvokeExtensions.DeviceIoControl(handle, controlCode, inBuffer, out uint outBuffer))
82
            return outBuffer;
83

84
        var error = Marshal.GetLastWin32Error();
85

86
        if (Log.Instance.IsTraceEnabled)
87
            Log.Instance.Trace($"DeviceIoControl returned 0, last error: {error} [feature={GetType().Name}]");
88

89
        throw new InvalidOperationException($"DeviceIoControl returned 0, last error: {error}");
90
    });
91

92
    private async Task VerifyStateSetAsync(T state)
93
    {
94
        var retries = 0;
95
        while (retries < 10)
96
        {
97
            if (state.Equals(await GetStateAsync().ConfigureAwait(false)))
98
                break;
99

100
            retries++;
101

102
            await Task.Delay(50).ConfigureAwait(false);
103
        }
104

105
        if (Log.Instance.IsTraceEnabled)
106
            Log.Instance.Trace($"Verify state {state} set failed. [feature={GetType().Name}]");
107
    }
108
}
109

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.