none
How do I retreive a USB "Bus reported device description" RRS feed

  • Question

  • In Device Manager >> Ports (COM & LPT) >> USB Serial Device (COMxx) >> Properties - Details Tab >> Property Bus reported device description, I can see the Value.

    I would like to find a way using Visual Basic to retrieve this value.

    On the web, I found "find objects in Win32_PnPEntity, then enumerate through the getDeviceProperties to find the "bus reported device description".  I have been able to find object in Win32_PnPEntity but need help getting the bus reported device description. Thanks, Ken

    Tuesday, November 26, 2019 6:38 PM

Answers

  • I am having to switch to another project by will mark this as answered since you did answer my original question and gave me enough info that should allow me to get the rest of the info I was looking for i.e. connected COM port.

    Thanks again for your help.  Ken

    • Marked as answer by bwanaken Wednesday, December 4, 2019 7:01 PM
    Wednesday, December 4, 2019 7:01 PM

All replies

  • SetupDi APIs (P/Invoke) and DEVPKEY_Device_BusReportedDeviceDesc
    Tuesday, November 26, 2019 8:28 PM
  • Thanks for your reply.  I am not familiar with using APIs so I need a bit more help.

    Here is some code that provides most of the info except for the "bus reported device description".

    ' See if the desired device shows up in the device manager.'
                Dim info As Management.ManagementObject
                Dim search As System.Management.ManagementObjectSearcher
                Dim Name As String
    
                search = New System.Management.ManagementObjectSearcher("SELECT * From Win32_PnPEntity")
                For Each info In search.Get()
                    ' Go through each device detected.'
                    Name = CType(info("Caption"), String) ' Get the name of the device.'
                    Dim ID As String = CType(info("DeviceID"), String)
                    Dim Description As String = CType(info("Description"), String)
                    Dim Desc As String = CType(info("Manufacturer"), String)
                    Dim misc As String = CType(info("SystemName"), String)
    
                    If InStr(info.Path.ToString, "USB\\") Then
    
                        ' USB devise found
                        If InStr(Name, "(COM") Then Console.WriteLine(Name + " " + ID)
    
                        ' use DEVPKEY_Device_BusReportedDeviceDesc and SetupDiGetDevicePropertyW
                        ' to get "bus reported device description"
                        Dim BusReportedDevDesc As String
    
                        ' I still need help with this
                        'BusReportedDevDesc = ??
    
                    End If
    
                Next

    Once the USB port is identified, how do I use that info to get the "bus reported device description"?

    Thanks, Ken


    Tuesday, November 26, 2019 10:05 PM
  • For example  =>

    (change sGuid variable by the Guid you want

    I declared 4 Guids for this test , like GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, but you can add others)

    Dim DEVPKEY_Device_DeviceDesc As DEVPROPKEY
    Dim DEVPKEY_Device_FriendlyName As DEVPROPKEY
    Dim DEVPKEY_Device_BusReportedDeviceDesc As DEVPROPKEY


    DEVPKEY_Device_DeviceDesc = New DEVPROPKEY()
    DEVPKEY_Device_DeviceDesc.fmtid = New Guid("A45C254E-DF1C-4EFD-8020-67D146A850E0")
    DEVPKEY_Device_DeviceDesc.pid = 2
    
    DEVPKEY_Device_FriendlyName = New DEVPROPKEY()
    DEVPKEY_Device_FriendlyName.fmtid = New Guid("A45C254E-DF1C-4EFD-8020-67D146A850E0")
    DEVPKEY_Device_FriendlyName.pid = 14
    
    DEVPKEY_Device_BusReportedDeviceDesc = New DEVPROPKEY()
    DEVPKEY_Device_BusReportedDeviceDesc.fmtid = New Guid("540B947E-8B40-45BC-A8A2-6A0B894CBDA2")
    DEVPKEY_Device_BusReportedDeviceDesc.pid = 4
    
    Dim GUID_DEVINTERFACE_USB_DEVICE As New Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED")
    Dim GUID_DEVINTERFACE_USB_HOST_CONTROLLER As New Guid("3ABF6F2D-71C4-462a-8A92-1E6861E6AF27")
    Dim GUID_DEVINTERFACE_USB_HUB As New Guid("f18a0e88-c30c-11d0-8815-00a0c906bed8")
    
    Dim GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR As New Guid("4D36E978-E325-11CE-BFC1-08002BE10318")
    
    Dim sGuid As Guid = GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
    Dim hdevDisplayInfoSet As IntPtr = SetupDiGetClassDevs(sGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT Or DIGCF_DEVICEINTERFACE)
    If (hdevDisplayInfoSet <> IntPtr.Zero) Then
        Dim data As SP_DEVICE_INTERFACE_DATA = New SP_DEVICE_INTERFACE_DATA()
        Dim nStatus As Integer = 0
        Dim i As Integer = 0
        Dim b As Boolean = False
        While (nStatus = 0)
            data.cbSize = Marshal.SizeOf(GetType(SP_DEVICE_INTERFACE_DATA))
            b = SetupDiEnumDeviceInterfaces(hdevDisplayInfoSet, IntPtr.Zero, sGuid, i, data)
            If (Not b) Then
                nStatus = Marshal.GetLastWin32Error()
                Exit While
            End If
            Dim dwBytes As UInteger = 0
            Dim bRet As Boolean = SetupDiGetDeviceInterfaceDetail(hdevDisplayInfoSet, data, IntPtr.Zero, 0, dwBytes, IntPtr.Zero)
            nStatus = Marshal.GetLastWin32Error()
            If (Not bRet And Marshal.GetLastWin32Error() = ERROR_INSUFFICIENT_BUFFER) Then
                Dim didd As SP_DEVICE_INTERFACE_DETAIL_DATA = New SP_DEVICE_INTERFACE_DETAIL_DATA()
                Dim nSize = 4 + If(IntPtr.Size = 4, 2, 4)
                didd.cbSize = nSize
                Dim da As SP_DEVINFO_DATA = New SP_DEVINFO_DATA()
                da.cbSize = Marshal.SizeOf(da)
                bRet = SetupDiGetDeviceInterfaceDetail(hdevDisplayInfoSet, data, didd, dwBytes, dwBytes, da)
                If (bRet) Then
                    Console.WriteLine("Device Path: {0}", didd.DevicePath)
    
                    Dim nRequiredSize As UInteger = 0
                    Dim nCharSize As Integer = 260 * Marshal.SystemDefaultCharSize
                    Dim pBuffer As IntPtr = Marshal.AllocHGlobal(nCharSize)
                    Dim nPropertyType As UInteger = 0
                    bRet = SetupDiGetDeviceProperty(hdevDisplayInfoSet, da, DEVPKEY_Device_DeviceDesc, nPropertyType, pBuffer, nCharSize, nRequiredSize, 0)
                    If (bRet <> 0) Then
                        Dim sDeviceDesc As String = Marshal.PtrToStringUni(pBuffer)
                        Console.WriteLine("Description : {0}", sDeviceDesc)
                    Else
                        Dim nError As Integer = Marshal.GetLastWin32Error()
                    End If
                    Marshal.FreeHGlobal(pBuffer)
    
                    pBuffer = Marshal.AllocHGlobal(nCharSize)
                    bRet = SetupDiGetDeviceProperty(hdevDisplayInfoSet, da, DEVPKEY_Device_BusReportedDeviceDesc, nPropertyType, pBuffer, nCharSize, nRequiredSize, 0)
                    If (bRet <> 0) Then
                        Dim sReportedDeviceDesc As String = Marshal.PtrToStringUni(pBuffer)
                        Console.WriteLine("Reported Device Desc : {0}", sReportedDeviceDesc)
                    Else
                        'ERROR_NOT_FOUND  1168(0x490)
                        Dim nError As Integer = Marshal.GetLastWin32Error()
                    End If
                    Marshal.FreeHGlobal(pBuffer)
    
                    nStatus = 0
                    Console.WriteLine("")
                End If
            End If
            i += 1
        End While
        SetupDiDestroyDeviceInfoList(hdevDisplayInfoSet)
    End If


    Declarations :

       <DllImport("Setupapi.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
        Public Shared Function SetupDiGetClassDevs(ByRef ClassGuid As Guid, ByVal Enumerator As IntPtr, ByVal hWndParent As IntPtr, ByVal Flags As Integer) As IntPtr
        End Function
    
        <DllImport("Setupapi.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
        Private Shared Function SetupDiEnumDeviceInterfaces(ByVal DeviceInfoSet As IntPtr, ByVal DeviceInfoData As IntPtr, ByRef InterfaceClassGuid As Guid, ByVal MemberIndex As Integer, ByRef DeviceInterfaceData As SP_DEVICE_INTERFACE_DATA) As Boolean
        End Function
    
        <DllImport("Setupapi.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
        Public Shared Function SetupDiDestroyDeviceInfoList(ByVal DeviceInfoSet As IntPtr) As Boolean
        End Function
    
        <DllImport("Setupapi.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
        Public Shared Function SetupDiGetDeviceProperty(ByVal deviceInfoSet As IntPtr, <[In]> ByRef DeviceInfoData As SP_DEVINFO_DATA, <[In]> ByRef propertyKey As DEVPROPKEY, <Out> ByRef propertyType As UInteger, ByVal propertyBuffer As IntPtr, ByVal propertyBufferSize As UInteger, <Out> ByRef requiredSize As UInteger, ByVal flags As UInteger) As Boolean
        End Function
    
        <StructLayout(LayoutKind.Sequential)>
        Public Structure DEVPROPKEY
            Public fmtid As Guid
            Public pid As UInteger
        End Structure
        
        <DllImport("Setupapi.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
        Public Shared Function SetupDiGetDeviceInterfaceDetail(ByVal hDevInfo As IntPtr, ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA, ByVal deviceInterfaceDetailData As IntPtr, ByVal deviceInterfaceDetailDataSize As UInt32, <System.Runtime.InteropServices.Out()> ByRef requiredSize As UInt32, ByVal deviceInfoData As IntPtr) As Boolean
        End Function
    
        <DllImport("Setupapi.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
        Public Shared Function SetupDiGetDeviceInterfaceDetail(ByVal hDevInfo As IntPtr, ByRef deviceInterfaceData As SP_DEVICE_INTERFACE_DATA, ByRef deviceInterfaceDetailData As SP_DEVICE_INTERFACE_DETAIL_DATA, ByVal deviceInterfaceDetailDataSize As UInt32, <System.Runtime.InteropServices.Out()> ByRef requiredSize As UInt32, ByRef deviceInfoData As SP_DEVINFO_DATA) As Boolean
        End Function
    
        Public Const DIGCF_PRESENT As Integer = &H2
        Public Const DIGCF_DEVICEINTERFACE As Integer = &H10
        Public Const ERROR_INSUFFICIENT_BUFFER As Integer = 122
    
        <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
        Public Structure SP_DEVINFO_DATA
            Public cbSize As Integer
            Public ClassGuid As Guid
            Public DevInst As Integer
            Public Reserved As IntPtr
        End Structure
    
        <StructLayout(LayoutKind.Sequential)>
        Structure SP_DEVICE_INTERFACE_DATA
            Public cbSize As Integer
            Public InterfaceClassGuid As Guid
            Public Flags As Integer
            Public Reserved As IntPtr
        End Structure
    
        <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode, Pack:=1)>
        Structure SP_DEVICE_INTERFACE_DETAIL_DATA
            Public cbSize As Integer
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)>
            Public DevicePath As String
        End Structure



    • Edited by Castorix31 Wednesday, November 27, 2019 10:00 AM
    Wednesday, November 27, 2019 9:53 AM
  • Castorix31,

    Thanks for the detailed help.  I managed to get the code to compile but it is not working and I suspect because I change the following line:

    Dim nSize = 4 + If(IntPtr.Size = 4, 2, 4)

    I could not understand what the code was doing so I commented out the rest of the line after the "+" sign.

    Dim nSize = 4 '+ If(IntPtr.Size = 4, 2, 4)

    Please let me know what I should have put for this line.

    Thanks, Ken

    Wednesday, November 27, 2019 10:37 PM
  • Don't change the line, it is a test to change the size if it is compiled in x86 or x64
    Thursday, November 28, 2019 7:52 AM
  • I could not get the line below to compile on my system so I re-wrote it long hand and got it to work.

    Dim nSize = 4 + If(IntPtr.Size = 4, 2, 4)

    The code show me the reported device description for all COM port that I was looking for.

    Question: Is it possible to extract the COM port i.e. COM3, COM24 etc associated with the device?

    Device Path: \\?\usb#vid_...
    Description : USB Serial Port
    Reported Device Desc : PDMS

    Port: COM5 <----------------- add this?

    If the code is not too complicated, could you please show me how?

    Thanks, Ken

    Friday, November 29, 2019 4:14 PM
  • Question: Is it possible to extract the COM port i.e. COM3, COM24 etc associated with the device?

    You can add :

    Dim hKey As IntPtr = SetupDiOpenDevRegKey(hdevDisplayInfoSet, da, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE)
    If (hKey <> CType(INVALID_HANDLE_VALUE, IntPtr)) Then
        Dim sbPort As StringBuilder = New StringBuilder(256)
        Dim nType As Integer = 0
        Dim nPortSize As Integer = sbPort.Capacity()
        Dim sPortName As String = "Not filled"
        Dim nRet As Integer = RegQueryValueEx(hKey, "PortName", 0, nType, sbPort, nPortSize)
        If (nRet = 0) Then
            sPortName = sbPort.ToString()
        End If
        RegCloseKey(hKey)
        Console.WriteLine("Port Name : {0}", sPortName)
    End If

    With declarations :

    <DllImport("Setupapi.dll", SetLastError:=True)>
    Public Shared Function SetupDiOpenDevRegKey(ByVal DeviceInfoSet As IntPtr, ByRef DeviceInfoData As SP_DEVINFO_DATA, Scope As Integer, HwProfile As Integer, KeyType As Integer, samDesired As Integer) As IntPtr
    End Function
    
    Public Const DICS_FLAG_GLOBAL = &H1 ' make change In all hardware profiles
    Public Const DICS_FLAG_CONFIGSPECIFIC = &H2 ' make change In specified profile only
    Public Const DICS_FLAG_CONFIGGENERAL = &H4 ' 1 Or more hardware profile-specific changes to follow.
    
    Public Const DIREG_DEV = &H1 ' Open / Create / Delete device key
    Public Const DIREG_DRV = &H2 ' Open / Create / Delete driver key
    Public Const DIREG_BOTH = &H4 ' Delete both driver And Device key
    
    Public Const KEY_QUERY_VALUE = &H1
    Public Const KEY_SET_VALUE = &H2
    
    Public Const INVALID_HANDLE_VALUE = -1
    
    <DllImport("Advapi32.dll", SetLastError:=True)>
    Public Shared Function RegCloseKey(hKey As IntPtr) As Integer
    End Function
    
    <DllImport("Advapi32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
    Public Shared Function RegQueryValueEx(hKey As IntPtr, lpValueName As String, lpReserved As Integer, ByRef lpType As Integer, lpData As StringBuilder, ByRef lpcbData As Integer) As Integer
    End Function

    Friday, November 29, 2019 5:50 PM
  • Thanks for the code.

    I have 5 USB serial ports connected however the code only finds a COM port for 2 of the 5.

    Here is the console output with your latest code running:

    -----------------

    Device Path: \\?\usb#vid_0403&pid_6015#db1g7t2l#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

    Description : USB Serial Converter

    Reported Device Desc : AlarmLinc V1.1

    Port Name : Not filled

     

    Device Path: \\?\usb#vid_0403&pid_6001#ft1xglo3#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

    Description : USB Serial Converter

    Reported Device Desc : USB-COM485 Plus1

    Port Name : Not filled

     

    Device Path: \\?\usb#vid_04d8&pid_0e30#s#n:_00100#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

    Description : USB Serial Device

    Reported Device Desc : PWS-100

    Port Name : COM30

     

    Device Path: \\?\usb#vid_0403&pid_6001#psn:jsi_rdu-01#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

    Description : USB Serial Converter

    Reported Device Desc : USB-RS485 Cable

    Port Name : Not filled

     

    Device Path: \\?\usb#vid_04d8&pid_000a#psn:jsi_pws-01#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

    Description : USB Serial Port

    Reported Device Desc : PWS-100

    Port Name : COM31

    -----------------

    You have been a great help so far.  Any suggestions for getting the COM port number for all USB devices?

    Thanks, Ken

    Friday, November 29, 2019 7:01 PM
  • I have only 1 COM1 port, so I cannot do real tests

    You can try to debug to check if the nRet value returned from RegQueryValueEx

    is really = 2 (ERROR_FILE_NOT_FOUND) when it is not filled

    Friday, November 29, 2019 8:15 PM
  • Yes, for the devices that do not report a COM port, nRet=2.

    Some devices reporting nRet=2 are other usb devices such as the keyboard and mouse but other are valid ub COM ports.

    Any suggestions?

    Thanks, ken

    Tuesday, December 3, 2019 4:54 PM
  • You can check if you find them in the registry in other keys.

    For my COM1, which works, it is :

    Tuesday, December 3, 2019 5:33 PM
  • I am having to switch to another project by will mark this as answered since you did answer my original question and gave me enough info that should allow me to get the rest of the info I was looking for i.e. connected COM port.

    Thanks again for your help.  Ken

    • Marked as answer by bwanaken Wednesday, December 4, 2019 7:01 PM
    Wednesday, December 4, 2019 7:01 PM