Refactor USB functions classes.

This commit is contained in:
2019-10-27 20:47:29 +00:00
parent 7c66697f2f
commit d360cb428a

View File

@@ -1,4 +1,4 @@
// /*************************************************************************** // /***************************************************************************
// The Disc Image Chef // The Disc Image Chef
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// //
@@ -45,7 +45,7 @@ namespace DiscImageChef.Devices.Windows
/// <summary> /// <summary>
/// Implements functions for getting and accesing information from the USB bus /// Implements functions for getting and accesing information from the USB bus
/// </summary> /// </summary>
static partial class Usb internal static partial class Usb
{ {
private const int IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080; private const int IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080;
internal const string GuidDevinterfaceDisk = "53f56307-b6bf-11d0-94f2-00a0c91efb8b"; internal const string GuidDevinterfaceDisk = "53f56307-b6bf-11d0-94f2-00a0c91efb8b";
@@ -59,9 +59,9 @@ namespace DiscImageChef.Devices.Windows
/// <returns>List of usb devices</returns> /// <returns>List of usb devices</returns>
internal static List<UsbDevice> GetConnectedDevices() internal static List<UsbDevice> GetConnectedDevices()
{ {
List<UsbDevice> devList = new List<UsbDevice>(); var devList = new List<UsbDevice>();
foreach(UsbController controller in GetHostControllers()) ListHub(controller.GetRootHub(), devList); foreach (var controller in GetHostControllers()) ListHub(controller.GetRootHub(), devList);
return devList; return devList;
} }
@@ -71,11 +71,13 @@ namespace DiscImageChef.Devices.Windows
/// </summary> /// </summary>
/// <param name="hub">Hub</param> /// <param name="hub">Hub</param>
/// <param name="devList">Device list</param> /// <param name="devList">Device list</param>
static void ListHub(UsbHub hub, ICollection<UsbDevice> devList) private static void ListHub(UsbHub hub, ICollection<UsbDevice> devList)
{ {
foreach(UsbPort port in hub.GetPorts()) foreach (var port in hub.GetPorts())
if (port.IsHub) if (port.IsHub)
{
ListHub(port.GetHub(), devList); ListHub(port.GetHub(), devList);
}
else else
{ {
if (port.IsDeviceConnected) devList.Add(port.GetDevice()); if (port.IsDeviceConnected) devList.Add(port.GetDevice());
@@ -91,7 +93,7 @@ namespace DiscImageChef.Devices.Windows
{ {
UsbDevice foundDevice = null; UsbDevice foundDevice = null;
foreach(UsbController controller in GetHostControllers()) foreach (var controller in GetHostControllers())
{ {
SearchHubDriverKeyName(controller.GetRootHub(), ref foundDevice, driverKeyName); SearchHubDriverKeyName(controller.GetRootHub(), ref foundDevice, driverKeyName);
if (foundDevice != null) break; if (foundDevice != null) break;
@@ -106,16 +108,18 @@ namespace DiscImageChef.Devices.Windows
/// <param name="hub">Hub</param> /// <param name="hub">Hub</param>
/// <param name="foundDevice">UsbDevice</param> /// <param name="foundDevice">UsbDevice</param>
/// <param name="driverKeyName">DriverKeyName</param> /// <param name="driverKeyName">DriverKeyName</param>
static void SearchHubDriverKeyName(UsbHub hub, ref UsbDevice foundDevice, string driverKeyName) private static void SearchHubDriverKeyName(UsbHub hub, ref UsbDevice foundDevice, string driverKeyName)
{ {
foreach(UsbPort port in hub.GetPorts()) foreach (var port in hub.GetPorts())
if (port.IsHub) if (port.IsHub)
{
SearchHubDriverKeyName(port.GetHub(), ref foundDevice, driverKeyName); SearchHubDriverKeyName(port.GetHub(), ref foundDevice, driverKeyName);
}
else else
{ {
if (!port.IsDeviceConnected) continue; if (!port.IsDeviceConnected) continue;
UsbDevice device = port.GetDevice(); var device = port.GetDevice();
if (device.DeviceDriverKey != driverKeyName) continue; if (device.DeviceDriverKey != driverKeyName) continue;
foundDevice = device; foundDevice = device;
@@ -128,11 +132,11 @@ namespace DiscImageChef.Devices.Windows
/// </summary> /// </summary>
/// <param name="instanceId">Device instance ID</param> /// <param name="instanceId">Device instance ID</param>
/// <returns>USB device</returns> /// <returns>USB device</returns>
static UsbDevice FindDeviceByInstanceId(string instanceId) private static UsbDevice FindDeviceByInstanceId(string instanceId)
{ {
UsbDevice foundDevice = null; UsbDevice foundDevice = null;
foreach(UsbController controller in GetHostControllers()) foreach (var controller in GetHostControllers())
{ {
SearchHubInstanceId(controller.GetRootHub(), ref foundDevice, instanceId); SearchHubInstanceId(controller.GetRootHub(), ref foundDevice, instanceId);
if (foundDevice != null) break; if (foundDevice != null) break;
@@ -147,16 +151,18 @@ namespace DiscImageChef.Devices.Windows
/// <param name="hub">Hub</param> /// <param name="hub">Hub</param>
/// <param name="foundDevice">USB device</param> /// <param name="foundDevice">USB device</param>
/// <param name="instanceId">Device instance ID</param> /// <param name="instanceId">Device instance ID</param>
static void SearchHubInstanceId(UsbHub hub, ref UsbDevice foundDevice, string instanceId) private static void SearchHubInstanceId(UsbHub hub, ref UsbDevice foundDevice, string instanceId)
{ {
foreach(UsbPort port in hub.GetPorts()) foreach (var port in hub.GetPorts())
if (port.IsHub) if (port.IsHub)
{
SearchHubInstanceId(port.GetHub(), ref foundDevice, instanceId); SearchHubInstanceId(port.GetHub(), ref foundDevice, instanceId);
}
else else
{ {
if (!port.IsDeviceConnected) continue; if (!port.IsDeviceConnected) continue;
UsbDevice device = port.GetDevice(); var device = port.GetDevice();
if (device.InstanceId != instanceId) continue; if (device.InstanceId != instanceId) continue;
foundDevice = device; foundDevice = device;
@@ -165,10 +171,10 @@ namespace DiscImageChef.Devices.Windows
} }
[DllImport("setupapi.dll")] [DllImport("setupapi.dll")]
static extern int CM_Get_Parent(out IntPtr pdnDevInst, IntPtr dnDevInst, int ulFlags); private static extern int CM_Get_Parent(out IntPtr pdnDevInst, IntPtr dnDevInst, int ulFlags);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)] [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
static extern int CM_Get_Device_ID(IntPtr dnDevInst, IntPtr buffer, int bufferLen, int ulFlags); private static extern int CM_Get_Device_ID(IntPtr dnDevInst, IntPtr buffer, int bufferLen, int ulFlags);
/// <summary> /// <summary>
/// Find a device based upon a Drive Letter /// Find a device based upon a Drive Letter
@@ -181,7 +187,7 @@ namespace DiscImageChef.Devices.Windows
// We start by getting the unique DeviceNumber of the given // We start by getting the unique DeviceNumber of the given
// DriveLetter. We'll use this later to find a matching // DriveLetter. We'll use this later to find a matching
// DevicePath "symbolic name" // DevicePath "symbolic name"
int devNum = GetDeviceNumber(@"\\.\" + driveLetter.TrimEnd('\\')); var devNum = GetDeviceNumber(@"\\.\" + driveLetter.TrimEnd('\\'));
return devNum < 0 ? null : FindDeviceNumber(devNum, deviceGuid); return devNum < 0 ? null : FindDeviceNumber(devNum, deviceGuid);
} }
@@ -196,7 +202,7 @@ namespace DiscImageChef.Devices.Windows
// We start by getting the unique DeviceNumber of the given // We start by getting the unique DeviceNumber of the given
// DriveLetter. We'll use this later to find a matching // DriveLetter. We'll use this later to find a matching
// DevicePath "symbolic name" // DevicePath "symbolic name"
int devNum = GetDeviceNumber(drivePath); var devNum = GetDeviceNumber(drivePath);
return devNum < 0 ? null : FindDeviceNumber(devNum, deviceGuid); return devNum < 0 ? null : FindDeviceNumber(devNum, deviceGuid);
} }
@@ -206,24 +212,24 @@ namespace DiscImageChef.Devices.Windows
/// <param name="devNum">Device Number</param> /// <param name="devNum">Device Number</param>
/// <param name="deviceGuid">Device GUID</param> /// <param name="deviceGuid">Device GUID</param>
/// <returns>USB device</returns> /// <returns>USB device</returns>
static UsbDevice FindDeviceNumber(int devNum, string deviceGuid) private static UsbDevice FindDeviceNumber(int devNum, string deviceGuid)
{ {
UsbDevice foundDevice = null; UsbDevice foundDevice = null;
string instanceId = ""; var instanceId = "";
Guid diskGuid = new Guid(deviceGuid); var diskGuid = new Guid(deviceGuid);
// We start at the "root" of the device tree and look for all // We start at the "root" of the device tree and look for all
// devices that match the interface GUID of a disk // devices that match the interface GUID of a disk
IntPtr h = SetupDiGetClassDevs(ref diskGuid, 0, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); var h = SetupDiGetClassDevs(ref diskGuid, 0, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (h != INVALID_HANDLE_VALUE) if (h != INVALID_HANDLE_VALUE)
{ {
bool success; bool success;
int i = 0; var i = 0;
do do
{ {
// create a Device Interface Data structure // create a Device Interface Data structure
SpDeviceInterfaceData dia = new SpDeviceInterfaceData(); var dia = new SpDeviceInterfaceData();
dia.cbSize = Marshal.SizeOf(dia); dia.cbSize = Marshal.SizeOf(dia);
// start the enumeration // start the enumeration
@@ -231,25 +237,25 @@ namespace DiscImageChef.Devices.Windows
if (success) if (success)
{ {
// build a DevInfo Data structure // build a DevInfo Data structure
SpDevinfoData da = new SpDevinfoData(); var da = new SpDevinfoData();
da.cbSize = Marshal.SizeOf(da); da.cbSize = Marshal.SizeOf(da);
// build a Device Interface Detail Data structure // build a Device Interface Detail Data structure
SpDeviceInterfaceDetailData didd = var didd =
new SpDeviceInterfaceDetailData {cbSize = 4 + Marshal.SystemDefaultCharSize}; // trust me :) new SpDeviceInterfaceDetailData {cbSize = 4 + Marshal.SystemDefaultCharSize}; // trust me :)
// now we can get some more detailed information // now we can get some more detailed information
int nRequiredSize = 0; var nRequiredSize = 0;
const int N_BYTES = BUFFER_SIZE; const int N_BYTES = BUFFER_SIZE;
if (SetupDiGetDeviceInterfaceDetail(h, ref dia, ref didd, N_BYTES, ref nRequiredSize, ref da)) if (SetupDiGetDeviceInterfaceDetail(h, ref dia, ref didd, N_BYTES, ref nRequiredSize, ref da))
if (GetDeviceNumber(didd.DevicePath) == devNum) if (GetDeviceNumber(didd.DevicePath) == devNum)
{ {
// current InstanceID is at the "USBSTOR" level, so we // current InstanceID is at the "USBSTOR" level, so we
// need up "move up" one level to get to the "USB" level // need up "move up" one level to get to the "USB" level
CM_Get_Parent(out IntPtr ptrPrevious, da.DevInst, 0); CM_Get_Parent(out var ptrPrevious, da.DevInst, 0);
// Now we get the InstanceID of the USB level device // Now we get the InstanceID of the USB level device
IntPtr ptrInstanceBuf = Marshal.AllocHGlobal(N_BYTES); var ptrInstanceBuf = Marshal.AllocHGlobal(N_BYTES);
CM_Get_Device_ID(ptrPrevious, ptrInstanceBuf, N_BYTES, 0); CM_Get_Device_ID(ptrPrevious, ptrInstanceBuf, N_BYTES, 0);
instanceId = Marshal.PtrToStringAuto(ptrInstanceBuf); instanceId = Marshal.PtrToStringAuto(ptrInstanceBuf);
@@ -260,8 +266,7 @@ namespace DiscImageChef.Devices.Windows
} }
i++; i++;
} } while (success);
while(success);
SetupDiDestroyDeviceInfoList(h); SetupDiDestroyDeviceInfoList(h);
} }
@@ -277,16 +282,16 @@ namespace DiscImageChef.Devices.Windows
/// </summary> /// </summary>
/// <param name="devicePath">Device path</param> /// <param name="devicePath">Device path</param>
/// <returns>Device number</returns> /// <returns>Device number</returns>
static int GetDeviceNumber(string devicePath) private static int GetDeviceNumber(string devicePath)
{ {
int ans = -1; var ans = -1;
IntPtr h = CreateFile(devicePath.TrimEnd('\\'), 0, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); var h = CreateFile(devicePath.TrimEnd('\\'), 0, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
if (h == INVALID_HANDLE_VALUE) return ans; if (h == INVALID_HANDLE_VALUE) return ans;
StorageDeviceNumber sdn = new StorageDeviceNumber(); var sdn = new StorageDeviceNumber();
int nBytes = Marshal.SizeOf(sdn); var nBytes = Marshal.SizeOf(sdn);
IntPtr ptrSdn = Marshal.AllocHGlobal(nBytes); var ptrSdn = Marshal.AllocHGlobal(nBytes);
if (DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, IntPtr.Zero, 0, ptrSdn, nBytes, out _, IntPtr.Zero)) if (DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, IntPtr.Zero, 0, ptrSdn, nBytes, out _, IntPtr.Zero))
{ {
@@ -302,11 +307,11 @@ namespace DiscImageChef.Devices.Windows
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
struct StorageDeviceNumber private struct StorageDeviceNumber
{ {
internal int DeviceType; internal readonly int DeviceType;
internal int DeviceNumber; internal readonly int DeviceNumber;
internal int PartitionNumber; internal readonly int PartitionNumber;
} }
} }
} }