-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEcAccess.cs
More file actions
194 lines (157 loc) · 5.43 KB
/
EcAccess.cs
File metadata and controls
194 lines (157 loc) · 5.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
using System;
using System.Runtime.InteropServices;
using System.Threading;
public static class EcAccess
{
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint OPEN_EXISTING = 3;
private const uint OLS_TYPE = 40000;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_READ_ACCESS = 0x0001;
private const uint FILE_WRITE_ACCESS = 0x0002;
private const byte EC_SC = 0x66;
private const byte EC_DATA = 0x62;
private static IntPtr handle = IntPtr.Zero;
// 计算 IOCTL 控制码
private static uint CTL_CODE(uint deviceType, uint function, uint method, uint access)
{
return (deviceType << 16) | (access << 14) | (function << 2) | method;
}
// 计算出的IOCTL读写端口代码,与调用的硬编码数字保持一致
private const uint IOCTL_READ_PORT = 2621464780; // = CTL_CODE(40000, 0x09, 0, 0x0001)
private const uint IOCTL_WRITE_PORT = 2621481176; // = CTL_CODE(40000, 0x0A, 0, 0x0002)
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct WriteIoPortInput
{
public uint PortNumber;
public byte Value;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct ReadIoPortInput
{
public uint PortNumber;
}
public static void Init()
{
handle = CreateFileW(
@"\\.\WinRing0_1_2_0",
GENERIC_READ | GENERIC_WRITE,
0,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero
);
if (handle.ToInt64() == -1)
{
throw new Exception("打开 WinRing0 设备失败:" + Marshal.GetLastWin32Error());
}
Console.WriteLine("驱动设备打开成功");
}
public static void WriteEC(byte address, byte data,int wait)
{
Console.WriteLine("[1] 等待 EC 空闲");
WaitIbfClear();
Thread.Sleep(wait);
Console.WriteLine("[2] 写入命令 0x81 到 EC_SC");
WritePort(EC_SC, 0x81);
Thread.Sleep(wait);
Console.WriteLine("[3] 等待 EC 空闲");
WaitIbfClear();
Thread.Sleep(wait);
Console.WriteLine($"[4] 写入地址 0x{address:X2} 到 EC_DATA");
WritePort(EC_DATA, address);
Thread.Sleep(wait);
Console.WriteLine("[5] 等待 EC 空闲");
WaitIbfClear();
Thread.Sleep(wait);
Console.WriteLine($"[6] 写入数据 0x{data:X2} 到 EC_DATA");
WritePort(EC_DATA, data);
Thread.Sleep(wait);
Console.WriteLine("[7] 等待 EC 空闲");
WaitIbfClear();
Thread.Sleep(wait);
Console.WriteLine($"[完成] 成功写入 EC 寄存器 0x{address:X2} = 0x{data:X2}");
}
private static void WaitIbfClear()
{
for (int i = 0; i < 100; i++)
{
byte status = ReadPort(EC_SC);
if ((status & 0x02) == 0) // IBF = 0
return;
Thread.Sleep(5);
}
throw new TimeoutException("等待 IBF 清零超时");
}
private static byte ReadPort(byte port)
{
ReadIoPortInput input = new ReadIoPortInput { PortNumber = port };
byte[] outBuffer = new byte[1];
uint bytesReturned = 0;
bool success = DeviceIoControl(
handle,
IOCTL_READ_PORT, // 这里用常量,不改调用代码里的硬编码数字
GetBytes(input), (uint)Marshal.SizeOf(input),
outBuffer, (uint)outBuffer.Length,
ref bytesReturned,
IntPtr.Zero
);
if (!success)
throw new Exception("DeviceIoControl 读取端口失败:" + Marshal.GetLastWin32Error());
return outBuffer[0];
}
private static void WritePort(byte port, byte value)
{
WriteIoPortInput input = new WriteIoPortInput { PortNumber = port, Value = value };
uint bytesReturned = 0;
bool success = DeviceIoControl(
handle,
IOCTL_WRITE_PORT, // 这里用常量,不改调用代码里的硬编码数字
GetBytes(input), (uint)Marshal.SizeOf(input),
null, 0,
ref bytesReturned,
IntPtr.Zero
);
if (!success)
throw new Exception("DeviceIoControl 写入端口失败:" + Marshal.GetLastWin32Error());
}
private static byte[] GetBytes<T>(T str) where T : struct
{
int size = Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
try
{
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return arr;
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr CreateFileW(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
byte[] lpInBuffer,
uint nInBufferSize,
[Out] byte[] lpOutBuffer,
uint nOutBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped
);
}