检测设备是否使用USB 3.0

时间:2013-04-04 19:31:43

标签: c# .net usb

有没有人知道如何使用C#检测连接到USB 3.0主机端口的USB设备是以3.0还是2.0运行?

我们正在制造USB 3.0延长线,我们需要验证所有引脚是否已正确焊接。我们想在软件中这样做。我们想将3.0拇指驱动器连接到电缆,并检查设备是否在USB 3.0模式下运行。如果它处于2.0模式,我们知道它们是一个或多个USB 3.0线的问题。

1 个答案:

答案 0 :(得分:10)

我已经设法在一些源代码I found的帮助下制作了一个工作演示。

private static void Main(string[] args)
{
  var hostCtrls = USB.GetHostControllers();

  foreach (var hostCtrl in hostCtrls)
  {
    var hub = hostCtrl.GetRootHub();
    foreach (var port in hub.GetPorts())
    {
      if (port.IsDeviceConnected && !port.IsHub)
      {
        var device = port.GetDevice();
        Console.WriteLine("Serial: " + device.DeviceSerialNumber);
        Console.WriteLine("Speed:  " + port.Speed);
        Console.WriteLine("Port:   " + device.PortNumber + Environment.NewLine);
      }
    }
  }
}

Output

该应用程序枚举USB主机控制器。然后它获取根集线器并使用属于它的端口。如果连接了设备但它不是集线器,则会显示所需信息。

在您的情况下,您可能知道要检查哪个设备,以便您可以修改源(上面和链接的代码)以专门检查该设备。

您需要在USB类中创建一个方法,通过指定端口号和集线器路径来从特定集线器获取特定端口。

类似的东西:

GetDeviceSpeed(string hubPath, int portNumber) { ... }

并使用适当的值调用它:

var hubPath = @"\\.\NUSB3#ROOT_HUB30#5&b235176&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8}";
var portNumber = 2;
GetDeviceSpeed(hubPath, portNumber);

如果您不愿意这样做,那么您只需使用上面的代码并注意您要测试的设备的序列号,然后只检查速度:

if (device.DeviceSerialNumber == "xxxxxx")
  Console.WriteLine("Speed:  " + port.Speed);

如果您要在具有GUI的应用程序中使用它,您只需在下拉列表中选择要检查的设备。

嗯......有一些想法,希望是一个有效的解决方案。

<强>附录

为了长寿,我将包括我用于演示的修改过的类 (由于300个字符的SO限制而删除了注释和空行):

