|
1 | | -using System.ComponentModel; |
| 1 | +using System; |
2 | 2 | using System.Runtime.InteropServices; |
3 | | -using System.Text; |
| 3 | +using System.ComponentModel; |
4 | 4 | using static FirmwareKit.Comm.Fastboot.Usb.Windows.Win32API; |
5 | 5 |
|
6 | | -namespace FirmwareKit.Comm.Fastboot.Usb.Windows; |
7 | | - |
8 | | -public class LegacyUsbDevice : UsbDevice |
| 6 | +namespace FirmwareKit.Comm.Fastboot.Usb.Windows |
9 | 7 | { |
10 | | - public static readonly uint IoGetSerialCode = ((FILE_DEVICE_UNKNOWN) << 16) | ((FILE_READ_ACCESS) << 14) | ((16) << 2) | (METHOD_BUFFERED); |
11 | | - public IntPtr DeviceHandle { get; private set; } |
| 8 | + public class LegacyUsbDevice : UsbDevice |
| 9 | + { |
| 10 | + public static uint IoGetSerialCode => CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS); |
| 11 | + public static uint IoGetDescriptorCode => CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS); |
12 | 12 |
|
13 | | - public IntPtr ReadBulkHandle { get; private set; } |
| 13 | + private IntPtr fileHandle = INVALID_HANDLE_VALUE; |
14 | 14 |
|
15 | | - public IntPtr WriteBulkHandle { get; private set; } |
| 15 | + public IntPtr Handle => fileHandle; |
16 | 16 |
|
17 | | - public override int CreateHandle() |
18 | | - { |
19 | | - DeviceHandle = SimpleCreateHandle(DevicePath); |
20 | | - ReadBulkHandle = SimpleCreateHandle(DevicePath + "\\BulkRead"); |
21 | | - WriteBulkHandle = SimpleCreateHandle(DevicePath + "\\BulkWrite"); |
22 | | - if (DeviceHandle == new IntPtr(-1) || |
23 | | - ReadBulkHandle == new IntPtr(-1) || |
24 | | - WriteBulkHandle == new IntPtr(-1)) |
25 | | - return Marshal.GetLastWin32Error(); |
26 | | - GetSerialNumber(); |
27 | | - return 0; |
28 | | - } |
| 17 | + public override int CreateHandle() |
| 18 | + { |
| 19 | + fileHandle = SimpleCreateHandle(DevicePath); |
| 20 | + if (fileHandle == INVALID_HANDLE_VALUE) |
| 21 | + return Marshal.GetLastWin32Error(); |
29 | 22 |
|
30 | | - public override void Reset() |
31 | | - { |
32 | | - // Not supported in legacy driver |
33 | | - } |
| 23 | + // 仿照谷歌原生逻辑,检查是否匹配 Fastboot 接口标准 (0xff, 0x42, 0x03) |
| 24 | + // 在 Legacy 驱动中,我们尝试探测其是否响应特定的 IOCTL |
| 25 | + if (!CheckInterface()) |
| 26 | + { |
| 27 | + CloseHandle(fileHandle); |
| 28 | + fileHandle = INVALID_HANDLE_VALUE; |
| 29 | + return -1; |
| 30 | + } |
34 | 31 |
|
35 | | - public override int GetSerialNumber() |
36 | | - { |
37 | | - byte[] serial = new byte[512]; |
38 | | - int bytes_get; |
39 | | - if (DeviceIoControl(DeviceHandle, IoGetSerialCode, Array.Empty<byte>(), 0, serial, 512, out bytes_get, IntPtr.Zero)) |
40 | | - { |
41 | | - // The legacy driver returns the serial number as a null-terminated UTF-16 string |
42 | | - SerialNumber = Encoding.Unicode.GetString(serial, 0, bytes_get).TrimEnd('\0'); |
| 32 | + GetSerialNumber(); |
43 | 33 | return 0; |
44 | 34 | } |
45 | | - return Marshal.GetLastWin32Error(); |
46 | | - } |
47 | 35 |
|
48 | | - public override byte[] Read(int length) |
49 | | - { |
50 | | - uint bytesRead; |
51 | | - byte[] data = new byte[length]; |
52 | | - if (ReadBulkHandle == IntPtr.Zero) |
53 | | - throw new Exception("Read handle is closed."); |
54 | | - |
55 | | - if (ReadFile(ReadBulkHandle, data, (uint)length, out bytesRead, IntPtr.Zero)) |
| 36 | + private bool CheckInterface() |
56 | 37 | { |
57 | | - byte[] res = new byte[bytesRead]; |
58 | | - Array.Copy(data, res, bytesRead); |
59 | | - return res; |
| 38 | + byte[] buffer = new byte[256]; |
| 39 | + int returned; |
| 40 | + // 能够响应 IoGetSerialCode,初步认为是兼容的 Legacy 驱动 |
| 41 | + return DeviceIoControl(fileHandle, IoGetSerialCode, null, 0, buffer, buffer.Length, out returned, IntPtr.Zero); |
60 | 42 | } |
61 | | - throw new Win32Exception(Marshal.GetLastWin32Error()); |
62 | | - } |
63 | 43 |
|
64 | | - public override long Write(byte[] data, int length) |
65 | | - { |
66 | | - ulong bytesWrite = 0; |
67 | | - if (WriteBulkHandle == IntPtr.Zero) |
68 | | - throw new Exception("Write handle is closed."); |
| 44 | + public override int GetSerialNumber() |
| 45 | + { |
| 46 | + byte[] buffer = new byte[256]; |
| 47 | + int returned; |
| 48 | + if (DeviceIoControl(fileHandle, IoGetSerialCode, null, 0, buffer, buffer.Length, out returned, IntPtr.Zero)) |
| 49 | + { |
| 50 | + SerialNumber = System.Text.Encoding.Unicode.GetString(buffer, 0, returned).TrimEnd('\0'); |
| 51 | + return 0; |
| 52 | + } |
| 53 | + return Marshal.GetLastWin32Error(); |
| 54 | + } |
69 | 55 |
|
70 | | - if (WriteFile(WriteBulkHandle, data, (uint)length, out bytesWrite, IntPtr.Zero)) |
| 56 | + public override byte[] Read(int length) |
71 | 57 | { |
72 | | - return (long)bytesWrite; |
| 58 | + byte[] buffer = new byte[length]; |
| 59 | + uint read; |
| 60 | + if (ReadFile(fileHandle, buffer, (uint)length, out read, IntPtr.Zero)) |
| 61 | + { |
| 62 | + byte[] result = new byte[read]; |
| 63 | + Array.Copy(buffer, result, (int)read); |
| 64 | + return result; |
| 65 | + } |
| 66 | + throw new Win32Exception(Marshal.GetLastWin32Error()); |
73 | 67 | } |
74 | | - throw new Win32Exception(Marshal.GetLastWin32Error()); |
75 | | - } |
76 | 68 |
|
77 | | - public override void Dispose() |
78 | | - { |
79 | | - if (DeviceHandle != IntPtr.Zero && DeviceHandle != new IntPtr(-1)) |
| 69 | + public override long Write(byte[] data, int length) |
80 | 70 | { |
81 | | - CloseHandle(DeviceHandle); |
82 | | - DeviceHandle = IntPtr.Zero; |
| 71 | + uint written; |
| 72 | + if (WriteFile(fileHandle, data, (uint)length, out written, IntPtr.Zero)) |
| 73 | + { |
| 74 | + return written; |
| 75 | + } |
| 76 | + throw new Win32Exception(Marshal.GetLastWin32Error()); |
83 | 77 | } |
84 | | - if (ReadBulkHandle != IntPtr.Zero && ReadBulkHandle != new IntPtr(-1)) |
| 78 | + |
| 79 | + public override void Reset() |
85 | 80 | { |
86 | | - CloseHandle(ReadBulkHandle); |
87 | | - ReadBulkHandle = IntPtr.Zero; |
| 81 | + // Legacy 驱动通常不支持软重置 |
88 | 82 | } |
89 | | - if (WriteBulkHandle != IntPtr.Zero && WriteBulkHandle != new IntPtr(-1)) |
| 83 | + |
| 84 | + public override void Dispose() |
90 | 85 | { |
91 | | - CloseHandle(WriteBulkHandle); |
92 | | - WriteBulkHandle = IntPtr.Zero; |
| 86 | + if (fileHandle != INVALID_HANDLE_VALUE) |
| 87 | + { |
| 88 | + CloseHandle(fileHandle); |
| 89 | + fileHandle = INVALID_HANDLE_VALUE; |
| 90 | + } |
| 91 | + GC.SuppressFinalize(this); |
93 | 92 | } |
94 | 93 | } |
95 | | - |
96 | | - |
97 | 94 | } |
0 commit comments