当使用Windows API枚举端口时,如何获取扩展端口信息?

问题描述 投票:0回答:1

我正在使用一些遗留的代码来枚举我的机器上的端口。

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

#include <string>
#include <iostream>
#include <assert.h>

bool GetTextProperty( std::string& sProperty, 
                      HDEVINFO dev, 
                      _SP_DEVINFO_DATA* pDeviceInfoData,
                      DWORD prop )
{
    char szBuf[MAX_PATH];
    DWORD iPropertySize = 0;
    if (SetupDiGetDeviceRegistryProperty(dev, pDeviceInfoData,
                                         prop, 0L, (PBYTE) szBuf, MAX_PATH, &iPropertySize))
    {
        sProperty = szBuf;
        assert( iPropertySize >= sProperty.size() + 1 );
        return true;
    }     
    return false;
}

inline bool readRegistryKeyValue( HKEY hKey, const std::string& key, std::string& value )
{
    bool res = false;
    CHAR szBuffer[512];
    DWORD dwBufferSize = sizeof(szBuffer);
    ULONG nError = RegQueryValueEx(hKey, key.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
    if (ERROR_SUCCESS == nError)
    {
        value = szBuffer;
        res = true;
    }
    return res;
}

void ListPorts()
{
    HDEVINFO        hDevInfo;
    SP_DEVINFO_DATA DeviceInfoData;
    DWORD           i;

    hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0L, 0L, DIGCF_PRESENT);
    if ( hDevInfo == INVALID_HANDLE_VALUE )
    {
        //Medoc_ReportError(MEDOC_ERROR_HARDWARE_DRIVER_API_FAILED,
        //                  &hDevInfo, sizeof hDevInfo);
        assert( false );
    }
    else
    {
        // Enumerate through all devices in Set.
        DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
        for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData) != 0; i++)
        {
            char szBuf[MAX_PATH];
            short wImageIdx   = 0;
            short wItem       = 0;
            DWORD iPropertySize;

            if (SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData,
                                                 SPDRP_FRIENDLYNAME, 0L, (PBYTE) szBuf, MAX_PATH, &iPropertySize))
            {
                std::cout << "Smart name: " << szBuf << std::endl;

                HKEY hKey = SetupDiOpenDevRegKey(
                                hDevInfo,
                                &DeviceInfoData,
                                DICS_FLAG_GLOBAL,
                                0,
                                DIREG_DEV,
                                KEY_READ );
                if ( hKey )
                {
                    std::string portName;
                    readRegistryKeyValue( hKey, "PortName", portName );
                    std::cout << "Port name: " << szBuf << std::endl;

                    for ( DWORD prop = 0; prop != SPDRP_MAXIMUM_PROPERTY; ++prop )
                    {
                        std::string temp;
                        GetTextProperty( temp, hDevInfo, &DeviceInfoData, prop );
                        std::cout << prop << " : " << temp << std::endl;
                    }

                    RegCloseKey(hKey);
                }
            }            
        }
    }

    // Cleanup
    SetupDiDestroyDeviceInfoList(hDevInfo);
}

int main( int argc, char* argv[] )
{
    ListPorts();
    return 0;
}

在其他信息中,它给了我访问端口名(COM*)、类型(例如FTDI)。VIDPID...

然而,当我有许多不同的设备基于FTDI芯片插入,他们都有相同的信息(SPDRP_HARDWAREID 房产报告 FTDIBUS\COMPORT&VID_0403&PID_6015FTDIBUS\COMPORT&VID_0403&PID_6010). 所以我无法辨别谁是谁。

当我使用USB sniffer("Device Monitoring Studio")时,这个可以在不建立任何端口连接的情况下报告更多相关信息。

enter image description here

这种扩展信息是否可以通过Windows API访问,以区分使用同一FTDI芯片的多个设备的名称?还是必须使用FTDI驱动API才能实现?

c++ windows winapi usb ftdi
1个回答
1
投票

在Ben Voigt和Simon Mourier的帮助下,我实现了这个目标,这是一段代码。

// More includes:
#include <initguid.h>
#include <devpkey.h>
#include <cfgmgr32.h>
// A new dependency:
#pragma comment (lib, "Cfgmgr32.lib")

bool GetDeviceProperty( const std::string& what, 
                        DEVINST dev, 
                        DEVPROPKEY prop )
{
    char szDeviceBuf[MAX_PATH];
    DEVPROPTYPE type;
    ULONG iDevicePropertySize = MAX_PATH;
    if ( CM_Get_DevNode_PropertyW(dev,
                                  &prop,
                                  &type,
                                  (PBYTE) szDeviceBuf,
                                  &iDevicePropertySize,
                                  0) == CR_SUCCESS )
    {
        wchar_t* txt = (wchar_t*) szDeviceBuf;
        std::wstring ws(txt);
        std::cout << what << " : " << std::string(ws.begin(), ws.end()) << std::endl;
        return true;
    }
    else
    {
        return false;
    }
}

void ListPorts()
{
        ...

                DEVINST devInstParent;
                auto status = CM_Get_Parent(&devInstParent, DeviceInfoData.DevInst, 0);
                if (status == CR_SUCCESS) 
                {
                    ShowDeviceProperty( "Bus reported device description", devInstParent, DEVPKEY_Device_BusReportedDeviceDesc );
                    ShowDeviceProperty( "Device description", devInstParent, DEVPKEY_Device_DeviceDesc );
                }
                else 
                {
                    continue;
                }

        ...
© www.soinside.com 2019 - 2024. All rights reserved.