Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect if device is using USB 3.0

Tags:

c#

.net

usb

Does anyone know a way to detect if a USB device connected to a USB 3.0 host port is running at 3.0 or 2.0 using C#?

We are manufacturing USB 3.0 extension cables and we need to verify that all the pins have been soldered correctly. We would like to do this in software. We would like to connect a 3.0 thumb drive to the cable and check if the device is operating in USB 3.0 mode. If it is in 2.0 mode, we know their is a problem with 1 or more of the USB 3.0 lines.

like image 733
Stonewall_Jefferson Avatar asked Apr 04 '13 19:04

Stonewall_Jefferson


1 Answers

I've managed to cook up a working demo with the help of some source code 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

The application enumerates the USB Host Controllers. Then it gets the Root Hub and enumarates the ports belonging to it. If there is a device connected and it's not a hub then it displays the required information.

In your case you probably know which device you want to check so you can modify the source (both the above and the linked code) to specifically check only that device.

You'll need to create a method in the USB class to get a specific port from a specific hub by specifying port number and the path to the hub.

Something like:

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

and the call it with the appropriate values:

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

If you however are reluctant to do this then you can simply use the above code and make notice of the serial number of the device you want to test and only check the speed then:

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

If you are to use this in an application with a GUI you could just select the device you want to check in a dropdown.

Well... There are some thoughts and hopefully a working solution.

Addendum

For the sake of longevity I'll include the modified classes I used for the demo.
(Comments and empty lines removed due to SO limitations on 30000 characters):

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;
    }
}
like image 61
Sani Singh Huttunen Avatar answered Oct 16 '22 03:10

Sani Singh Huttunen