Hardware Enumeration Using SetupAPI.DLL - Discussion

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts
  • josnan petrel
    Member
    • Dec 2012
    • 104

    Hardware Enumeration Using SetupAPI.DLL - Discussion

    ...This thread is for discussion of Pierre's post.

    Hello Pierre
    can be get all information of a guid
    Last edited by Gary Beene; 19 Apr 2015, 12:55 AM.
  • Pierre Bellisle
    Member
    • Dec 2001
    • 5282

    #2
    ¡Hola Josnan,

    Can you give an example of what information you want to get?

    Pierre

    Comment

    • Ken Deitz
      Member
      • Mar 2010
      • 5

      #3
      finding the serial com port number by USB device serial number

      Mr. Bellisle, I found some of this code of yours but it does not seem to list the COM# as a "drive letter".

      Code:
      'Get USB device serial number by Pierre Bellisle 2011-10-25
      
      #COMPILE EXE '#Win 8.04#
      #DIM ALL
      #INCLUDE "Win32Api.inc"
      
      %USB_STRING_DESCRIPTOR_TYPE =   3
      %USB_REQUEST_GET_DESCRIPTOR =   6
      %MAXIMUM_USB_STRING_LENGTH  = 255
      %DEVICECONNECTED            =   1
      
      %FILE_DEVICE_UNKNOWN        =  34
      %FILE_DEVICE_USB            = %FILE_DEVICE_UNKNOWN
      %METHOD_BUFFERED            =   0
      %FILE_ANY_ACCESS            =   0
      
      %IOCTL_USB_GET_NODE_CONNECTION_NAME            = &H00220414
      %IOCTL_GET_HCD_DRIVERKEY_NAME                  = &H00220424
      %IOCTL_USB_GET_NODE_INFORMATION                = &H00220408
      %IOCTL_USB_GET_ROOT_HUB_NAME                   = &H00220408
      %IOCTL_USB_GET_NODE_CONNECTION_INFORMATION     = &H0022040C
      %IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION = &H00220410
      
      TYPE USB_DEVICE_DESCRIPTOR 'Packet.Data 1 - USB_CONFIGURATION_DESCRIPTOR_TYPE
       bLength            AS BYTE 'Specifies the length, in bytes, of this descriptor.
       bDescriptorType    AS BYTE 'Specifies the descriptor type. Must be set to USB_DEVICE_DESCRIPTOR_TYPE (1).
       bcdUSB             AS WORD 'Identifies the version of the USB specification that this descriptor structure complies with. This value is a binary-coded decimal number.
       bDeviceClass       AS BYTE 'Specifies the class code of the device as assigned by the USB specification group.
       bDeviceSubClass    AS BYTE 'Specifies the subclass code of the device as assigned by the USB specification group.
       bDeviceProtocol    AS BYTE 'Specifies the protocol code of the device as assigned by the USB specification group.
       bMaxPacketSize0    AS BYTE 'Specifies the maximum packet size, in bytes, for endpoint zero of the device. The value must be set to 8, 16, 32, or 64.
       idVendor           AS WORD 'Specifies the vendor identifier for the device as assigned by the USB specification committee.
       idProduct          AS WORD 'Specifies the product identifier. This value is assigned by the manufacturer and is device-specific.
       bcdDevice          AS WORD 'Identifies the version of the device. This value is a binary-coded decimal number.
       iManufacturer      AS BYTE 'Specifies a device-defined index of the string descriptor that provides a string containing the name of the manufacturer of this device.
       iProduct           AS BYTE 'Specifies a device-defined index of the string descriptor that provides a string that contains a description of the device.
       iSerialNumber      AS BYTE 'Specifies a device-defined index of the string descriptor that provides a string that contains a manufacturer-determined serial number for the device.
       bNumConfigurations AS BYTE 'Specifies the total number of possible configurations for the device.
      END TYPE
      
      TYPE USB_ENDPOINT_DESCRIPTOR 'Packet.Data 5 - USB_CONFIGURATION_DESCRIPTOR_TYPE
       bLength          AS BYTE 'Specifies the length, in bytes, of this descriptor.
       bDescriptorType  AS BYTE 'Specifies the descriptor type. Must be set to USB_ENDPOINT_DESCRIPTOR_TYPE.
       bEndpointAddress AS BYTE 'Specifies the USB-defined endpoint address. The four low-order bits specify the endpoint number. The high-order bit specifies the direction of data flow on this endpoint: 1 for in, 0 for out.
       bmAttributes     AS BYTE 'The two low-order bits specify the endpoint type, one of USB_ENDPOINT_TYPE_CONTROL, USB_ENDPOINT_TYPE_ISOCHRONOUS, USB_ENDPOINT_TYPE_BULK, or USB_ENDPOINT_TYPE_INTERRUPT.
       wMaxPacketSize   AS WORD 'Specifies the maximum packet size that can be sent from or to this endpoint.
       bInterval        AS BYTE 'For interrupt endpoints, bInterval contains the polling interval. For other types of endpoint, this value should be ignored. This value reflects the device's configuration in firmware. Drivers cannot change it.
      END TYPE
      
      TYPE USB_COMMON_DESCRIPTOR 'Packet.Data header - USB_CONFIGURATION_DESCRIPTOR_TYPE
       bLength         AS BYTE  'Lenght in bytes of the descriptor.
       bDescriptorType AS BYTE  'The descriptor type. 1 for USB_DEVICE_DESCRIPTOR, 2 for USB_CONFIGURATION_DESCRIPTOR, 4 for USB_INTERFACE_DESCRIPTOR, 5 for USB_ENDPOINT_DESCRIPTOR, 33 for HID_DESCRIPTOR.
      END TYPE
      
      TYPE SETUP_PACKET
       bmRequest AS BYTE 'The type of USB device request, standard, class, or vendor
       bRequest  AS BYTE '0x06 value indicates a request of GET_DESCRIPTOR.
       wValue    AS WORD 'Type of descriptor to retrieve in the high byte of wValue and the descriptor index in the low byte.
       wIndex    AS WORD 'The device-specific index of the descriptor that is to be retrieved.
       wLength   AS WORD 'The length of the data that is transferred during the second phase of the control transfer.
      END TYPE
      
      TYPE USB_DESCRIPTOR_REQUEST
       ConnectionIndex AS LONG                                'The port whose descriptors are retrieved.
       SETUP_PACKET                                           'See SETUP_PACKET type.
       DATA            AS STRING * %MAXIMUM_USB_STRING_LENGTH 'On output from the IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION I/O control request, this member contains the retrieved descriptors.
      END TYPE
      
      TYPE USB_HUB_DESCRIPTOR
       bDescriptorLength   AS BYTE        'The length, in bytes of the descriptor.
       bDescriptorType     AS BYTE        'The descriptor type. For hub descriptors, this value should be 0x29.
       bNumberOfPorts      AS BYTE        'The number of ports on the hub.
       wHubCharacteristics AS WORD        'The hub characteristics. For more information about this member, see Universal Serial Bus Specification.
       bPowerOnToPowerGood AS BYTE        'The time, in 2-millisecond intervals, that it takes the device to turn on completely. For more information about this member, see Universal Serial Bus Specification.
       bHubControlCurrent  AS BYTE        'The maximum current requirements, in milliamperes, of the controller component of the hub.
       bRemoveAndPowerMask AS STRING * 65 'Not currently implemented. Do not use this member. This member implements DeviceRemovable and PortPwrCtrlMask fields of the hub descriptor. For more information about these fields, see Universal Serial Bus
      '                                    Specification.
      END TYPE
      
      TYPE USB_HUB_NODE
       UsbHub      AS WORD 'Indicates that the device is a hub.
       UsbMIParent AS WORD 'Indicates that the device is a composite device with multiple interfaces.
      END TYPE
      
      TYPE USB_HUB_INFORMATION
       HubDescriptor   AS USB_HUB_DESCRIPTOR 'A USB_HUB_DESCRIPTOR structure that contains selected information from the hub descriptor.
       HubIsBusPowered AS LONG               'A Boolean value that indicates whether the hub is powered. If TRUE, the hub is powered. If FALSE, the hub is not powered.
      END TYPE
      
      TYPE USB_MI_PARENT_INFORMATION
       NumberOfInterfaces AS LONG 'The number of interfaces on the composite device.
      END TYPE
      
      UNION USB_NODE_INFORMATION_UNION
       HubInformation      AS USB_HUB_INFORMATION       'A USB_HUB_INFORMATION structure that contains information about a parent hub device.
       MiParentInformation AS USB_MI_PARENT_INFORMATION 'A USB_MI_PARENT_INFORMATION structure that contains information about a parent non-hub, composite device.
      END UNION
      
      TYPE USB_NODE_INFORMATION
       NodeType AS USB_HUB_NODE   'A USB_HUB_NODE enumerator that indicates whether the parent device is a hub or a non-hub composite device.
       USB_NODE_INFORMATION_UNION 'See USB_NODE_INFORMATION_UNION union
      END TYPE
      
      TYPE USB_HCD_DRIVERKEY_NAME
       ActualLength  AS DWORD                               'The length, in bytes, of the string in the DriverKeyName member.
       DriverKeyName AS STRING * %MAXIMUM_USB_STRING_LENGTH 'wChar array, a NULL-terminated Unicode driver key name for the USB host controller.
      END TYPE
      
      TYPE USB_NODE_CONNECTION_NAME
       ConnectionIndex AS LONG                                 'A value that is greater than or equal to 1 that specifies the number of the port to which the hub is attached.
       ActualLength    AS LONG                                 'The length, in bytes, of the attached hub's symbolic link.
       NAME            AS STRING * %MAXIMUM_USB_STRING_LENGTH  'A Unicode symbolic link for the downstream hub that is attached to the port that is indicated by ConnectionIndex.
      END TYPE
      
      TYPE USB_PIPE_INFO
       EndpointDescriptor AS USB_ENDPOINT_DESCRIPTOR 'See USB_ENDPOINT_DESCRIPTOR type
       ScheduleOffset     AS DWORD                   'Indicates the schedule offset assigned to the endpoint for this pipe.
      END TYPE
      
      TYPE USB_NODE_CONNECTION_INFORMATION
       ConnectionIndex           AS LONG                  'A value that is greater than or equal to 1 that specifies the number of the port.
       DeviceDescriptor          AS USB_DEVICE_DESCRIPTOR 'A USB_DEVICE_DESCRIPTOR structure that reports the USB device descriptor that is returned by the attached device during enumeration.
       CurrentConfigurationValue AS BYTE                  'Value used with SetConfiguration request to specify that current configuration of the device that is connected to the indicated port. See Universal Serial Bus Specification.
       LowSpeed                  AS BYTE                  'If TRUE, the port and its connected device are currently operating at a low speed.
       DeviceIsHub               AS BYTE                  'Value that indicates if the device that is attached to the port is a hub. If TRUE, the device that is attached to the port is a hub. If FALSE, the device is not a hub.
       DeviceAddress             AS WORD                  'The USB-assigned, bus-relative address of the device that is attached to the port.
       NumberOfOpenPipes         AS DWORD                 'The number of open USB pipes that are associated with the port.
       ConnectionStatus          AS DWORD                 'A USB_CONNECTION_STATUS-typed enumerator that indicates the connection status.
       PipeList(1 TO 32)         AS USB_PIPE_INFO         'An array of USB_PIPE_INFO structures that describes the open pipes that are associated with the port.
      END TYPE
      
      TYPE USB_LANGUAGE_ID
       bLength         AS BYTE 'Size of Descriptor in Bytes
       bDescriptorType AS BYTE 'Constant, string Descriptor (0x03)
       wLangId(0)      AS WORD 'First of an array of language id
      END TYPE                                            'Pipe descriptions include the schedule offset of the pipe and the associated endpoint descriptor. This information can be used to calculate bandwidth usage.
      '______________________________________________________________________________
      
      FUNCTION regDosDevidesGet(BYREF sDosDevicesArray() AS STRING) AS LONG
       LOCAL Retval         AS LONG
       LOCAL hKey           AS DWORD
       LOCAL ValueLen       AS DWORD
       LOCAL DataLen        AS DWORD
       LOCAL dwRegType      AS DWORD
       LOCAL dwValueCount   AS DWORD
       LOCAL DosDeviceCount AS DWORD
       LOCAL zValueName     AS ASCIIZ * %MAX_PATH
       LOCAL sData          AS STRING * %MAX_PATH
      
       Retval = RegOpenKeyEx(%HKEY_LOCAL_MACHINE, "SYSTEM\MountedDevices", BYVAL %NULL, %KEY_READ, hKey)
       IF Retval = %ERROR_SUCCESS THEN
         dwValueCount = 0
         DosDeviceCount = 0
         DO
           ValueLen = %MAX_PATH
           DataLen = %MAX_PATH
           Retval = RegEnumValue(hKey, dwValueCount, zValueName, ValueLen, _
                                 BYVAL %Null, dwRegType, sData, DataLen)
           IF Retval = %ERROR_NO_MORE_ITEMS THEN Retval = %ERROR_SUCCESS : EXIT DO
           IF LCASE$(LEFT$(zValueName, 12)) = "\dosdevices\" THEN
             IF DataLen > 12 THEN
               REDIM PRESERVE sDosDevicesArray(0 TO DosDeviceCount) AS STRING
               sDosDevicesArray(DosDeviceCount) = RIGHT$(zValueName, 2) & ACODE$(LEFT$(sData, DataLen)) 'If unicode
               INCR DosDeviceCount
             END IF
           END IF
           INCR dwValueCount
         LOOP WHILE Retval = %ERROR_SUCCESS
         RegCloseKey(hKey)
       END IF
       FUNCTION = DosDeviceCount
      
      END FUNCTION
      '______________________________________________________________________________
      
      FUNCTION usbDeviceLanguageId(BYVAL hHub AS DWORD, BYVAL PortIndex AS LONG, BYREF LanguageIdArray() AS WORD)AS LONG
       LOCAL Request         AS USB_DESCRIPTOR_REQUEST
       LOCAL pUsbLanguageId  AS USB_LANGUAGE_ID POINTER
       LOCAL BytesReturned   AS DWORD
       LOCAL LanguageIdCount AS LONG
       LOCAL Success         AS LONG
      
       IF LanguageIdArray(1) = 0 THEN 'Get the languages ids
         Request.ConnectionIndex = PortIndex
         Request.bmRequest       = &H80
         Request.bRequest        = %USB_REQUEST_GET_DESCRIPTOR
         Request.wValue          = MAK(WORD, 0, %USB_STRING_DESCRIPTOR_TYPE) 'No Index here
         Request.wLength         = %MAXIMUM_USB_STRING_LENGTH '3 * 256 '4 'LanguageIdArray(1) size = 4, 1033
         Success = DeviceIoControl(hHub, %IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, _
                                   BYVAL VARPTR(Request), SIZEOF(Request), _
                                   BYVAL VARPTR(Request), SIZEOF(Request), BytesReturned, BYVAL %NULL)
         IF Success THEN
           pUsbLanguageId = VARPTR(Request.Data)
           IF @pUsbLanguageId.bDescriptorType = 3 THEN 'Constant, string Descriptor = 3
             LanguageIdCount = (@pUsbLanguageId.bLength \ 2) - 1
             DIM LanguageIdArrayFromIo(1 TO LanguageIdCount) AS WORD AT VARPTR(Request.Data) + 2
             REDIM LanguageIdArray(1 TO LanguageIdCount)
             COPYMEMORY(BYVAL VARPTR(LanguageIdArray(1)), BYVAL VARPTR(LanguageIdArrayFromIo(1)), LanguageIdCount * 2)
      
             LOCAL sBuffer   AS STRING
             LOCAL zLanguage AS ASCIIZ * %MAX_PATH
             LOCAL Looper    AS LONG
             FOR Looper = 1 TO LanguageIdCount
              sBuffer = sBuffer & "0x" & HEX$(LanguageIdArray(Looper), 4) & " (" & FORMAT$(LanguageIdArray(Looper)) & ") "
               GetLocaleInfo MAK(DWORD, LanguageIdArray(Looper), %SORT_DEFAULT), %LOCALE_SENGLANGUAGE, zLanguage, %MAX_PATH
               sBuffer = sBuffer & zLanguage & " ("
               GetLocaleInfo MAK(DWORD, LanguageIdArray(Looper), %SORT_DEFAULT), %LOCALE_SENGCOUNTRY, zLanguage, %MAX_PATH
               sBuffer = sBuffer & zLanguage &  "), "
               GetLocaleInfo MAK(DWORD, LanguageIdArray(Looper), %SORT_DEFAULT), %LOCALE_SLANGUAGE, zLanguage, %MAX_PATH
               sBuffer = sBuffer & zLanguage & $CRLF
             NEXT
             PRINT sBuffer
           END IF
         END IF
       END IF
      
      END FUNCTION
      '______________________________________________________________________________
      
      FUNCTION usbDeviceString(BYVAL hHub AS DWORD, BYVAL PortIndex AS LONG, BYVAL Index AS BYTE)AS STRING
       LOCAL Request                 AS USB_DESCRIPTOR_REQUEST
       LOCAL pBuffer                 AS USB_COMMON_DESCRIPTOR POINTER
       LOCAL sBuffer                 AS STRING
       LOCAL BytesReturned           AS DWORD
       LOCAL StringLen               AS LONG
       LOCAL Success                 AS LONG
       DIM   LanguageIdArray(1 TO 1) AS WORD
      
       usbDeviceLanguageId(hHub, PortIndex, LanguageIdArray())
      
       Request.ConnectionIndex = PortIndex
       Request.bmRequest       = &H80
       Request.bRequest        = %USB_REQUEST_GET_DESCRIPTOR
       Request.wValue          = MAK(WORD, Index, %USB_STRING_DESCRIPTOR_TYPE)
       Request.wIndex          = LanguageIdArray(1) 'Use only the first one
       Request.wLength         = %MAXIMUM_USB_STRING_LENGTH
      
       Success = DeviceIoControl(hHub, %IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, _
                                 BYVAL VARPTR(Request), SIZEOF(Request), _
                                 BYVAL VARPTR(Request), SIZEOF(Request), BytesReturned, BYVAL %NULL)
       IF Success THEN
         pBuffer = VARPTR(Request.DATA)
         StringLen = @pBuffer.bLength
         sBuffer = ACODE$(MID$(Request.DATA, 3, StringLen - 2))
         sBuffer = RTRIM$(sBuffer, ANY $SPC & $NUL)
         IF sBuffer = "" THEN sBuffer = "None" 'Descriptor is blank
         FUNCTION = sBuffer
       ELSE
         FUNCTION = "None" 'No string descriptor returned
       END IF
      
      END FUNCTION
      '______________________________________________________________________________
      
      FUNCTION usbDeviceInfo(BYVAL hHub AS DWORD, BYVAL PortIndex AS LONG, _
                             BYVAL pBuffer AS USB_DEVICE_DESCRIPTOR POINTER, BYREF sDosDevicesArray() AS STRING)AS STRING
       LOCAL sManufacturer   AS STRING
       LOCAL sProduct        AS STRING
       LOCAL sDiskSerial     AS STRING
       LOCAL sTry            AS STRING
       LOCAL sDrive          AS STRING
       LOCAL zVolume         AS ASCIIZ * 50
       LOCAL zVolumeSerial   AS ASCIIZ * 10
       LOCAL zFileSystem     AS ASCIIZ * 10
       LOCAL FileSystemFlags AS DWORD
       LOCAL VolumeSerial    AS DWORD
       LOCAL MaxLenFileName  AS LONG
       LOCAL Looper          AS LONG
       LOCAL CharPos         AS LONG
      
       sManufacturer = usbDeviceString(hHub, PortIndex, @pBuffer.iManufacturer)
       sProduct      = usbDeviceString(hHub, PortIndex, @pBuffer.iProduct)
       sDiskSerial   = usbDeviceString(hHub, PortIndex, @pBuffer.iSerialNumber)
       sDrive        = "None"
      
       FOR Looper = 0 TO UBOUND(sDosDevicesArray())
         zVolume       = "-"
         zFileSystem   = "-"
         zVolumeSerial = "-"
      
         sTry = LCASE$(sManufacturer)
      ?sTry
         REPLACE $SPC WITH "_" IN sTry
         IF (sTry = "none") OR (sTry = "generic") OR (sTry = "?") THEN sTry = "&ven_"
         CharPos = INSTR(LCASE$(sDosDevicesArray(Looper)), sTry)
         IF CharPos THEN
           sTry = LCASE$(sProduct)
           REPLACE $SPC WITH "_" IN sTry
           IF (sTry = "none") OR (sTry = "mass_storage")  OR (sTry = "usb_mass_storage") THEN sTry = "&prod_"
           CharPos = INSTR(CharPos, LCASE$(sDosDevicesArray(Looper)), sTry)
           IF CharPos THEN
             sTry = LCASE$(sDiskSerial) & "&0"
             REPLACE $SPC WITH "_" IN sTry
             CharPos = INSTR(CharPos, LCASE$(sDosDevicesArray(Looper)), sTry)
             IF CharPos THEN
               sDrive = LEFT$(sDosDevicesArray(Looper), 2)
               ? sDrive
               GetVolumeInformation(BYVAL STRPTR(sDrive), zVolume, SIZEOF(zVolume), VolumeSerial, MaxLenFileName, _
                                    FileSystemFlags, zFileSystem, SIZEOF(zFileSystem))
               zVolumeSerial = LEFT$(HEX$(VolumeSerial), 4) & "-" & RIGHT$(HEX$(VolumeSerial), 4)
               IF LEN(zVolume) = 0 THEN zVolume = "None"
               EXIT FOR
             END IF
           END IF
         END IF
       NEXT
      
       FUNCTION = "id Vendor    " & $TAB & "0x" & HEX$(@pBuffer.idVendor, 4)  & $CRLF & _
                  "id Product   " & $TAB & "0x" & HEX$(@pBuffer.idProduct, 4) & $CRLF & _
                  "Manufacturer " & $TAB & sManufacturer                      & $CRLF & _
                  "Product      " & $TAB & sProduct                           & $CRLF & _
                  "SerialNumber " & $TAB & sDiskSerial                        & $CRLF & _
                  "Drive letter " & $TAB & sDrive                             & $CRLF & _
                  "Volume       " & $TAB & zVolume                            & $CRLF & _
                  "Volume Serial" & $TAB & zVolumeSerial                      & $CRLF & _
                  "FileSystem   " & $TAB & zFileSystem                        & $CRLF & $CRLF
      
      END FUNCTION
      '______________________________________________________________________________
      
      SUB usbPortEnum(BYVAL hHub AS DWORD, BYVAL PortCount AS BYTE, BYVAL HubDepth AS BYTE, _
                      BYREF sBuffer AS STRING, BYREF sDosDevicesArray() AS STRING)
       LOCAL  ConnectionInformation AS USB_NODE_CONNECTION_INFORMATION
       LOCAL  NodeInformation       AS USB_NODE_INFORMATION
       LOCAL  NodeConnection        AS USB_NODE_CONNECTION_NAME
       LOCAL  SecurityAttr          AS SECURITY_ATTRIBUTES 'Needed for Win2000
       LOCAL  NodeConnectionName    AS ASCIIZ * %MAXIMUM_USB_STRING_LENGTH
       LOCAL  sDeviceInfo           AS STRING
       LOCAL  hNodeConnection       AS DWORD
       LOCAL  BytesReturned         AS DWORD
       LOCAL  Success               AS LONG
       LOCAL  PortIndex             AS LONG
       LOCAL  HubWanted             AS LONG
      
       SecurityAttr.nLength              = SIZEOF(SECURITY_ATTRIBUTES)
       SecurityAttr.lpSecurityDescriptor = 0
       SecurityAttr.bInheritHandle       = %FALSE
      
       FOR PortIndex = 1 TO PortCount 'Iterate each ports and see what is connected
         ConnectionInformation.ConnectionIndex = PortIndex
      
         Success = DeviceIoControl(hHub, %IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, _
                                   BYVAL VARPTR(ConnectionInformation), SIZEOF(ConnectionInformation), _
                                   BYVAL VARPTR(ConnectionInformation), SIZEOF(ConnectionInformation), _
                                   BytesReturned, BYVAL %NULL)
         IF Success THEN
           IF ConnectionInformation.ConnectionStatus = %DEVICECONNECTED THEN
             IF ConnectionInformation.DeviceIsHub THEN 'It's a HUB, we need to iterate his ports.
               NodeConnection.ConnectionIndex = PortIndex
               Success = DeviceIoControl(hHub, %IOCTL_USB_GET_NODE_CONNECTION_NAME, _
                                         BYVAL VARPTR(NodeConnection), SIZEOF(NodeConnection), _
                                         BYVAL VARPTR(NodeConnection), SIZEOF(NodeConnection), _
                                         BytesReturned, BYVAL %NULL)
               IF Success THEN
                 NodeConnectionName = ACODE$(LEFT$(NodeConnection.NAME, NodeConnection.ActualLength))
                 NodeConnectionName = "\\.\" & NodeConnectionName
                 hNodeConnection = CreateFile(NodeConnectionName, %GENERIC_READ, %FILE_SHARE_READ, _
                                              SecurityAttr, %OPEN_EXISTING, 0, BYVAL %NULL)
                 Success = DeviceIoControl(hNodeConnection, %IOCTL_USB_GET_NODE_INFORMATION, _
                                           BYVAL VARPTR(NodeInformation), SIZEOF(NodeInformation), _
                                           BYVAL VARPTR(NodeInformation), SIZEOF(NodeInformation), _
                                           BytesReturned, BYVAL %NULL)
                 IF Success THEN
                   HubWanted = %FALSE
                   IF HubWanted THEN
                     sBuffer = sBuffer & usbDeviceInfo(hHub, PortIndex, VARPTR(ConnectionInformation.DeviceDescriptor), _
                                                       BYREF sDosDevicesArray())
                   ELSE
                     usbDeviceInfo(hHub, PortIndex, VARPTR(ConnectionInformation.DeviceDescriptor), _
                                   BYREF sDosDevicesArray())
                   END IF
                   'Recursive function call
                   usbPortEnum(hNodeConnection, NodeInformation.HubInformation.HubDescriptor.bNumberOfPorts, _
                               HubDepth + 1, sBuffer, sDosDevicesArray())
                 END IF
                 CloseHandle(hNodeConnection)
               END IF
             ELSE
               sDeviceInfo = usbDeviceInfo(hHub, PortIndex, VARPTR(ConnectionInformation.DeviceDescriptor), _
                                           BYREF sDosDevicesArray())
               sBuffer = sBuffer & sDeviceInfo
             END IF
           END IF
         END IF
       NEXT
      
      END SUB
      '______________________________________________________________________________
      
      SUB usbHostControllerInfo(BYVAL hHostController AS DWORD, BYREF sBuffer AS STRING, BYREF sDosDevicesArray()AS STRING)
       LOCAL SecurityAttr             AS SECURITY_ATTRIBUTES 'Needed for Win2000
       LOCAL NodeInformation          AS USB_NODE_INFORMATION
       LOCAL DriverKeyName            AS USB_HCD_DRIVERKEY_NAME
       LOCAL RootHubName              AS ASCIIZ * %MAXIMUM_USB_STRING_LENGTH
       LOCAL hRootHub                 AS DWORD
       LOCAL BytesReturned            AS LONG
       LOCAL Success                  AS LONG
      
       SecurityAttr.nLength              = SIZEOF(SECURITY_ATTRIBUTES)
       SecurityAttr.lpSecurityDescriptor = 0
       SecurityAttr.bInheritHandle       = %FALSE
      
       Success = DeviceIoControl(hHostController, %IOCTL_GET_HCD_DRIVERKEY_NAME, _
                                 BYVAL VARPTR(DriverKeyName), SIZEOF(DriverKeyName), _
                                 BYVAL VARPTR(DriverKeyName), SIZEOF(DriverKeyName), _
                                 BytesReturned, BYVAL %NULL)
       IF Success THEN
         Success = DeviceIoControl(hHostController, %IOCTL_USB_GET_ROOT_HUB_NAME, _
                                   BYVAL VARPTR(DriverKeyName), SIZEOF(DriverKeyName), _
                                   BYVAL VARPTR(DriverKeyName), SIZEOF(DriverKeyName), _
                                   BytesReturned, BYVAL %NULL)
         IF Success THEN
           RootHubName = ACODE$(LEFT$(DriverKeyName.DriverKeyName, DriverKeyName.ActualLength))
           RootHubName = "\\.\" & RootHubName
           hRootHub = CreateFile(RootHubName, %GENERIC_READ, %FILE_SHARE_READ, _
                                 SecurityAttr, %OPEN_EXISTING, BYVAL %NULL, BYVAL %NULL)
           IF hRootHub <> %INVALID_HANDLE_VALUE THEN
             Success = DeviceIoControl(hRootHub, %IOCTL_USB_GET_NODE_INFORMATION, _
                                       BYVAL VARPTR(NodeInformation), SIZEOF(NodeInformation), _
                                       BYVAL VARPTR(NodeInformation), SIZEOF(NodeInformation), _
                                       BytesReturned, BYVAL %NULL)
             IF Success THEN
               usbPortEnum(hRootHub, NodeInformation.HubInformation.HubDescriptor.bNumberOfPorts, _
                           0, sBuffer, sDosDevicesArray())
               CloseHandle(hRootHub)
             END IF
           END IF
         END IF
       END IF
      
      END SUB
      '______________________________________________________________________________
      
      FUNCTION UsbDeviceSerialNumberGet() AS STRING
       LOCAL SecurityAttr             AS SECURITY_ATTRIBUTES 'Needed for Win2000
       LOCAL HostControllerName       AS ASCIIZ * 12
       LOCAL sBuffer                  AS STRING
       DIM   sDosDevicesArray(0 TO 0) AS STRING
       LOCAL hHostController          AS DWORD
       LOCAL Looper                   AS LONG
       LOCAL DosDeviceCount           AS DWORD
      
       SecurityAttr.nLength              = SIZEOF(SECURITY_ATTRIBUTES)
       SecurityAttr.lpSecurityDescriptor = 0
       SecurityAttr.bInheritHandle       = %FALSE
      
       DosDeviceCount = regDosDevidesGet(sDosDevicesArray())
      
       FOR Looper = 0 TO 25
         HostControllerName = "\\.\HCD" & FORMAT$(Looper)
         hHostController    = CreateFile(HostControllerName, %GENERIC_READ, %FILE_SHARE_READ, _
                                         SecurityAttr, %OPEN_EXISTING, BYVAL %NULL, BYVAL %NULL)
         IF GetLastError = 0 THEN
           IF (hHostController <> %INVALID_HANDLE_VALUE) THEN
             usbHostControllerInfo(hHostController, sBuffer, sDosDevicesArray())
             CloseHandle(hHostController)
           END IF
         END IF
       NEXT
      
       FUNCTION = sBuffer
      
      END FUNCTION
      '______________________________________________________________________________
      
      FUNCTION PBMAIN
      
       MessageBox(%HWND_DESKTOP, UsbDeviceSerialNumberGet, "USB serial number", 64)
      
      END FUNCTION
      '_______________
      Last edited by Gary Beene; 19 Apr 2015, 12:54 AM.

      Comment

      • Pierre Bellisle
        Member
        • Dec 2001
        • 5282

        #4
        Hi Ken,
        If I may, usually, no question are allowed in the "Source code" forum.
        Then if you post code, it would be nice to put [code] before your code and [/code] after it to give a nice look.
        Also, no need to post the entire code, the question was all what's needed.

        Ok now,
        Quote> I found some of this code of yours but it does not seem to list the COM# as a "drive letter".
        I'm not sure to understand you.

        The Usb serial number code is to get a serial number of a USB device. Example: Most of USB memory stick have a serial number on them, like 1A945B361209.
        If I read your question, I am under the impression, because of the "COM#", that you want a drive letter from a com port, like "COM3 = F:\".
        If it's so then it won't be possible since there is no corellation between ComPort and DriveLetter.
        If it's that you have a USB memory stick and you don't get a serial number, then it may be because some memory stick, even if it's relatively rare, simply don't have serial number.
        And if it is because you don't get a DriveLetter from a USB memory stick then I will need more detail to understand whats going on.

        I will ask the gbForum gbAdministrator to gbMove this gbPart of the gbThread to... maybe "The programming forum",
        so meet you there for more talk...

        Pierre
        Last edited by Pierre Bellisle; 19 Apr 2015, 07:58 AM.

        Comment

        • Gary Beene
          Member
          • May 2008
          • 20120

          #5
          Hardware Enumeration Using SetupAPI.DLL - Discussion

          Hi Ken!
          Glad to see you posting! I added the code tags for your post.
          Last edited by Gary Beene; 19 Apr 2015, 12:56 AM.

          Comment

          • Ken Deitz
            Member
            • Mar 2010
            • 5

            #6
            restatement

            I would like to be able to simply use the code to find the COM port after extracting the device serial number as this code does, this allows me to find the com # by using the USB serial number. For example, when I plug in an ARDUINO of a known usb device serial number, I would like to be able to get the com # assigned. Is this a bit better explanation?

            Comment

            • Pierre Bellisle
              Member
              • Dec 2001
              • 5282

              #7
              Hi Ken,

              I now understand what you meant. It make perfect sense to me with the details.

              In fact I'm already doing it with an USB IR Toy.
              - I'm still waiting for my Arduino & shields to come at the post office.

              I will see if I can come up with something for you, gimme little time...

              Pierre

              Comment

              • Pierre Bellisle
                Member
                • Dec 2001
                • 5282

                #8
                Hey Ken,

                Here is something for you to play with,
                Main function of interest is UsbComPortGet.
                On my side I got only a UsbIrToy so the Arduino portion is yours to check,
                tell me if it work for you.

                Have fun

                Pierre

                UsbToComPort

                Comment

                • Cliff Nichols
                  Member
                  • Aug 2006
                  • 3753

                  #9
                  I have several postings in the source code forums involving Serial Ports such as USB Incomplete that may be of help???
                  Engineer's Motto: If it aint broke take it apart and fix it

                  "If at 1st you don't succeed... call it version 1.0"

                  "Half of Programming is coding"....."The other 90% is DEBUGGING"

                  "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                  Comment

                  • Ken Deitz
                    Member
                    • Mar 2010
                    • 5

                    #10
                    Thank you Pierre. My next problem is the callback function within the code. I have PBCC 5. Is an upgrade to PBCC 6 sufficient? I plan not to use any of the GUI stuff. The end result is intended to be command line based... UsbComPortGet 6493433313535120E0D1
                    The argument is the serial number of the arduino. I intend to place the com port it finds in the OPEN statement of more code I have written prior to this. It is intended to automate the difficulty surround the plugging of the arduino. Plug-n-Play instead of annoyance in setup. Thanks again!

                    Comment

                    • Pierre Bellisle
                      Member
                      • Dec 2001
                      • 5282

                      #11
                      Hi Ken,
                      PBCC 5 should be able to compile a working executable of this code.

                      You could get rid of the callback and do something like
                      PRINT UsbComPortGet(&h2341, &h8041, "6493433313535120E0D1") in PbMain.

                      Try to fill the VendorId and ProductId fields.
                      In my example above, 0x2341 is for Arduino, and 0x8041 is for the UNO model.

                      Pierre

                      Comment

                      Working...
                      X