public class USB
{
    const int GENERIC_WRITE = 0x40000000;
    const int FILE_SHARE_READ = 0x1;
    const int FILE_SHARE_WRITE = 0x2;
    const int OPEN_EXISTING = 0x3;
    const int INVALID_HANDLE_VALUE = -1;
    const int IOCTL_GET_HCD_DRIVERKEY_NAME = 0x220424;
    const int IOCTL_USB_GET_ROOT_HUB_NAME = 0x220408;
    const int IOCTL_USB_GET_NODE_INFORMATION = 0x220408;
    const int IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX = 0x220448;
    const int IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION = 0x220410;
    const int IOCTL_USB_GET_NODE_CONNECTION_NAME = 0x220414;
    const int IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME = 0x220420;
    const int USB_DEVICE_DESCRIPTOR_TYPE = 0x1;
    const int USB_STRING_DESCRIPTOR_TYPE = 0x3;
    const int BUFFER_SIZE = 2048;
    const int MAXIMUM_USB_STRING_LENGTH = 255;
    const string GUID_DEVINTERFACE_HUBCONTROLLER = "3abf6f2d-71c4-462a-8a92-1e6861e6af27";
    const string REGSTR_KEY_USB = "USB";
    const int DIGCF_PRESENT = 0x2;
    const int DIGCF_ALLCLASSES = 0x4;
    const int DIGCF_DEVICEINTERFACE = 0x10;
    const int SPDRP_DRIVER = 0x9;
    const int SPDRP_DEVICEDESC = 0x0;
    const int REG_SZ = 1;
    enum USB_HUB_NODE
    {
        UsbHub,
        UsbMIParent
    }
    enum USB_CONNECTION_STATUS
    {
        NoDeviceConnected,
        DeviceConnected,
        DeviceFailedEnumeration,
        DeviceGeneralFailure,
        DeviceCausedOvercurrent,
        DeviceNotEnoughPower,
        DeviceNotEnoughBandwidth,
        DeviceHubNestedTooDeeply,
        DeviceInLegacyHub
    }
    enum USB_DEVICE_SPEED : byte
    {
        UsbLowSpeed,
        UsbFullSpeed,
        UsbHighSpeed,
        UsbSuperSpeed
    }
    [StructLayout(LayoutKind.Sequential)]
    struct SP_DEVINFO_DATA
    {
        public int cbSize;
        public Guid ClassGuid;
        public IntPtr DevInst;
        public IntPtr Reserved;
    }
    [StructLayout(LayoutKind.Sequential)]
    struct SP_DEVICE_INTERFACE_DATA
    {
        public int cbSize;
        public Guid InterfaceClassGuid;
        public int Flags;
        public IntPtr Reserved;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct SP_DEVICE_INTERFACE_DETAIL_DATA
    {
        public int cbSize;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
        public string DevicePath;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct USB_HCD_DRIVERKEY_NAME
    {
        public int ActualLength;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
        public string DriverKeyName;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct USB_ROOT_HUB_NAME
    {
        public int ActualLength;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
        public string RootHubName;
    }
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct USB_HUB_DESCRIPTOR
    {
        public byte bDescriptorLength;
        public byte bDescriptorType;
        public byte bNumberOfPorts;
        public short wHubCharacteristics;
        public byte bPowerOnToPowerGood;
        public byte bHubControlCurrent;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public byte[] bRemoveAndPowerMask;
    }
    [StructLayout(LayoutKind.Sequential)]
    struct USB_HUB_INFORMATION
    {
        public USB_HUB_DESCRIPTOR HubDescriptor;
        public byte HubIsBusPowered;
    }
    [StructLayout(LayoutKind.Sequential)]
    struct USB_NODE_INFORMATION
    {
        public int NodeType;
        public USB_HUB_INFORMATION HubInformation;
    }
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct USB_NODE_CONNECTION_INFORMATION_EX
    {
        public int ConnectionIndex;
        public USB_DEVICE_DESCRIPTOR DeviceDescriptor;
        public byte CurrentConfigurationValue;
        public byte Speed;
        public byte DeviceIsHub;
        public short DeviceAddress;
        public int NumberOfOpenPipes;
        public int ConnectionStatus;
    }
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct USB_DEVICE_DESCRIPTOR
    {
        public byte bLength;
        public byte bDescriptorType;
        public short bcdUSB;
        public byte bDeviceClass;
        public byte bDeviceSubClass;
        public byte bDeviceProtocol;
        public byte bMaxPacketSize0;
        public short idVendor;
        public short idProduct;
        public short bcdDevice;
        public byte iManufacturer;
        public byte iProduct;
        public byte iSerialNumber;
        public byte bNumConfigurations;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct USB_STRING_DESCRIPTOR
    {
        public byte bLength;
        public byte bDescriptorType;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAXIMUM_USB_STRING_LENGTH)]
        public string bString;
    }
    [StructLayout(LayoutKind.Sequential)]
    struct USB_SETUP_PACKET
    {
        public byte bmRequest;
        public byte bRequest;
        public short wValue;
        public short wIndex;
        public short wLength;
    }
    [StructLayout(LayoutKind.Sequential)]
    struct USB_DESCRIPTOR_REQUEST
    {
        public int ConnectionIndex;
        public USB_SETUP_PACKET SetupPacket;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct USB_NODE_CONNECTION_NAME
    {
        public int ConnectionIndex;
        public int ActualLength;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
        public string NodeName;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct USB_NODE_CONNECTION_DRIVERKEY_NAME
    {
        public int ConnectionIndex;
        public int ActualLength;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = BUFFER_SIZE)]
        public string DriverKeyName;
    }
    [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SetupDiGetClassDevs(
            ref Guid ClassGuid,
            int Enumerator,
            IntPtr hwndParent,
            int Flags
    );
    [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SetupDiGetClassDevs(
            int ClassGuid,
            string Enumerator,
            IntPtr hwndParent,
            int Flags
    );
    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool SetupDiEnumDeviceInterfaces(
            IntPtr DeviceInfoSet,
            IntPtr DeviceInfoData,
            ref Guid InterfaceClassGuid,
            int MemberIndex,
            ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData
    );
    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool SetupDiGetDeviceInterfaceDetail(
            IntPtr DeviceInfoSet,
            ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
            ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,
            int DeviceInterfaceDetailDataSize,
            ref int RequiredSize,
            ref SP_DEVINFO_DATA DeviceInfoData
    );
    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool SetupDiGetDeviceRegistryProperty(
            IntPtr DeviceInfoSet,
            ref SP_DEVINFO_DATA DeviceInfoData,
            int iProperty,
            ref int PropertyRegDataType,
            IntPtr PropertyBuffer,
            int PropertyBufferSize,
            ref int RequiredSize
    );
    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool SetupDiEnumDeviceInfo(
            IntPtr DeviceInfoSet,
            int MemberIndex,
            ref SP_DEVINFO_DATA DeviceInfoData
    );
    [DllImport("setupapi.dll", SetLastError = true)]
    static extern bool SetupDiDestroyDeviceInfoList(
            IntPtr DeviceInfoSet
    );
    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool SetupDiGetDeviceInstanceId(
            IntPtr DeviceInfoSet,
            ref SP_DEVINFO_DATA DeviceInfoData,
            StringBuilder DeviceInstanceId,
            int DeviceInstanceIdSize,
            out int RequiredSize
    );
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool DeviceIoControl(
            IntPtr hDevice,
            int dwIoControlCode,
            IntPtr lpInBuffer,
            int nInBufferSize,
            IntPtr lpOutBuffer,
            int nOutBufferSize,
            out int lpBytesReturned,
            IntPtr lpOverlapped
    );
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern IntPtr CreateFile(
         string lpFileName,
         int dwDesiredAccess,
         int dwShareMode,
         IntPtr lpSecurityAttributes,
         int dwCreationDisposition,
         int dwFlagsAndAttributes,
         IntPtr hTemplateFile
    );
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern bool CloseHandle(
            IntPtr hObject
    );
    static public System.Collections.ObjectModel.ReadOnlyCollection<USBController> GetHostControllers()
    {
        List<USBController> HostList = new List<USBController>();
        Guid HostGUID = new Guid(GUID_DEVINTERFACE_HUBCONTROLLER);
        IntPtr h = SetupDiGetClassDevs(ref HostGUID, 0, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
        if (h.ToInt32() != INVALID_HANDLE_VALUE)
        {
            IntPtr ptrBuf = Marshal.AllocHGlobal(BUFFER_SIZE);
            bool Success;
            int i = 0;
            do
            {
                USBController host = new USBController();
                host.ControllerIndex = i;
                SP_DEVICE_INTERFACE_DATA dia = new SP_DEVICE_INTERFACE_DATA();
                dia.cbSize = Marshal.SizeOf(dia);
                Success = SetupDiEnumDeviceInterfaces(h, IntPtr.Zero, ref HostGUID, i, ref dia);
                if (Success)
                {
                    SP_DEVINFO_DATA da = new SP_DEVINFO_DATA();
                    da.cbSize = Marshal.SizeOf(da);
                    SP_DEVICE_INTERFACE_DETAIL_DATA didd = new SP_DEVICE_INTERFACE_DETAIL_DATA();
                    didd.cbSize = 4 + Marshal.SystemDefaultCharSize;
                    int nRequiredSize = 0;
                    int nBytes = BUFFER_SIZE;
                    if (SetupDiGetDeviceInterfaceDetail(h, ref dia, ref didd, nBytes, ref nRequiredSize, ref da))
                    {
                        host.ControllerDevicePath = didd.DevicePath;
                        int RequiredSize = 0;
                        int RegType = REG_SZ;
                        if (SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DEVICEDESC, ref RegType, ptrBuf, BUFFER_SIZE, ref RequiredSize))
                        {
                            host.ControllerDeviceDesc = Marshal.PtrToStringAuto(ptrBuf);
                        }
                        if (SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DRIVER, ref RegType, ptrBuf, BUFFER_SIZE, ref RequiredSize))
                        {
                            host.ControllerDriverKeyName = Marshal.PtrToStringAuto(ptrBuf);
                        }
                    }
                    HostList.Add(host);
                }
                i++;
            } while (Success);
            Marshal.FreeHGlobal(ptrBuf);
            SetupDiDestroyDeviceInfoList(h);
        }
        return new System.Collections.ObjectModel.ReadOnlyCollection<USBController>(HostList);
    }
    public class USBController
    {
        internal int ControllerIndex;
        internal string ControllerDriverKeyName, ControllerDevicePath, ControllerDeviceDesc;
        public USBController()
        {
            ControllerIndex = 0;
            ControllerDevicePath = "";
            ControllerDeviceDesc = "";
            ControllerDriverKeyName = "";
        }
        public int Index
        {
            get { return ControllerIndex; }
        }
        public string DevicePath
        {
            get { return ControllerDevicePath; }
        }
        public string DriverKeyName
        {
            get { return ControllerDriverKeyName; }
        }
        public string Name
        {
            get { return ControllerDeviceDesc; }
        }
        public USBHub GetRootHub()
        {
            IntPtr h, h2;
            USBHub Root = new USBHub();
            Root.HubIsRootHub = true;
            Root.HubDeviceDesc = "Root Hub";
            h = CreateFile(ControllerDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
            if (h.ToInt32() != INVALID_HANDLE_VALUE)
            {
                int nBytesReturned;
                USB_ROOT_HUB_NAME HubName = new USB_ROOT_HUB_NAME();
                int nBytes = Marshal.SizeOf(HubName);
                IntPtr ptrHubName = Marshal.AllocHGlobal(nBytes);
                if (DeviceIoControl(h, IOCTL_USB_GET_ROOT_HUB_NAME, ptrHubName, nBytes, ptrHubName, nBytes, out nBytesReturned, IntPtr.Zero))
                {
                    HubName = (USB_ROOT_HUB_NAME)Marshal.PtrToStructure(ptrHubName, typeof(USB_ROOT_HUB_NAME));
                    Root.HubDevicePath = @"\\.\" + HubName.RootHubName;
                }
                h2 = CreateFile(Root.HubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
                if (h2.ToInt32() != INVALID_HANDLE_VALUE)
                {
                    USB_NODE_INFORMATION NodeInfo = new USB_NODE_INFORMATION();
                    NodeInfo.NodeType = (int)USB_HUB_NODE.UsbHub;
                    nBytes = Marshal.SizeOf(NodeInfo);
                    IntPtr ptrNodeInfo = Marshal.AllocHGlobal(nBytes);
                    Marshal.StructureToPtr(NodeInfo, ptrNodeInfo, true);
                    if (DeviceIoControl(h2, IOCTL_USB_GET_NODE_INFORMATION, ptrNodeInfo, nBytes, ptrNodeInfo, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        NodeInfo = (USB_NODE_INFORMATION)Marshal.PtrToStructure(ptrNodeInfo, typeof(USB_NODE_INFORMATION));
                        Root.HubIsBusPowered = Convert.ToBoolean(NodeInfo.HubInformation.HubIsBusPowered);
                        Root.HubPortCount = NodeInfo.HubInformation.HubDescriptor.bNumberOfPorts;
                    }
                    Marshal.FreeHGlobal(ptrNodeInfo);
                    CloseHandle(h2);
                }
                Marshal.FreeHGlobal(ptrHubName);
                CloseHandle(h);
            }
            return Root;
        }
    }
    public class USBHub
    {
        internal int HubPortCount;
        internal string HubDriverKey, HubDevicePath, HubDeviceDesc;
        internal string HubManufacturer, HubProduct, HubSerialNumber, HubInstanceID;
        internal bool HubIsBusPowered, HubIsRootHub;
        public USBHub()
        {
            HubPortCount = 0;
            HubDevicePath = "";
            HubDeviceDesc = "";
            HubDriverKey = "";
            HubIsBusPowered = false;
            HubIsRootHub = false;
            HubManufacturer = "";
            HubProduct = "";
            HubSerialNumber = "";
            HubInstanceID = "";
        }
        public int PortCount
        {
            get { return HubPortCount; }
        }
        public string DevicePath
        {
            get { return HubDevicePath; }
        }
        public string DriverKey
        {
            get { return HubDriverKey; }
        }
        public string Name
        {
            get { return HubDeviceDesc; }
        }
        public string InstanceID
        {
            get { return HubInstanceID; }
        }
        public bool IsBusPowered
        {
            get { return HubIsBusPowered; }
        }
        public bool IsRootHub
        {
            get { return HubIsRootHub; }
        }
        public string Manufacturer
        {
            get { return HubManufacturer; }
        }
        public string Product
        {
            get { return HubProduct; }
        }
        public string SerialNumber
        {
            get { return HubSerialNumber; }
        }
        public System.Collections.ObjectModel.ReadOnlyCollection<USBPort> GetPorts()
        {
            List<USBPort> PortList = new List<USBPort>();
            IntPtr h = CreateFile(HubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
            if (h.ToInt32() != INVALID_HANDLE_VALUE)
            {
                int nBytes = Marshal.SizeOf(typeof(USB_NODE_CONNECTION_INFORMATION_EX));
                IntPtr ptrNodeConnection = Marshal.AllocHGlobal(nBytes);
                for (int i = 1; i <= HubPortCount; i++)
                {
                    int nBytesReturned;
                    USB_NODE_CONNECTION_INFORMATION_EX NodeConnection = new USB_NODE_CONNECTION_INFORMATION_EX();
                    NodeConnection.ConnectionIndex = i;
                    Marshal.StructureToPtr(NodeConnection, ptrNodeConnection, true);
                    if (DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, ptrNodeConnection, nBytes, ptrNodeConnection, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        NodeConnection = (USB_NODE_CONNECTION_INFORMATION_EX)Marshal.PtrToStructure(ptrNodeConnection, typeof(USB_NODE_CONNECTION_INFORMATION_EX));
                        USBPort port = new USBPort();
                        port.PortPortNumber = i;
                        port.PortHubDevicePath = HubDevicePath;
                        USB_CONNECTION_STATUS Status = (USB_CONNECTION_STATUS)NodeConnection.ConnectionStatus;
                        port.PortStatus = Status.ToString();
                        USB_DEVICE_SPEED Speed = (USB_DEVICE_SPEED)NodeConnection.Speed;
                        port.PortSpeed = Speed.ToString();
                        port.PortIsDeviceConnected = (NodeConnection.ConnectionStatus == (int)USB_CONNECTION_STATUS.DeviceConnected);
                        port.PortIsHub = Convert.ToBoolean(NodeConnection.DeviceIsHub);
                        port.PortDeviceDescriptor = NodeConnection.DeviceDescriptor;
                        PortList.Add(port);
                    }
                }
                Marshal.FreeHGlobal(ptrNodeConnection);
                CloseHandle(h);
            }
            return new System.Collections.ObjectModel.ReadOnlyCollection<USBPort>(PortList);
        }
    }
    public class USBPort
    {
        internal int PortPortNumber;
        internal string PortStatus, PortHubDevicePath, PortSpeed;
        internal bool PortIsHub, PortIsDeviceConnected;
        internal USB_DEVICE_DESCRIPTOR PortDeviceDescriptor;
        public USBPort()
        {
            PortPortNumber = 0;
            PortStatus = "";
            PortHubDevicePath = "";
            PortSpeed = "";
            PortIsHub = false;
            PortIsDeviceConnected = false;
        }
        public int PortNumber
        {
            get { return PortPortNumber; }
        }
        public string HubDevicePath
        {
            get { return PortHubDevicePath; }
        }
        public string Status
        {
            get { return PortStatus; }
        }
        public string Speed
        {
            get { return PortSpeed; }
        }
        public bool IsHub
        {
            get { return PortIsHub; }
        }
        public bool IsDeviceConnected
        {
            get { return PortIsDeviceConnected; }
        }
        public USBDevice GetDevice()
        {
            if (!PortIsDeviceConnected)
            {
                return null;
            }
            USBDevice Device = new USBDevice();
            Device.DevicePortNumber = PortPortNumber;
            Device.DeviceHubDevicePath = PortHubDevicePath;
            Device.DeviceDescriptor = PortDeviceDescriptor;
            IntPtr h = CreateFile(PortHubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
            if (h.ToInt32() != INVALID_HANDLE_VALUE)
            {
                int nBytesReturned;
                int nBytes = BUFFER_SIZE;
                string NullString = new string((char)0, BUFFER_SIZE / Marshal.SystemDefaultCharSize);
                if (PortDeviceDescriptor.iManufacturer > 0)
                {
                    USB_DESCRIPTOR_REQUEST Request = new USB_DESCRIPTOR_REQUEST();
                    Request.ConnectionIndex = PortPortNumber;
                    Request.SetupPacket.wValue = (short)((USB_STRING_DESCRIPTOR_TYPE << 8) + PortDeviceDescriptor.iManufacturer);
                    Request.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(Request));
                    Request.SetupPacket.wIndex = 0x409;
                    IntPtr ptrRequest = Marshal.StringToHGlobalAuto(NullString);
                    Marshal.StructureToPtr(Request, ptrRequest, true);
                    if (DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        IntPtr ptrStringDesc = new IntPtr(ptrRequest.ToInt32() + Marshal.SizeOf(Request));
                        USB_STRING_DESCRIPTOR StringDesc = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
                        Device.DeviceManufacturer = StringDesc.bString;
                    }
                    Marshal.FreeHGlobal(ptrRequest);
                }
                if (PortDeviceDescriptor.iProduct > 0)
                {
                    USB_DESCRIPTOR_REQUEST Request = new USB_DESCRIPTOR_REQUEST();
                    Request.ConnectionIndex = PortPortNumber;
                    Request.SetupPacket.wValue = (short)((USB_STRING_DESCRIPTOR_TYPE << 8) + PortDeviceDescriptor.iProduct);
                    Request.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(Request));
                    Request.SetupPacket.wIndex = 0x409;
                    IntPtr ptrRequest = Marshal.StringToHGlobalAuto(NullString);
                    Marshal.StructureToPtr(Request, ptrRequest, true);
                    if (DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        IntPtr ptrStringDesc = new IntPtr(ptrRequest.ToInt32() + Marshal.SizeOf(Request));
                        USB_STRING_DESCRIPTOR StringDesc = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
                        Device.DeviceProduct = StringDesc.bString;
                    }
                    Marshal.FreeHGlobal(ptrRequest);
                }
                if (PortDeviceDescriptor.iSerialNumber > 0)
                {
                    USB_DESCRIPTOR_REQUEST Request = new USB_DESCRIPTOR_REQUEST();
                    Request.ConnectionIndex = PortPortNumber;
                    Request.SetupPacket.wValue = (short)((USB_STRING_DESCRIPTOR_TYPE << 8) + PortDeviceDescriptor.iSerialNumber);
                    Request.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(Request));
                    Request.SetupPacket.wIndex = 0x409;
                    IntPtr ptrRequest = Marshal.StringToHGlobalAuto(NullString);
                    Marshal.StructureToPtr(Request, ptrRequest, true);
                    if (DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        IntPtr ptrStringDesc = new IntPtr(ptrRequest.ToInt32() + Marshal.SizeOf(Request));
                        USB_STRING_DESCRIPTOR StringDesc = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
                        Device.DeviceSerialNumber = StringDesc.bString;
                    }
                    Marshal.FreeHGlobal(ptrRequest);
                }
                USB_NODE_CONNECTION_DRIVERKEY_NAME DriverKey = new USB_NODE_CONNECTION_DRIVERKEY_NAME();
                DriverKey.ConnectionIndex = PortPortNumber;
                nBytes = Marshal.SizeOf(DriverKey);
                IntPtr ptrDriverKey = Marshal.AllocHGlobal(nBytes);
                Marshal.StructureToPtr(DriverKey, ptrDriverKey, true);
                if (DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ptrDriverKey, nBytes, ptrDriverKey, nBytes, out nBytesReturned, IntPtr.Zero))
                {
                    DriverKey = (USB_NODE_CONNECTION_DRIVERKEY_NAME)Marshal.PtrToStructure(ptrDriverKey, typeof(USB_NODE_CONNECTION_DRIVERKEY_NAME));
                    Device.DeviceDriverKey = DriverKey.DriverKeyName;

                    Device.DeviceName = GetDescriptionByKeyName(Device.DeviceDriverKey);
                    Device.DeviceInstanceID = GetInstanceIDByKeyName(Device.DeviceDriverKey);
                }
                Marshal.FreeHGlobal(ptrDriverKey);
                CloseHandle(h);
            }
            return Device;
        }
        public USBHub GetHub()
        {
            if (!PortIsHub)
            {
                return null;
            }
            USBHub Hub = new USBHub();
            IntPtr h, h2;
            Hub.HubIsRootHub = false;
            Hub.HubDeviceDesc = "External Hub";
            h = CreateFile(PortHubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
            if (h.ToInt32() != INVALID_HANDLE_VALUE)
            {
                int nBytesReturned;
                USB_NODE_CONNECTION_NAME NodeName = new USB_NODE_CONNECTION_NAME();
                NodeName.ConnectionIndex = PortPortNumber;
                int nBytes = Marshal.SizeOf(NodeName);
                IntPtr ptrNodeName = Marshal.AllocHGlobal(nBytes);
                Marshal.StructureToPtr(NodeName, ptrNodeName, true);
                if (DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_NAME, ptrNodeName, nBytes, ptrNodeName, nBytes, out nBytesReturned, IntPtr.Zero))
                {
                    NodeName = (USB_NODE_CONNECTION_NAME)Marshal.PtrToStructure(ptrNodeName, typeof(USB_NODE_CONNECTION_NAME));
                    Hub.HubDevicePath = @"\\.\" + NodeName.NodeName;
                }
                h2 = CreateFile(Hub.HubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
                if (h2.ToInt32() != INVALID_HANDLE_VALUE)
                {
                    USB_NODE_INFORMATION NodeInfo = new USB_NODE_INFORMATION();
                    NodeInfo.NodeType = (int)USB_HUB_NODE.UsbHub;
                    nBytes = Marshal.SizeOf(NodeInfo);
                    IntPtr ptrNodeInfo = Marshal.AllocHGlobal(nBytes);
                    Marshal.StructureToPtr(NodeInfo, ptrNodeInfo, true);
                    if (DeviceIoControl(h2, IOCTL_USB_GET_NODE_INFORMATION, ptrNodeInfo, nBytes, ptrNodeInfo, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        NodeInfo = (USB_NODE_INFORMATION)Marshal.PtrToStructure(ptrNodeInfo, typeof(USB_NODE_INFORMATION));
                        Hub.HubIsBusPowered = Convert.ToBoolean(NodeInfo.HubInformation.HubIsBusPowered);
                        Hub.HubPortCount = NodeInfo.HubInformation.HubDescriptor.bNumberOfPorts;
                    }
                    Marshal.FreeHGlobal(ptrNodeInfo);
                    CloseHandle(h2);
                }
                USBDevice Device = GetDevice();
                Hub.HubInstanceID = Device.DeviceInstanceID;
                Hub.HubManufacturer = Device.Manufacturer;
                Hub.HubProduct = Device.Product;
                Hub.HubSerialNumber = Device.SerialNumber;
                Hub.HubDriverKey = Device.DriverKey;
                Marshal.FreeHGlobal(ptrNodeName);
                CloseHandle(h);
            }
            return Hub;
        }
    }
    public class USBDevice
    {
        internal int DevicePortNumber;
        internal string DeviceDriverKey, DeviceHubDevicePath, DeviceInstanceID, DeviceName;
        internal string DeviceManufacturer, DeviceProduct, DeviceSerialNumber;
        internal USB_DEVICE_DESCRIPTOR DeviceDescriptor;
        public USBDevice()
        {
            DevicePortNumber = 0;
            DeviceHubDevicePath = "";
            DeviceDriverKey = "";
            DeviceManufacturer = "";
            DeviceProduct = "Unknown USB Device";
            DeviceSerialNumber = "";
            DeviceName = "";
            DeviceInstanceID = "";
        }
        public int PortNumber
        {
            get { return DevicePortNumber; }
        }
        public string HubDevicePath
        {
            get { return DeviceHubDevicePath; }
        }
        public string DriverKey
        {
            get { return DeviceDriverKey; }
        }
        public string InstanceID
        {
            get { return DeviceInstanceID; }
        }
        public string Name
        {
            get { return DeviceName; }
        }
        public string Manufacturer
        {
            get { return DeviceManufacturer; }
        }
        public string Product
        {
            get { return DeviceProduct; }
        }
        public string SerialNumber
        {
            get { return DeviceSerialNumber; }
        }
    }
    static string GetDescriptionByKeyName(string DriverKeyName)
    {
        string ans = "";
        string DevEnum = REGSTR_KEY_USB;
        IntPtr h = SetupDiGetClassDevs(0, DevEnum, IntPtr.Zero, DIGCF_PRESENT | DIGCF_ALLCLASSES);
        if (h.ToInt32() != INVALID_HANDLE_VALUE)
        {
            IntPtr ptrBuf = Marshal.AllocHGlobal(BUFFER_SIZE);
            string KeyName;
            bool Success;
            int i = 0;
            do
            {
                SP_DEVINFO_DATA da = new SP_DEVINFO_DATA();
                da.cbSize = Marshal.SizeOf(da);
                Success = SetupDiEnumDeviceInfo(h, i, ref da);
                if (Success)
                {
                    int RequiredSize = 0;
                    int RegType = REG_SZ;
                    KeyName = "";
                    if (SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DRIVER, ref RegType, ptrBuf, BUFFER_SIZE, ref RequiredSize))
                    {
                        KeyName = Marshal.PtrToStringAuto(ptrBuf);
                    }
                    if (KeyName == DriverKeyName)
                    {
                        if (SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DEVICEDESC, ref RegType, ptrBuf, BUFFER_SIZE, ref RequiredSize))
                        {
                            ans = Marshal.PtrToStringAuto(ptrBuf);
                        }
                        break;
                    }
                }
                i++;
            } while (Success);
            Marshal.FreeHGlobal(ptrBuf);
            SetupDiDestroyDeviceInfoList(h);
        }
        return ans;
    }
    static string GetInstanceIDByKeyName(string DriverKeyName)
    {
        string ans = "";
        string DevEnum = REGSTR_KEY_USB;
        IntPtr h = SetupDiGetClassDevs(0, DevEnum, IntPtr.Zero, DIGCF_PRESENT | DIGCF_ALLCLASSES);
        if (h.ToInt32() != INVALID_HANDLE_VALUE)
        {
            IntPtr ptrBuf = Marshal.AllocHGlobal(BUFFER_SIZE);
            string KeyName;
            bool Success;
            int i = 0;
            do
            {
                SP_DEVINFO_DATA da = new SP_DEVINFO_DATA();
                da.cbSize = Marshal.SizeOf(da);
                Success = SetupDiEnumDeviceInfo(h, i, ref da);
                if (Success)
                {
                    int RequiredSize = 0;
                    int RegType = REG_SZ;
                    KeyName = "";
                    if (SetupDiGetDeviceRegistryProperty(h, ref da, SPDRP_DRIVER, ref RegType, ptrBuf, BUFFER_SIZE, ref RequiredSize))
                    {
                        KeyName = Marshal.PtrToStringAuto(ptrBuf);
                    }
                    if (KeyName == DriverKeyName)
                    {
                        int nBytes = BUFFER_SIZE;
                        StringBuilder sb = new StringBuilder(nBytes);
                        SetupDiGetDeviceInstanceId(h, ref da, sb, nBytes, out RequiredSize);
                        ans = sb.ToString();
                        break;
                    }
                }
                i++;
            } while (Success);
            Marshal.FreeHGlobal(ptrBuf);
            SetupDiDestroyDeviceInfoList(h);
        }
        return ans;
    }
}