Accessing Multiple USB-Serial Devices using the Device Instance Path – KBA228257

Version 5

    Version: **

     

    Translation - Japanese: デバイス インスタンス パスを使用した複数のUSBシリアル デバイスへのアクセス – KBA228257- Community Translated (JA)

     

    Question:

    How can a USB Serial Device be accessed when multiple devices are connected?

     

    Answer:

    When a USB-Serial part configured as I2C, SPI, or UART in vendor mode is connected to USB host, one or more devices will be enumerated based on the configuration.

    Windows OS will assign a specific device enumeration index for each device during the device enumeration process. Also, this USB device enumeration process will create a unique Device Instance Path for every USB device. This Device Instance Path can be used to differentiate the devices with the same VID and PID by mapping the instance path of a device to its respective device enumeration index, with the help of the function defined in this article.

    The GetDevicePath() function, defined below, takes the device enumeration index of a Cypress Device as a parameter, similar to the CyOpen and CyGetDeviceInfo APIs, and prints the Device Instance Path of that device using windows APIs.

     

     

    Note: The setupapi library should be linked to the project. You can do this by adding setupapi.lib to the property page Linker Input Additional Dependencies.

     

    Code:

     

    // Additional header file to be added

    #include <setupapi.h>

     

    // GetDevicePath Function

     

    void GetDevicePath(int deviceNumber)

    {

           //Initialization

           GUID CyDrvGuid = { 0xae18aa60, 0x7f6a, 0x11d4, 0x97, 0xdd, 0x0, 0x1, 0x2, 0x29, 0xb9, 0x59 };   // cyusb3 guid

           SP_DEVINFO_DATA devInfoData;

           SP_DEVICE_INTERFACE_DATA  devInterfaceData;

           PSP_INTERFACE_DEVICE_DETAIL_DATA functionClassDeviceData;

           ULONG requiredLength = 0;

           HDEVINFO hwDeviceInfo = SetupDiGetClassDevs((LPGUID)& CyDrvGuid,   //Returns a handle to the device information set

                  NULL,

                  NULL,

                  DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);

           if (hwDeviceInfo != INVALID_HANDLE_VALUE) { //checks if the handle is invalid

                  devInterfaceData.cbSize = sizeof(devInterfaceData);         //get the size of devInterfaceData structure

     

                  //enumerates the device interfaces that are contained in a device information set

                  if (SetupDiEnumDeviceInterfaces(hwDeviceInfo, 0, (LPGUID)& CyDrvGuid,     

                         deviceNumber, &devInterfaceData)) {                                   

     

                         SetupDiGetInterfaceDeviceDetail(hwDeviceInfo, &devInterfaceData, NULL, 0,

                         &requiredLength, NULL);

                         ULONG predictedLength = requiredLength;

                         functionClassDeviceData = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(predictedLength);

                         functionClassDeviceData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

                         devInfoData.cbSize = sizeof(devInfoData);

     

                         //Retrieve the information from Plug and Play including the device path

                         if (SetupDiGetInterfaceDeviceDetail(hwDeviceInfo,

                       &devInterfaceData,

                       functionClassDeviceData,

                       predictedLength,

                       &requiredLength,

                       &devInfoData)) {

                       wprintf(L"%ls\n", functionClassDeviceData->DevicePath); //Prints the device path of the required device

                         }

                  }

           }

     

           SetupDiDestroyDeviceInfoList(hwDeviceInfo);

    }