主要描述:UVC设备相同的情况下搜索到的信息相同,这种情况下很难区分UVC设备对应的COM口。
下面是通过用windosAPI搜索设备管理器获取COM口以及USB设备对应属性对比进行UVC设备与COM口绑定。
主要包含的头文件
#include <QMainWindow>
#include <Windows.h>
#include <vector>
#include <string>
#include <stdint.h>
#include <stdio.h>
#include <devguid.h>
#include <map>
#include <dshow.h>
#include <atlcomcli.h>
#include <SetupAPI.h>
#include <string>
#pragma comment(lib, "Setupapi.lib")
#pragma comment(lib, "Strmiids.lib")
#include <comutil.h>
#include <string>
#pragma comment(lib, "comsuppw.lib")
using namespace std;
用到的结构体容器
//存储USB设备信息
typedef struct _USB_DEV
{
string strUsbName;
string strUsbProperty;
} USB_DEV;
vector<USB_DEV> g_usbDevices;
//存储COM口信息
typedef struct _COM_DEV
{
string strComName;
string strComProperty;
} _COM_DEV;
vector<_COM_DEV> g_comDevices;
//存储USB设备与COM口对应信息
typedef struct DEVICES
{
int DevicesNum;
string strName;
string strCom;
} DEVICES;
vector<DEVICES> g_Devices;
搜索USB设备信息
void GetUsbProperty()
{
HRESULT hr;
VARIANT name;
LONGLONG start = 0, stop = MAXLONGLONG;
ICreateDevEnum* dev_enum;
IEnumMoniker* enum_moniker;
IMoniker* moniker;
IPropertyBag* pbag;
//create an enumerator for video input devices
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&dev_enum);
if (hr < 0) throw hr;
hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &enum_moniker, NULL);
if (hr < 0) throw hr;
if (hr == S_FALSE) return; //no devices found
while (enum_moniker->Next(1, &moniker, 0) == S_OK)
{
//get properties
hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pbag);
if (hr >= 0)
{
VariantInit(&name);
//get the description
hr = pbag->Read(L"Description", &name, 0);
if (hr < 0)
hr = pbag->Read(L"FriendlyName", &name, 0);
USB_DEV usb_dev;
string Str;
Str = _com_util::ConvertBSTRToString(name.bstrVal);
usb_dev.strUsbName = Str;
if (hr >= 0)
{
CComVariant vWaveInId;
if (SUCCEEDED(pbag->Read(L"DevicePath", &vWaveInId, NULL)))
{
//这里截取所用到的信息
string str = _com_util::ConvertBSTRToString(vWaveInId.bstrVal);
string strPidVid = str.substr(8, 17);
string strAdress = str.substr(33, 8);
usb_dev.strUsbProperty = strPidVid + strAdress;
g_usbDevices.push_back(usb_dev);
}
}
VariantClear(&name);
pbag->Release();
}
}
enum_moniker->Release();
dev_enum->Release();
return;
}
搜索COM口信息
void MainWindow::GetComProperty()
{
// 得到设备信息集
//GUID_DEVCLASS_PORTS对应端口
HDEVINFO hDevInfo = SetupDiGetClassDevs(
(LPGUID)&GUID_DEVCLASS_PORTS,
NULL,
0,
DIGCF_PRESENT/* | DIGCF_ALLCLASSES*/);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
printf("Error! SetupDiGetClassDevs() return %d\n", GetLastError());
SetupDiDestroyDeviceInfoList(hDevInfo);
return;
}
TCHAR szBuf[MAX_PATH];
SP_DEVINFO_DATA spDevInfoData = { sizeof(SP_DEVINFO_DATA) };
// 开始列举设备
for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
{
_COM_DEV com_dev;
// 得到设备实例的唯一标识ID(由注册表路径组成)
if (SetupDiGetDeviceInstanceId(
hDevInfo,
&spDevInfoData,
szBuf,
MAX_PATH,
NULL))
{
printf("%03d : InstanceId = %s\n", i, szBuf);
string str = TCHAR2STRING(szBuf);
string strPidVid = str.substr(4, 17);
string strAdress = str.substr(29, 8);
str = strPidVid + strAdress;
transform(str.begin(),str.end(),str.begin(), ::tolower);
com_dev.strComProperty = str;
}
// 得到设备型号
if (SetupDiGetDeviceRegistryProperty(
hDevInfo,
&spDevInfoData,
SPDRP_FRIENDLYNAME,
NULL,
(PBYTE)szBuf,
MAX_PATH,
NULL))
{
printf("%03d : FriendName = %s\n", i, szBuf);
string str = TCHAR2STRING(szBuf);
string strComName = str.substr(12);
com_dev.strComName = strComName;
g_comDevices.push_back(com_dev);
}
}
}
上面涉及到数据类型转换TCHAR2STRING函数 TCHAR转string
string TCHAR2STRING(TCHAR *STR)
{
int iLen = WideCharToMultiByte(CP_ACP, 0,STR, -1, NULL, 0, NULL, NULL);
char* chRtn =new char[iLen*sizeof(char)];
WideCharToMultiByte(CP_ACP, 0, STR, -1, chRtn, iLen, NULL, NULL);
std::string str(chRtn);
return str;
}
然后将得到的信息对比得到对应关系存储在结构体容器中
void UCContarst()
{
int num = 0;
for (int i = 0; i < g_usbDevices.size();i++)
{
for (int j = 0; j < g_comDevices.size(); j++)
{
if (g_usbDevices[i].strUsbProperty == g_comDevices[j].strComProperty)
{
DEVICES devices;
devices.DevicesNum = num;
devices.strCom = g_comDevices[j].strComName;
devices.strName = g_usbDevices[i].strUsbName;
g_Devices.push_back(devices);
num++;
}
}
}
}
下面分别是QT和MFC将搜索到的com口显示在下拉列表,注意在每次点击刷新需要清楚列表并清空容器
void MainWindow::on_pushButton_Serch_clicked()
{
ui->comboBox_COM->clear(); //清除列表
GetUsbProperty();
GetComProperty();
UCContarst();
for (int i = 0; i < g_Devices.size();i++)
{
string str = g_Devices[i].strCom;
QString qstr = QString::fromStdString(str);
ui->comboBox_COM->addItem(qstr);
}
g_usbDevices.clear();
g_comDevices.clear();
g_Devices.clear();
}
MFC
void CUToComDlg::OnBnClickedBtnSerch()
{
((CComboBox*)GetDlgItem(IDC_COMBO_COM))->ResetContent();//消除现有所有内容
GetUsbProperty();
GetComProperty();
UCContarst();
for (int i = 0; i < g_Devices.size();i++)
{
CString str = g_Devices[i].strCom;
m_com.InsertString(i, str);
}
g_usbDevices.clear();
g_comDevices.clear();
g_Devices.clear();
}