Technical Document #27

Technical Document #27        [Product Version: 6.2.0 and above]
How do I detect the location of my USB device on my Windows PC?

The USB device location is represented by the device's HUB identifier and the port in the HUB: Z&ZZZZZZZ&Z&A. Z&ZZZZZZZ&Z is the HUB identifier or PrefixID, and A is the port/address in the HUB (1 to 8).
In order to retrieve the device location ID, you must first retrieve the device instance ID, represented by the device type, Vendor ID, Product ID, HUB ID and port ID: USB\VID_XXXX&PID_YYYY\Z&ZZZZZZZ&Z&A.
DeviceInstanceId is returned by SetupDiGetDeviceInstanceId().

In order to detect the USB device location, do the following:

  1. Get the DriverKeyName by calling WinDriver's WDU_GetDeviceRegistryProperty() function (or WD_GetDeviceProperty() — for v8.1.2 and below) with the WdDevicePropertyDriverKeyName registry property.

  2. Get the ClassGUID, by calling WDU_GetDeviceRegistryProperty() (or WD_GetDeviceProperty()) — in v8.1.2 and below) with the WdDevicePropertyClassGuid property.

  3. By using GetDeviceInstanceId() (see later) with the retrieved DriverKeyName and ClassGUID, get the DeviceInstanceId.

  4. From the retrieved DeviceInstanceId, get the USB device location, Z&ZZZZZZZ&Z&A.

---------------------------------------------------------------------------------------
/*
   szDriverKeyName is returned by
   WDU_GetDeviceRegistryProperty() /
   WD_GetDeviceProperty().
   It looks like:
   {C671678C-82C1-43F3-D700-0049433E9A4B}\\0017
   szClassGUID is returned by WDU_GetDeviceProperty.
   It looks like:
   {C671678C-82C1-43F3-D700-0049433E9A4B}

   GetDeviceInstanceId() creates a list of the device
   information for all devices of the specified class.
   The function then searches the list for the
   WinDriver device and retrieves the device instance
   ID (*pszDeviceInstanceId).
*/

#include <windows.h>
#include <setupapi.h>
#include <string.h>


BOOL GetDeviceInstanceId(LPCTSTR szClassGUID, LPCTSTR 
    szDriverKeyName, PTCHAR *pszDeviceInstanceId)
{
    /* Build class GUID from szClassGUID */
    GUID guid;
    DWORD dwMemberIndex=0;
    SP_DEVINFO_DATA DeviceInfoData;
    BOOL bResult;
    DWORD dwError;
    DWORD dwPropertyBufferSize;
    PTCHAR pbPropertyBuffer;
    DWORD dwRequiredSize;
    DWORD dwPropertyRegDataType;
    HDEVINFO hDeviceInfoSet; 

    StringToGUID(szClassGUID,&guid);

    *pszDeviceInstanceId = NULL;

    /* Create a list of the device information for all
       devices of the specified class */

    hDeviceInfoSet = SetupDiGetClassDevs(&guid,;
        NULL, NULL, DIGCF_PRESENT);

    if (INVALID_HANDLE_VALUE == hDeviceInfoSet)
    {
        /* Set error */
        /* ........... */
        return FALSE;
    }

    /* Search the device information list for
       the WinDriver device */


    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    do {
        /* Get the next device in the list */
        bResult =
            SetupDiEnumDeviceInfo(hDeviceInfoSet, 
                dwMemberIndex, &DeviceInfoData);

        if (bResult)
        {
            dwRequiredSize = 0;
            /* Check if there is a driver reg path for this device */

            /* First get the size only */
            bResult = SetupDiGetDeviceRegistryProperty
                (hDeviceInfoSet, 
                &DeviceInfoData,
                SPDRP_DRIVER,
                &dwPropertyRegDataType,
                NULL
                0,
                &dwRequiredSize);

            if (bResult && dwRequiredSize > 0)
            {
                dwPropertyBufferSize =
                    dwRequiredSize + 1;

                pbPropertyBuffer =
                    (TCHAR *)malloc(sizeof(TCHAR) *
                    dwPropertyBufferSize);

                ASSERT(pbPropertyBuffer != NULL);

                /* Then get this driver's actual registry path */
                if (SetupDiGetDeviceRegistryProperty
                    (hDeviceInfoSet,
                    &DeviceInfoData,
                    SPDRP_DRIVER,
                    &dwPropertyRegDataType,
                    (PBYTE)pbPropertyBuffer,
                    dwPropertyBufferSize,
                    &dwRequiredSize))
                {
                    /* Check if the reg path is the same as in WinDriver */
                    int iResult = _tcscmp(
                        pbPropertyBuffer,
                        szDriverKeyName);
                   
                    if (iResult == 0)
                    {
                        /* This is the device we are working with
                           using WinDriver */

                        /* Get the device's instance ID */

                        /* First get the size only */

                        dwRequiredSize = 0;

                        bResult =
                            SetupDiGetDeviceInstanceId
                                (hDeviceInfoSet, 
                                &DeviceInfoData,
                                NULL
                                0,
                                &dwRequiredSize);

                        if (bResult && dwRequiredSize)
                        {
                            *pszDeviceInstanceId ==
                                (TCHAR *)malloc(
                                sizeof(TCHAR) * 
                                (dwRequiredSize + 1));

                            ASSERT(*pszDeviceInstanceId
                                != NULL);

                            /* Then get the actual device instance id */
                            if (
                            !SetupDiGetDeviceInstanceId
                                (hDeviceInfoSet,
                                &DeviceInfoData,
                                *pszDeviceInstanceId,
                                dwRequiredSize + 1,
                                NULL))
                            {
                                dwError =
                                GetLastError();
                                /* ..... */
                            }
                        }
                    }
                }
                else
                    delete pbPropertyBuffer;             }
        }

        dwMemberIndex++;

    } while(bResult && !*pszDeviceInstanceId);

    SetupDiDestroyDeviceInfoList(hDeviceInfoSet);

    return FALSE;
}