使用Windows API识别USB COM设备

时间:2018-01-06 13:28:16

标签: c++11 winapi arduino

我通过WinAPI句柄连接到Arduino Uno R3。

std::string name = "COM5";
this->handle = CreateFile(name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

我如何才能安全地区分Arduino,以便我不与不同的东西进行通信或者至少得到它的名字,最好没有第三方库?经过研究后我发现了几个API(QueryDosDeviceNtQueryObject),但我不知道如何在我的代码中实现这些。

编辑:我现在能够枚举USB设备,但是我遇到了完全相反的问题。我不知道如何从这些创建文件:

EXTERN_C const DEVPROPKEY DECLSPEC_SELECTANY DEVPKEY_Device_BusReportedDeviceDesc = { { 0x540b947e, 0x8b40, 0x45bc, { 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2 } }, 4 };

typedef BOOL(WINAPI *FN_SetupDiGetDeviceProperty)(
    __in       HDEVINFO DeviceInfoSet,
    __in       PSP_DEVINFO_DATA DeviceInfoData,
    __in       const DEVPROPKEY *PropertyKey,
    __out      DEVPROPTYPE *PropertyType,
    __out_opt  PBYTE PropertyBuffer,
    __in       DWORD PropertyBufferSize,
    __out_opt  PDWORD RequiredSize,
    __in       DWORD Flags
);

std::vector<device> usbenumerator::ListDevices()
{
    DWORD dwSize;
    DEVPROPTYPE ulPropertyType;
    CONFIGRET status;
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DeviceInfoData;
    char szDeviceInstanceID[MAX_DEVICE_ID_LEN];
    WCHAR szBuffer[4096];
    FN_SetupDiGetDeviceProperty GetDeviceProperty = (FN_SetupDiGetDeviceProperty)(GetProcAddress(GetModuleHandle("setupapi.dll"), "SetupDiGetDevicePropertyW"));

    hDevInfo = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);

    std::vector<device> output;

    if (hDevInfo == INVALID_HANDLE_VALUE)
    {
        return output;
    }

    for (int i = 0; ; i++)
    {
        device dev;

        DeviceInfoData.cbSize = sizeof(DeviceInfoData);

        if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData))
        {
                break;
        }

        status = CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID, MAX_PATH, 0);

        if (status != CR_SUCCESS)
        {
            continue;
        }

        std::string deviceID = szDeviceInstanceID;
        dev.id = deviceID;

        if (GetDeviceProperty && GetDeviceProperty(hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &ulPropertyType, (BYTE*) szBuffer, sizeof(szBuffer), &dwSize, 0))
        {
            if (GetDeviceProperty(hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0))
            {
                _bstr_t b(szBuffer);
                const char* cBusReportedDesc = b;

                std::string busReportedDesc = cBusReportedDesc;
                dev.busReportedDesc = busReportedDesc;
            }
        }

        output.push_back(dev);
     }

     return output;
}

1 个答案:

答案 0 :(得分:0)

我想我明白了:我基本上是在Windows注册表中创建自己的SymbolicName键副本(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\**YOUR_DEVICE_ID**\Device Parameters,例如HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_2341&PID_0001\75633313233351E0A1E1\Device Parameters

// Error checking omitted

CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID, MAX_PATH, 0);

std::string deviceID = szDeviceInstanceID;
std::string did = deviceID;

// Convert all backslashes to hash signs
std::replace(did.begin(), did.end(), '\\', '#');

// The GUID seems to stay the same: https://docs.microsoft.com/en-us/windows-hardware/drivers/install/guid-devinterface-usb-device
std::string rid = "\\??\\" + did + "#{a5dcbf10-6530-11d2-901f-00c04fb951ed}";

handle = CreateFile(rid, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);