Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/hakchi2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/FelLib
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-01-12 11:50:43 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-01-12 11:50:43 +0300
commitb805961692c60da23ee412eb6ae4ae6052d45b55 (patch)
tree07970e216ee448ee7107ae83a96a51ec321883e0 /FelLib
parentb91d8b1cb2e3468b0235f8c9f63d635b0ebc23a1 (diff)
Fixed detection bug and unhandled exception bug
Diffstat (limited to 'FelLib')
-rw-r--r--FelLib/Fel.cs735
-rw-r--r--FelLib/WinUSBNet/API/DeviceManagement.cs627
2 files changed, 700 insertions, 662 deletions
diff --git a/FelLib/Fel.cs b/FelLib/Fel.cs
index d6f51059..63fbee54 100644
--- a/FelLib/Fel.cs
+++ b/FelLib/Fel.cs
@@ -1,351 +1,384 @@
-using MadWizard.WinUSBNet;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading;
-
-namespace com.clusterrr.FelLib
-{
- public class Fel
- {
- public byte[] Fes1Bin;
- public byte[] UBootBin;
-
- public enum CurrentAction { RunningCommand, ReadingMemory, WritingMemory }
- public delegate void OnFelProgress(CurrentAction action, string command);
-
- USBDevice device = null;
- byte inEndp = 0;
- byte outEndp = 0;
- const int ReadTimeout = 1000;
- const int WriteTimeout = 1000;
- public const int MaxBulkSize = 0x10000;
- UInt16 vid, pid;
- bool DramInitDone = false;
-
- const UInt32 cmdOffset = 0x604FF;
- const UInt32 fes1_base_m = 0x2000;
- const UInt32 dram_base = 0x40000000;
- const UInt32 flash_mem_base = 0x43800000;
- const UInt32 flash_mem_size = 0x20;
- const UInt32 uboot_base_m = 0x47000000u;
- const UInt32 sector_size = 0x20000;
- const UInt32 uboot_base_f = 0x100000;
- const UInt32 kernel_base_f = (sector_size * 0x30);
- const UInt32 kernel_base_m = flash_mem_base;
- const UInt32 kernel_max_size = (uboot_base_m - flash_mem_base);
- const UInt32 kernel_max_flash_size = (sector_size * 0x20);
- const string fastboot = "fastboot_test";
-
- public static bool DeviceExists(UInt16 vid, UInt16 pid)
- {
- var fel = new Fel();
- try
- {
- fel.Open(vid, pid);
- return true;
- }
- catch
- {
- return false;
- }
- finally
- {
- fel.Close();
- }
- }
-
- public void Open(UInt16 vid, UInt16 pid)
- {
- this.vid = vid;
- this.pid = pid;
- Close();
- device = USBDevice.GetSingleDevice(vid, pid);
- if (device == null) throw new FelException("Device not found");
- foreach (var pipe in device.Pipes)
- {
- if (pipe.IsIn)
- inEndp = pipe.Address;
- else
- outEndp = pipe.Address;
- }
- device.Pipes[inEndp].Policy.PipeTransferTimeout = ReadTimeout;
- device.Pipes[outEndp].Policy.PipeTransferTimeout = WriteTimeout;
- //ClearInputBuffer();
- if (VerifyDevice().Board != 0x00166700) throw new FelException("Invalid board ID");
- }
- public void Close()
- {
- if (device != null)
- {
- try
- {
- device.Pipes[inEndp].Abort();
- }
- catch { }
- try
- {
- device.Pipes[outEndp].Abort();
- }
- catch
- {
- }
- device.Dispose();
- device = null;
- }
- }
-
- public void ClearInputBuffer()
- {
- var dummyBuff = new byte[64];
- device.Pipes[inEndp].Policy.PipeTransferTimeout = 50;
- try
- {
- while (true) device.Pipes[inEndp].Read(dummyBuff);
- }
- catch { }
- device.Pipes[inEndp].Policy.PipeTransferTimeout = ReadTimeout;
- }
-
- private void WriteToUSB(byte[] buffer)
- {
- device.Pipes[outEndp].Write(buffer);
- }
-
- private int ReadFromUSB(byte[] buffer, int offset, int length)
- {
- return device.Pipes[inEndp].Read(buffer, offset, length);
- }
- private byte[] ReadFromUSB(UInt32 length)
- {
- var result = new byte[length];
- int pos = 0;
- while (pos < length)
- {
- pos += ReadFromUSB(result, pos, (int)(length - pos));
- }
- return result;
- }
-
- private void FelWrite(byte[] buffer)
- {
- var req = new AWUSBRequest();
- req.Cmd = AWUSBRequest.RequestType.AW_USB_WRITE;
- req.Len = (uint)buffer.Length;
- WriteToUSB(req.Data);
- WriteToUSB(buffer);
- var resp = new AWUSBResponse(ReadFromUSB(13));
- if (resp.CswStatus != 0) throw new FelException("FEL write error");
- }
-
- private byte[] FelRead(UInt32 length)
- {
- var req = new AWUSBRequest();
- req.Cmd = AWUSBRequest.RequestType.AW_USB_READ;
- req.Len = length;
- WriteToUSB(req.Data);
-
- var result = ReadFromUSB(length);
- var resp = new AWUSBResponse(ReadFromUSB(13));
- if (resp.CswStatus != 0) throw new FelException("FEL read error");
- return result;
- }
-
- private void FelRequest(AWFELStandardRequest.RequestType command)
- {
- var req = new AWFELStandardRequest();
- req.Cmd = command;
- FelWrite(req.Data);
- }
-
- private void FelRequest(AWFELStandardRequest.RequestType command, UInt32 address, UInt32 length)
- {
- var req = new AWFELMessage();
- req.Cmd = command;
- req.Address = address;
- req.Len = length;
- FelWrite(req.Data);
- }
-
- public AWFELVerifyDeviceResponse VerifyDevice()
- {
- FelRequest(AWFELStandardRequest.RequestType.FEL_VERIFY_DEVICE);
- byte[] resp;
- try
- {
- resp = FelRead(32);
- }
- catch
- {
- resp = new byte[32];
- }
- var status = new AWFELStatusResponse(FelRead(8));
- return new AWFELVerifyDeviceResponse(resp);
- }
-
- public void WriteMemory(UInt32 address, byte[] buffer, OnFelProgress callback = null)
- {
- if (address >= dram_base)
- InitDram();
-
- UInt32 length = (UInt32)buffer.Length;
- if (length != (length & ~((UInt32)3)))
- {
- length = (length + 3) & ~((UInt32)3);
- var newBuffer = new byte[length];
- Array.Copy(buffer, 0, newBuffer, 0, buffer.Length);
- buffer = newBuffer;
- }
-
- int pos = 0;
- while (pos < buffer.Length)
- {
- if (callback != null) callback(CurrentAction.WritingMemory, null);
- var buf = new byte[Math.Min(buffer.Length - pos, MaxBulkSize)];
- Array.Copy(buffer, pos, buf, 0, buf.Length);
- FelRequest(AWFELStandardRequest.RequestType.FEL_DOWNLOAD, (UInt32)(address + pos), (uint)buf.Length);
- FelWrite(buf);
- var status = new AWFELStatusResponse(FelRead(8));
- if (status.State != 0) throw new FelException("FEL write error");
- pos += buf.Length;
- }
- }
-
- private byte[] ReadMemory(UInt32 address, UInt32 length, OnFelProgress callback = null)
- {
- if (address >= dram_base)
- InitDram();
-
- length = (length + 3) & ~((UInt32)3);
-
- var result = new List<byte>();
- while (length > 0)
- {
- if (callback != null) callback(CurrentAction.ReadingMemory, null);
- var l = Math.Min(length, MaxBulkSize);
- FelRequest(AWFELStandardRequest.RequestType.FEL_UPLOAD, address, l);
- var r = FelRead((UInt32)l);
- result.AddRange(r);
- var status = new AWFELStatusResponse(FelRead(8));
- if (status.State != 0) throw new FelException("FEL read error");
- length -= l;
- address += l;
- }
- return result.ToArray();
- }
-
- public bool InitDram(bool force = false)
- {
- if (DramInitDone && !force) return true;
- if (DramInitDone) return true;
- const UInt32 testSize = 0x80;
- if (Fes1Bin == null || Fes1Bin.Length < testSize)
- throw new FelException("Can't init DRAM, incorrect Fes1 binary");
- var buf = ReadMemory((UInt32)(fes1_base_m + Fes1Bin.Length - testSize), testSize);
- var buf2 = new byte[testSize];
- Array.Copy(Fes1Bin, Fes1Bin.Length - buf.Length, buf2, 0, testSize);
- if (buf.SequenceEqual(buf2))
- {
- return DramInitDone = true;
- }
- WriteMemory(fes1_base_m, Fes1Bin);
- Exec(fes1_base_m);
- Thread.Sleep(2000);
- return DramInitDone = true;
- }
-
- public byte[] ReadFlash(UInt32 address, UInt32 length, OnFelProgress callback = null)
- {
- var result = new List<byte>();
- while (((length + address % sector_size + sector_size - 1) / sector_size) > flash_mem_size)
- {
- var sectors = (length + address % sector_size + sector_size - 1) / sector_size - flash_mem_size;
- var buf = ReadFlash(address, sectors * sector_size - address % sector_size, callback);
- address += (uint)buf.Length;
- length -= (uint)buf.Length;
- result.AddRange(buf);
- }
- if (result.Count > 0) return result.ToArray();
- var command = string.Format("sunxi_flash phy_read {0:x} {1:x} {2:x};{3}", flash_mem_base, address / sector_size, (length + address % sector_size + sector_size - 1) / sector_size, fastboot);
- RunUbootCmd(command, false, callback);
- result.AddRange(ReadMemory(flash_mem_base + address % sector_size, length, callback));
- return result.ToArray();
- }
-
- public void WriteFlash(UInt32 address, byte[] buffer, OnFelProgress callback = null)
- {
- int length = buffer.Length;
- int pos = 0;
- if ((address % sector_size) != 0)
- throw new FelException(string.Format("Invalid address to flash: 0x{0:X8}", address));
- if ((length % sector_size) != 0)
- throw new FelException(string.Format("Invalid length to flash: 0x{0:X8}", length));
- byte[] newBuf;
- while ((length / sector_size) > flash_mem_size)
- {
- var sectors = (length / sector_size) - flash_mem_size;
- newBuf = new byte[sectors * sector_size];
- Array.Copy(buffer, pos, newBuf, 0, newBuf.Length);
- WriteFlash(address, newBuf, callback);
- address += (UInt32)newBuf.Length;
- length -= newBuf.Length;
- pos += newBuf.Length;
- }
- newBuf = new byte[length - pos];
- Array.Copy(buffer, pos, newBuf, 0, newBuf.Length);
- WriteMemory(flash_mem_base, newBuf, callback);
- var command = string.Format("sunxi_flash phy_write {0:x} {1:x} {2:x};{3}", flash_mem_base, address / sector_size, length / sector_size, fastboot);
- RunUbootCmd(command, false, callback);
- }
-
- public void Exec(UInt32 address)
- {
- FelRequest(AWFELStandardRequest.RequestType.FEL_RUN, address, 0);
- var status = new AWFELStatusResponse(FelRead(8));
- if (status.State != 0) throw new FelException("FEL run error");
- }
-
- public void RunUbootCmd(string command, bool noreturn = false, OnFelProgress callback = null)
- {
- if (callback != null) callback(CurrentAction.RunningCommand, command);
- const UInt32 testSize = 0x20;
- if (UBootBin == null || UBootBin.Length < testSize)
- throw new FelException("Can't init Uboot, incorrect Uboot binary");
- var buf = ReadMemory(uboot_base_m, testSize);
- var buf2 = new byte[testSize];
- Array.Copy(UBootBin, 0, buf2, 0, testSize);
- if (!buf.SequenceEqual(buf2))
- WriteMemory(uboot_base_m, UBootBin);
- var cmdBuff = Encoding.ASCII.GetBytes(command + "\0");
- WriteMemory((uint)(uboot_base_m + cmdOffset), cmdBuff);
- Exec((uint)uboot_base_m);
- if (noreturn) return;
- Close();
- for (int i = 0; i < 10; i++)
- {
- Thread.Sleep(1000);
- if (callback != null) callback(CurrentAction.RunningCommand, command);
- }
- int errorCount = 0;
- while (true)
- {
- try
- {
- Open(vid, pid);
- break;
- }
- catch (Exception ex)
- {
- errorCount++;
- if (errorCount >= 10)
- {
- Close();
- throw ex;
- }
- Thread.Sleep(2000);
- }
- }
- }
- }
-}
+using MadWizard.WinUSBNet;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace com.clusterrr.FelLib
+{
+ public class Fel
+ {
+ public byte[] Fes1Bin;
+ public byte[] UBootBin;
+
+ public enum CurrentAction { RunningCommand, ReadingMemory, WritingMemory }
+ public delegate void OnFelProgress(CurrentAction action, string command);
+
+ USBDevice device = null;
+ byte inEndp = 0;
+ byte outEndp = 0;
+ const int ReadTimeout = 1000;
+ const int WriteTimeout = 1000;
+ public const int MaxBulkSize = 0x10000;
+ UInt16 vid, pid;
+ bool DramInitDone = false;
+
+ const UInt32 cmdOffset = 0x604FF;
+ const UInt32 fes1_base_m = 0x2000;
+ const UInt32 dram_base = 0x40000000;
+ const UInt32 flash_mem_base = 0x43800000;
+ const UInt32 flash_mem_size = 0x20;
+ const UInt32 uboot_base_m = 0x47000000u;
+ const UInt32 sector_size = 0x20000;
+ const UInt32 uboot_base_f = 0x100000;
+ const UInt32 kernel_base_f = (sector_size * 0x30);
+ const UInt32 kernel_base_m = flash_mem_base;
+ const UInt32 kernel_max_size = (uboot_base_m - flash_mem_base);
+ const UInt32 kernel_max_flash_size = (sector_size * 0x20);
+ const string fastboot = "fastboot_test";
+
+ public static bool DeviceExists(UInt16 vid, UInt16 pid)
+ {
+ var fel = new Fel();
+ try
+ {
+ fel.Open(vid, pid);
+#if DEBUG
+ DebugLog("Device detection successful");
+#endif
+ return true;
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ DebugLog("Device detection error: " + ex.Message + ex.StackTrace);
+#endif
+ return false;
+ }
+ finally
+ {
+ fel.Close();
+ }
+ }
+
+ public void Open(UInt16 vid, UInt16 pid)
+ {
+ this.vid = vid;
+ this.pid = pid;
+ Close();
+#if DEBUG
+ DebugLog("Trying to open device...");
+#endif
+ device = USBDevice.GetSingleDevice(vid, pid);
+ if (device == null) throw new FelException("Device with such VID and PID not found");
+#if DEBUG
+ DebugLog("Checking USB endpoints...");
+#endif
+ foreach (var pipe in device.Pipes)
+ {
+ if (pipe.IsIn)
+ {
+ inEndp = pipe.Address;
+#if DEBUG
+ DebugLog("IN endpoint found: "+ inEndp);
+#endif
+ }
+ else
+ {
+ outEndp = pipe.Address;
+#if DEBUG
+ DebugLog("Out endpoint found: "+outEndp);
+#endif
+ }
+ }
+ device.Pipes[inEndp].Policy.PipeTransferTimeout = ReadTimeout;
+ device.Pipes[outEndp].Policy.PipeTransferTimeout = WriteTimeout;
+#if DEBUG
+ DebugLog("Trying to verify device");
+#endif
+ if (VerifyDevice().Board != 0x00166700) throw new FelException("Invalid board ID: " + VerifyDevice().Board);
+ }
+ public void Close()
+ {
+ if (device != null)
+ {
+ try
+ {
+ device.Pipes[inEndp].Abort();
+ }
+ catch { }
+ try
+ {
+ device.Pipes[outEndp].Abort();
+ }
+ catch
+ {
+ }
+ device.Dispose();
+ device = null;
+ }
+ }
+
+ private void WriteToUSB(byte[] buffer)
+ {
+#if DEBUG
+ DebugLog("-> " + BitConverter.ToString(buffer));
+#endif
+
+ device.Pipes[outEndp].Write(buffer);
+ }
+
+ private int ReadFromUSB(byte[] buffer, int offset, int length)
+ {
+ var data = device.Pipes[inEndp].Read(buffer, offset, length);
+#if DEBUG
+ DebugLog("<- " + BitConverter.ToString(buffer));
+#endif
+ return data;
+ }
+ private byte[] ReadFromUSB(UInt32 length)
+ {
+ var result = new byte[length];
+ int pos = 0;
+ while (pos < length)
+ {
+ pos += ReadFromUSB(result, pos, (int)(length - pos));
+ }
+ return result;
+ }
+
+ private void FelWrite(byte[] buffer)
+ {
+ var req = new AWUSBRequest();
+ req.Cmd = AWUSBRequest.RequestType.AW_USB_WRITE;
+ req.Len = (uint)buffer.Length;
+ WriteToUSB(req.Data);
+ WriteToUSB(buffer);
+ var resp = new AWUSBResponse(ReadFromUSB(13));
+ if (resp.CswStatus != 0) throw new FelException("FEL write error");
+ }
+
+ private byte[] FelRead(UInt32 length)
+ {
+ var req = new AWUSBRequest();
+ req.Cmd = AWUSBRequest.RequestType.AW_USB_READ;
+ req.Len = length;
+ WriteToUSB(req.Data);
+
+ var result = ReadFromUSB(length);
+ var resp = new AWUSBResponse(ReadFromUSB(13));
+ if (resp.CswStatus != 0) throw new FelException("FEL read error");
+ return result;
+ }
+
+ private void FelRequest(AWFELStandardRequest.RequestType command)
+ {
+ var req = new AWFELStandardRequest();
+ req.Cmd = command;
+ FelWrite(req.Data);
+ }
+
+ private void FelRequest(AWFELStandardRequest.RequestType command, UInt32 address, UInt32 length)
+ {
+ var req = new AWFELMessage();
+ req.Cmd = command;
+ req.Address = address;
+ req.Len = length;
+ FelWrite(req.Data);
+ }
+
+ public AWFELVerifyDeviceResponse VerifyDevice()
+ {
+ FelRequest(AWFELStandardRequest.RequestType.FEL_VERIFY_DEVICE);
+ byte[] resp;
+ try
+ {
+ resp = FelRead(32);
+ }
+ catch
+ {
+ resp = new byte[32];
+ }
+ var status = new AWFELStatusResponse(FelRead(8));
+ return new AWFELVerifyDeviceResponse(resp);
+ }
+
+ public void WriteMemory(UInt32 address, byte[] buffer, OnFelProgress callback = null)
+ {
+ if (address >= dram_base)
+ InitDram();
+
+ UInt32 length = (UInt32)buffer.Length;
+ if (length != (length & ~((UInt32)3)))
+ {
+ length = (length + 3) & ~((UInt32)3);
+ var newBuffer = new byte[length];
+ Array.Copy(buffer, 0, newBuffer, 0, buffer.Length);
+ buffer = newBuffer;
+ }
+
+ int pos = 0;
+ while (pos < buffer.Length)
+ {
+ if (callback != null) callback(CurrentAction.WritingMemory, null);
+ var buf = new byte[Math.Min(buffer.Length - pos, MaxBulkSize)];
+ Array.Copy(buffer, pos, buf, 0, buf.Length);
+ FelRequest(AWFELStandardRequest.RequestType.FEL_DOWNLOAD, (UInt32)(address + pos), (uint)buf.Length);
+ FelWrite(buf);
+ var status = new AWFELStatusResponse(FelRead(8));
+ if (status.State != 0) throw new FelException("FEL write error");
+ pos += buf.Length;
+ }
+ }
+
+ private byte[] ReadMemory(UInt32 address, UInt32 length, OnFelProgress callback = null)
+ {
+ if (address >= dram_base)
+ InitDram();
+
+ length = (length + 3) & ~((UInt32)3);
+
+ var result = new List<byte>();
+ while (length > 0)
+ {
+ if (callback != null) callback(CurrentAction.ReadingMemory, null);
+ var l = Math.Min(length, MaxBulkSize);
+ FelRequest(AWFELStandardRequest.RequestType.FEL_UPLOAD, address, l);
+ var r = FelRead((UInt32)l);
+ result.AddRange(r);
+ var status = new AWFELStatusResponse(FelRead(8));
+ if (status.State != 0) throw new FelException("FEL read error");
+ length -= l;
+ address += l;
+ }
+ return result.ToArray();
+ }
+
+ public bool InitDram(bool force = false)
+ {
+ if (DramInitDone && !force) return true;
+ if (DramInitDone) return true;
+ const UInt32 testSize = 0x80;
+ if (Fes1Bin == null || Fes1Bin.Length < testSize)
+ throw new FelException("Can't init DRAM, incorrect Fes1 binary");
+ var buf = ReadMemory((UInt32)(fes1_base_m + Fes1Bin.Length - testSize), testSize);
+ var buf2 = new byte[testSize];
+ Array.Copy(Fes1Bin, Fes1Bin.Length - buf.Length, buf2, 0, testSize);
+ if (buf.SequenceEqual(buf2))
+ {
+ return DramInitDone = true;
+ }
+ WriteMemory(fes1_base_m, Fes1Bin);
+ Exec(fes1_base_m);
+ Thread.Sleep(2000);
+ return DramInitDone = true;
+ }
+
+ public byte[] ReadFlash(UInt32 address, UInt32 length, OnFelProgress callback = null)
+ {
+ var result = new List<byte>();
+ while (((length + address % sector_size + sector_size - 1) / sector_size) > flash_mem_size)
+ {
+ var sectors = (length + address % sector_size + sector_size - 1) / sector_size - flash_mem_size;
+ var buf = ReadFlash(address, sectors * sector_size - address % sector_size, callback);
+ address += (uint)buf.Length;
+ length -= (uint)buf.Length;
+ result.AddRange(buf);
+ }
+ if (result.Count > 0) return result.ToArray();
+ var command = string.Format("sunxi_flash phy_read {0:x} {1:x} {2:x};{3}", flash_mem_base, address / sector_size, (length + address % sector_size + sector_size - 1) / sector_size, fastboot);
+ RunUbootCmd(command, false, callback);
+ result.AddRange(ReadMemory(flash_mem_base + address % sector_size, length, callback));
+ return result.ToArray();
+ }
+
+ public void WriteFlash(UInt32 address, byte[] buffer, OnFelProgress callback = null)
+ {
+ int length = buffer.Length;
+ int pos = 0;
+ if ((address % sector_size) != 0)
+ throw new FelException(string.Format("Invalid address to flash: 0x{0:X8}", address));
+ if ((length % sector_size) != 0)
+ throw new FelException(string.Format("Invalid length to flash: 0x{0:X8}", length));
+ byte[] newBuf;
+ while ((length / sector_size) > flash_mem_size)
+ {
+ var sectors = (length / sector_size) - flash_mem_size;
+ newBuf = new byte[sectors * sector_size];
+ Array.Copy(buffer, pos, newBuf, 0, newBuf.Length);
+ WriteFlash(address, newBuf, callback);
+ address += (UInt32)newBuf.Length;
+ length -= newBuf.Length;
+ pos += newBuf.Length;
+ }
+ newBuf = new byte[length - pos];
+ Array.Copy(buffer, pos, newBuf, 0, newBuf.Length);
+ WriteMemory(flash_mem_base, newBuf, callback);
+ var command = string.Format("sunxi_flash phy_write {0:x} {1:x} {2:x};{3}", flash_mem_base, address / sector_size, length / sector_size, fastboot);
+ RunUbootCmd(command, false, callback);
+ }
+
+ public void Exec(UInt32 address)
+ {
+ FelRequest(AWFELStandardRequest.RequestType.FEL_RUN, address, 0);
+ var status = new AWFELStatusResponse(FelRead(8));
+ if (status.State != 0) throw new FelException("FEL run error");
+ }
+
+ public void RunUbootCmd(string command, bool noreturn = false, OnFelProgress callback = null)
+ {
+ if (callback != null) callback(CurrentAction.RunningCommand, command);
+ const UInt32 testSize = 0x20;
+ if (UBootBin == null || UBootBin.Length < testSize)
+ throw new FelException("Can't init Uboot, incorrect Uboot binary");
+ var buf = ReadMemory(uboot_base_m, testSize);
+ var buf2 = new byte[testSize];
+ Array.Copy(UBootBin, 0, buf2, 0, testSize);
+ if (!buf.SequenceEqual(buf2))
+ WriteMemory(uboot_base_m, UBootBin);
+ var cmdBuff = Encoding.ASCII.GetBytes(command + "\0");
+ WriteMemory((uint)(uboot_base_m + cmdOffset), cmdBuff);
+ Exec((uint)uboot_base_m);
+ if (noreturn) return;
+ Close();
+ for (int i = 0; i < 10; i++)
+ {
+ Thread.Sleep(1000);
+ if (callback != null) callback(CurrentAction.RunningCommand, command);
+ }
+ int errorCount = 0;
+ while (true)
+ {
+ try
+ {
+ Open(vid, pid);
+ break;
+ }
+ catch (Exception ex)
+ {
+ errorCount++;
+ if (errorCount >= 10)
+ {
+ Close();
+ throw ex;
+ }
+ Thread.Sleep(2000);
+ }
+ }
+ }
+
+#if DEBUG
+ private static void DebugLog(string text)
+ {
+ Console.WriteLine(text);
+ try
+ {
+ File.AppendAllText("debug.txt", DateTime.Now + ": " + text + "\r\n");
+ }
+ catch { }
+ }
+#endif
+ }
+}
diff --git a/FelLib/WinUSBNet/API/DeviceManagement.cs b/FelLib/WinUSBNet/API/DeviceManagement.cs
index 36a34e83..2d593cce 100644
--- a/FelLib/WinUSBNet/API/DeviceManagement.cs
+++ b/FelLib/WinUSBNet/API/DeviceManagement.cs
@@ -1,311 +1,316 @@
-/* WinUSBNet library
- * (C) 2010 Thomas Bleeker (www.madwizard.org)
- *
- * Licensed under the MIT license, see license.txt or:
- * http://www.opensource.org/licenses/mit-license.php
- */
-
-/* NOTE: Parts of the code in this file are based on the work of Jan Axelson
- * See http://www.lvr.com/winusb.htm for more information
- */
-
-using System;
-using System.Runtime.InteropServices;
-using System.Collections.Generic;
-using System.Windows.Forms;
-using System.Text.RegularExpressions;
-
-namespace MadWizard.WinUSBNet.API
-{
- /// <summary>
- /// Routines for detecting devices and receiving device notifications.
- /// </summary>
- internal static partial class DeviceManagement
- {
-
- // Get device name from notification message.
- // Also checks checkGuid with the GUID from the message to check the notification
- // is for a relevant device. Other messages might be received.
- public static string GetNotifyMessageDeviceName(Message m, Guid checkGuid)
- {
- int stringSize;
-
-
- DEV_BROADCAST_DEVICEINTERFACE_1 devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE_1();
- DEV_BROADCAST_HDR devBroadcastHeader = new DEV_BROADCAST_HDR();
-
- // The LParam parameter of Message is a pointer to a DEV_BROADCAST_HDR structure.
-
- Marshal.PtrToStructure(m.LParam, devBroadcastHeader);
-
- if ((devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
- {
- // The dbch_devicetype parameter indicates that the event applies to a device interface.
- // So the structure in LParam is actually a DEV_BROADCAST_INTERFACE structure,
- // which begins with a DEV_BROADCAST_HDR.
-
- // Obtain the number of characters in dbch_name by subtracting the 32 bytes
- // in the strucutre that are not part of dbch_name and dividing by 2 because there are
- // 2 bytes per character.
-
- stringSize = System.Convert.ToInt32((devBroadcastHeader.dbch_size - 32) / 2);
-
- // The dbcc_name parameter of devBroadcastDeviceInterface contains the device name.
- // Trim dbcc_name to match the size of the String.
-
- devBroadcastDeviceInterface.dbcc_name = new char[stringSize + 1];
-
- // Marshal data from the unmanaged block pointed to by m.LParam
- // to the managed object devBroadcastDeviceInterface.
-
- Marshal.PtrToStructure(m.LParam, devBroadcastDeviceInterface);
-
- // Check if message is for the GUID
- if (devBroadcastDeviceInterface.dbcc_classguid != checkGuid)
- return null;
-
- // Store the device name in a String.
- string deviceNameString = new String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
-
- return deviceNameString;
-
- }
- return null;
- }
-
- private static byte[] GetProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property, out int regType)
- {
- uint requiredSize;
-
- if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, IntPtr.Zero, IntPtr.Zero, 0, out requiredSize))
- {
- if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
- throw APIException.Win32("Failed to get buffer size for device registry property.");
- }
-
- byte[] buffer = new byte[requiredSize];
-
- if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, out regType, buffer, (uint)buffer.Length, out requiredSize))
- throw APIException.Win32("Failed to get device registry property.");
-
- return buffer;
-
-
-
- }
-
- // todo: is the queried data always available, or should we check ERROR_INVALID_DATA?
- private static string GetStringProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property)
- {
- int regType;
- byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out regType);
- if (regType != (int)RegTypes.REG_SZ)
- throw new APIException("Invalid registry type returned for device property.");
-
- // sizof(char), 2 bytes, are removed to leave out the string terminator
- return System.Text.Encoding.Unicode.GetString(buffer, 0, buffer.Length - sizeof(char));
- }
-
- private static string[] GetMultiStringProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property)
- {
- int regType;
- byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out regType);
- if (regType != (int)RegTypes.REG_MULTI_SZ)
- throw new APIException("Invalid registry type returned for device property.");
-
- string fullString = System.Text.Encoding.Unicode.GetString(buffer);
-
- return fullString.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
-
- }
- private static DeviceDetails GetDeviceDetails(string devicePath, IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData)
- {
- DeviceDetails details = new DeviceDetails();
- details.DevicePath = devicePath;
- details.DeviceDescription = GetStringProperty(deviceInfoSet, deviceInfoData, SPDRP.SPDRP_DEVICEDESC);
- details.Manufacturer = GetStringProperty(deviceInfoSet, deviceInfoData, SPDRP.SPDRP_MFG);
- string[] hardwareIDs = GetMultiStringProperty(deviceInfoSet, deviceInfoData, SPDRP.SPDRP_HARDWAREID);
-
- Regex regex = new Regex("^USB\\\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4})", RegexOptions.IgnoreCase);
- bool foundVidPid = false;
- foreach (string hardwareID in hardwareIDs)
- {
- Match match = regex.Match(hardwareID);
- if (match.Success)
- {
- details.VID = ushort.Parse(match.Groups[1].Value, System.Globalization.NumberStyles.AllowHexSpecifier);
- details.PID = ushort.Parse(match.Groups[2].Value, System.Globalization.NumberStyles.AllowHexSpecifier);
- foundVidPid = true;
- break;
- }
- }
-
- if (!foundVidPid)
- throw new APIException("Failed to find VID and PID for USB device. No hardware ID could be parsed.");
-
- return details;
- }
-
-
- public static DeviceDetails[] FindDevices(UInt16 vid, UInt16 pid)
- {
- IntPtr deviceInfoSet = IntPtr.Zero;
- List<DeviceDetails> deviceList = new List<DeviceDetails>();
- var guid = new Guid("{A5DCBF10-6530-11D2-901F-00C04FB951ED}"); // USB device
- try
- {
- deviceInfoSet = SetupDiGetClassDevs(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,
- DIGCF_PRESENT | DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES);
- if (deviceInfoSet == FileIO.INVALID_HANDLE_VALUE)
- throw APIException.Win32("Failed to enumerate devices.");
- int memberIndex = 0;
- while (true)
- {
- // Begin with 0 and increment through the device information set until
- // no more devices are available.
- SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
-
- // The cbSize element of the deviceInterfaceData structure must be set to
- // the structure's size in bytes.
- // The size is 28 bytes for 32-bit code and 32 bytes for 64-bit code.
- deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);
-
- bool success;
-
- success = SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref guid, memberIndex, ref deviceInterfaceData);
-
- // Find out if a device information set was retrieved.
- if (!success)
- {
- int lastError = Marshal.GetLastWin32Error();
- if (lastError == ERROR_NO_MORE_ITEMS)
- break;
-
- throw APIException.Win32("Failed to get device interface.");
- }
- // A device is present.
-
- int bufferSize = 0;
-
- success = SetupDiGetDeviceInterfaceDetail
- (deviceInfoSet,
- ref deviceInterfaceData,
- IntPtr.Zero,
- 0,
- ref bufferSize,
- IntPtr.Zero);
-
- if (!success)
- {
- if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
- throw APIException.Win32("Failed to get interface details buffer size.");
- }
-
- IntPtr detailDataBuffer = IntPtr.Zero;
- try
- {
-
- // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
- detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
-
- // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
-
- Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
-
- // Call SetupDiGetDeviceInterfaceDetail again.
- // This time, pass a pointer to DetailDataBuffer
- // and the returned required buffer size.
-
- // build a DevInfo Data structure
- SP_DEVINFO_DATA da = new SP_DEVINFO_DATA();
- da.cbSize = Marshal.SizeOf(da);
-
-
- success = SetupDiGetDeviceInterfaceDetail
- (deviceInfoSet,
- ref deviceInterfaceData,
- detailDataBuffer,
- bufferSize,
- ref bufferSize,
- ref da);
-
- if (!success)
- throw APIException.Win32("Failed to get device interface details.");
-
-
- // Skip over cbsize (4 bytes) to get the address of the devicePathName.
-
- IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);
- string pathName = Marshal.PtrToStringUni(pDevicePathName);
-
- // Get the String containing the devicePathName.
-
- DeviceDetails details = GetDeviceDetails(pathName, deviceInfoSet, da);
-
- if (details.VID == vid && details.PID == pid)
- deviceList.Add(details);
- }
- finally
- {
- if (detailDataBuffer != IntPtr.Zero)
- {
- Marshal.FreeHGlobal(detailDataBuffer);
- detailDataBuffer = IntPtr.Zero;
- }
- }
- memberIndex++;
- }
- }
- finally
- {
- if (deviceInfoSet != IntPtr.Zero && deviceInfoSet != FileIO.INVALID_HANDLE_VALUE)
- {
- SetupDiDestroyDeviceInfoList(deviceInfoSet);
- }
- }
- return deviceList.ToArray();
- }
-
-
- public static void RegisterForDeviceNotifications(IntPtr controlHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)
- {
-
- DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE();
- IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;
- try
- {
- int size = Marshal.SizeOf(devBroadcastDeviceInterface);
- devBroadcastDeviceInterface.dbcc_size = size;
-
- devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
- devBroadcastDeviceInterface.dbcc_reserved = 0;
- devBroadcastDeviceInterface.dbcc_classguid = classGuid;
- devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size);
-
- // Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer.
- // Set fDeleteOld True to prevent memory leaks.
- Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);
-
- deviceNotificationHandle = RegisterDeviceNotification(controlHandle, devBroadcastDeviceInterfaceBuffer, DEVICE_NOTIFY_WINDOW_HANDLE);
- if (deviceNotificationHandle == IntPtr.Zero)
- throw APIException.Win32("Failed to register device notification");
-
- // Marshal data from the unmanaged block devBroadcastDeviceInterfaceBuffer to
- // the managed object devBroadcastDeviceInterface
- Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);
- }
- finally
- {
- // Free the memory allocated previously by AllocHGlobal.
- if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
- Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
- }
- }
-
- public static void StopDeviceDeviceNotifications(IntPtr deviceNotificationHandle)
- {
- if (!DeviceManagement.UnregisterDeviceNotification(deviceNotificationHandle))
- throw APIException.Win32("Failed to unregister device notification");
- }
- }
-}
+/* WinUSBNet library
+ * (C) 2010 Thomas Bleeker (www.madwizard.org)
+ *
+ * Licensed under the MIT license, see license.txt or:
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+/* NOTE: Parts of the code in this file are based on the work of Jan Axelson
+ * See http://www.lvr.com/winusb.htm for more information
+ */
+
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using System.Text.RegularExpressions;
+
+namespace MadWizard.WinUSBNet.API
+{
+ /// <summary>
+ /// Routines for detecting devices and receiving device notifications.
+ /// </summary>
+ internal static partial class DeviceManagement
+ {
+
+ // Get device name from notification message.
+ // Also checks checkGuid with the GUID from the message to check the notification
+ // is for a relevant device. Other messages might be received.
+ public static string GetNotifyMessageDeviceName(Message m, Guid checkGuid)
+ {
+ int stringSize;
+
+
+ DEV_BROADCAST_DEVICEINTERFACE_1 devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE_1();
+ DEV_BROADCAST_HDR devBroadcastHeader = new DEV_BROADCAST_HDR();
+
+ // The LParam parameter of Message is a pointer to a DEV_BROADCAST_HDR structure.
+
+ Marshal.PtrToStructure(m.LParam, devBroadcastHeader);
+
+ if ((devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
+ {
+ // The dbch_devicetype parameter indicates that the event applies to a device interface.
+ // So the structure in LParam is actually a DEV_BROADCAST_INTERFACE structure,
+ // which begins with a DEV_BROADCAST_HDR.
+
+ // Obtain the number of characters in dbch_name by subtracting the 32 bytes
+ // in the strucutre that are not part of dbch_name and dividing by 2 because there are
+ // 2 bytes per character.
+
+ stringSize = System.Convert.ToInt32((devBroadcastHeader.dbch_size - 32) / 2);
+
+ // The dbcc_name parameter of devBroadcastDeviceInterface contains the device name.
+ // Trim dbcc_name to match the size of the String.
+
+ devBroadcastDeviceInterface.dbcc_name = new char[stringSize + 1];
+
+ // Marshal data from the unmanaged block pointed to by m.LParam
+ // to the managed object devBroadcastDeviceInterface.
+
+ Marshal.PtrToStructure(m.LParam, devBroadcastDeviceInterface);
+
+ // Check if message is for the GUID
+ if (devBroadcastDeviceInterface.dbcc_classguid != checkGuid)
+ return null;
+
+ // Store the device name in a String.
+ string deviceNameString = new String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
+
+ return deviceNameString;
+
+ }
+ return null;
+ }
+
+ private static byte[] GetProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property, out int regType)
+ {
+ uint requiredSize;
+
+ if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, IntPtr.Zero, IntPtr.Zero, 0, out requiredSize))
+ {
+ if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
+ throw APIException.Win32("Failed to get buffer size for device registry property.");
+ }
+
+ byte[] buffer = new byte[requiredSize];
+
+ if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, out regType, buffer, (uint)buffer.Length, out requiredSize))
+ throw APIException.Win32("Failed to get device registry property.");
+
+ return buffer;
+
+
+
+ }
+
+ // todo: is the queried data always available, or should we check ERROR_INVALID_DATA?
+ private static string GetStringProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property)
+ {
+ int regType;
+ byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out regType);
+ if (regType != (int)RegTypes.REG_SZ)
+ throw new APIException("Invalid registry type returned for device property.");
+
+ // sizof(char), 2 bytes, are removed to leave out the string terminator
+ return System.Text.Encoding.Unicode.GetString(buffer, 0, buffer.Length - sizeof(char));
+ }
+
+ private static string[] GetMultiStringProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property)
+ {
+ int regType;
+ byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out regType);
+ if (regType != (int)RegTypes.REG_MULTI_SZ)
+ throw new APIException("Invalid registry type returned for device property.");
+
+ string fullString = System.Text.Encoding.Unicode.GetString(buffer);
+
+ return fullString.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
+
+ }
+ private static DeviceDetails GetDeviceDetails(string devicePath, IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData)
+ {
+ DeviceDetails details = new DeviceDetails();
+ details.DevicePath = devicePath;
+ details.DeviceDescription = GetStringProperty(deviceInfoSet, deviceInfoData, SPDRP.SPDRP_DEVICEDESC);
+ details.Manufacturer = GetStringProperty(deviceInfoSet, deviceInfoData, SPDRP.SPDRP_MFG);
+ string[] hardwareIDs = GetMultiStringProperty(deviceInfoSet, deviceInfoData, SPDRP.SPDRP_HARDWAREID);
+
+ Regex regex = new Regex("^USB\\\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4})", RegexOptions.IgnoreCase);
+ bool foundVidPid = false;
+ foreach (string hardwareID in hardwareIDs)
+ {
+ Match match = regex.Match(hardwareID);
+ if (match.Success)
+ {
+ details.VID = ushort.Parse(match.Groups[1].Value, System.Globalization.NumberStyles.AllowHexSpecifier);
+ details.PID = ushort.Parse(match.Groups[2].Value, System.Globalization.NumberStyles.AllowHexSpecifier);
+ foundVidPid = true;
+ break;
+ }
+ }
+
+ if (!foundVidPid)
+ throw new APIException("Failed to find VID and PID for USB device. No hardware ID could be parsed.");
+
+ return details;
+ }
+
+
+ public static DeviceDetails[] FindDevices(UInt16 vid, UInt16 pid)
+ {
+ IntPtr deviceInfoSet = IntPtr.Zero;
+ List<DeviceDetails> deviceList = new List<DeviceDetails>();
+ var guid = new Guid("{A5DCBF10-6530-11D2-901F-00C04FB951ED}"); // USB device
+ try
+ {
+ deviceInfoSet = SetupDiGetClassDevs(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,
+ DIGCF_PRESENT | DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES);
+ if (deviceInfoSet == FileIO.INVALID_HANDLE_VALUE)
+ throw APIException.Win32("Failed to enumerate devices.");
+ int memberIndex = 0;
+ while (true)
+ {
+ // Begin with 0 and increment through the device information set until
+ // no more devices are available.
+ SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
+
+ // The cbSize element of the deviceInterfaceData structure must be set to
+ // the structure's size in bytes.
+ // The size is 28 bytes for 32-bit code and 32 bytes for 64-bit code.
+ deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);
+
+ bool success;
+
+ success = SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref guid, memberIndex, ref deviceInterfaceData);
+
+ // Find out if a device information set was retrieved.
+ if (!success)
+ {
+ int lastError = Marshal.GetLastWin32Error();
+ if (lastError == ERROR_NO_MORE_ITEMS)
+ break;
+
+ throw APIException.Win32("Failed to get device interface.");
+ }
+ // A device is present.
+
+ int bufferSize = 0;
+
+ success = SetupDiGetDeviceInterfaceDetail
+ (deviceInfoSet,
+ ref deviceInterfaceData,
+ IntPtr.Zero,
+ 0,
+ ref bufferSize,
+ IntPtr.Zero);
+
+ if (!success)
+ {
+ if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
+ throw APIException.Win32("Failed to get interface details buffer size.");
+ }
+
+ IntPtr detailDataBuffer = IntPtr.Zero;
+ try
+ {
+
+ // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
+ detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
+
+ // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
+
+ Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
+
+ // Call SetupDiGetDeviceInterfaceDetail again.
+ // This time, pass a pointer to DetailDataBuffer
+ // and the returned required buffer size.
+
+ // build a DevInfo Data structure
+ SP_DEVINFO_DATA da = new SP_DEVINFO_DATA();
+ da.cbSize = Marshal.SizeOf(da);
+
+
+ success = SetupDiGetDeviceInterfaceDetail
+ (deviceInfoSet,
+ ref deviceInterfaceData,
+ detailDataBuffer,
+ bufferSize,
+ ref bufferSize,
+ ref da);
+
+ if (!success)
+ throw APIException.Win32("Failed to get device interface details.");
+
+
+ // Skip over cbsize (4 bytes) to get the address of the devicePathName.
+
+ IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);
+ string pathName = Marshal.PtrToStringUni(pDevicePathName);
+
+ // Get the String containing the devicePathName.
+ try
+ {
+ DeviceDetails details = GetDeviceDetails(pathName, deviceInfoSet, da);
+ if (details.VID == vid && details.PID == pid)
+ deviceList.Add(details);
+ }
+ catch (APIException)
+ {
+ continue;
+ }
+ }
+ finally
+ {
+ if (detailDataBuffer != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(detailDataBuffer);
+ detailDataBuffer = IntPtr.Zero;
+ }
+ }
+ memberIndex++;
+ }
+ }
+ finally
+ {
+ if (deviceInfoSet != IntPtr.Zero && deviceInfoSet != FileIO.INVALID_HANDLE_VALUE)
+ {
+ SetupDiDestroyDeviceInfoList(deviceInfoSet);
+ }
+ }
+ return deviceList.ToArray();
+ }
+
+
+ public static void RegisterForDeviceNotifications(IntPtr controlHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)
+ {
+
+ DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE();
+ IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;
+ try
+ {
+ int size = Marshal.SizeOf(devBroadcastDeviceInterface);
+ devBroadcastDeviceInterface.dbcc_size = size;
+
+ devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+ devBroadcastDeviceInterface.dbcc_reserved = 0;
+ devBroadcastDeviceInterface.dbcc_classguid = classGuid;
+ devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size);
+
+ // Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer.
+ // Set fDeleteOld True to prevent memory leaks.
+ Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);
+
+ deviceNotificationHandle = RegisterDeviceNotification(controlHandle, devBroadcastDeviceInterfaceBuffer, DEVICE_NOTIFY_WINDOW_HANDLE);
+ if (deviceNotificationHandle == IntPtr.Zero)
+ throw APIException.Win32("Failed to register device notification");
+
+ // Marshal data from the unmanaged block devBroadcastDeviceInterfaceBuffer to
+ // the managed object devBroadcastDeviceInterface
+ Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);
+ }
+ finally
+ {
+ // Free the memory allocated previously by AllocHGlobal.
+ if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
+ Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
+ }
+ }
+
+ public static void StopDeviceDeviceNotifications(IntPtr deviceNotificationHandle)
+ {
+ if (!DeviceManagement.UnregisterDeviceNotification(deviceNotificationHandle))
+ throw APIException.Win32("Failed to unregister device notification");
+ }
+ }
+}