C++获取所有USB接口的vid、pid等信息

最近项目要写一个MFC的外挂程序,要分别获取电脑上所有扫描枪的输入信息,这时我们就需要根据扫描枪的vid和pid进行区分,有一些同批次同型号的输入设备vid和pid会相同,我们可能需要设备实例路径进行区分,可以在设备管理器->键盘->点击设备查看,如图:
在这里插入图片描述
这里记录一下获取USB信息的代码,因为涉及到公司业务,只给出这部分我封装好的类,这是MFC下继承CDialogEx的类,C++只需要略作修改,核心代码为HID_FindAllDevices函数,我对记录pid,vid的vector进行了去重,设备有pid,vid相同的需要修改。

ScannerDlg.h

#pragma once
#include <vector>
#include <algorithm>
#include "afxwin.h"

// CScannerDlg 对话框
struct _VID_PID_
{
	USHORT V_ID;
	USHORT P_ID;
	_VID_PID_(USHORT vid, USHORT pid)
	{
		V_ID = vid;
		P_ID = pid;
	}
	bool operator==(const _VID_PID_ &other)
	{
		if (V_ID == other.V_ID && P_ID == other.P_ID)
			return true;
		return false;
	}
};

class CScannerDlg : public CDialogEx
{
	DECLARE_DYNAMIC(CScannerDlg)

public:
	CScannerDlg(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~CScannerDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_SCANNER_DIALOG };
#endif

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

	DECLARE_MESSAGE_MAP()

private:
	std::vector<_VID_PID_> vecVidPid;
	void HID_FindAllDevices(unsigned short *FIFO_Length);
public:
	CComboBox m_combo_scanner;
	afx_msg void OnCbnDropdownComboScanner();
	afx_msg void OnBnClickedOk();
};

ScannerDlg.cpp

// ScannerDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "ScannerDlg.h"
#include "afxdialogex.h"
#include <iostream>  
#include <string>  
#include <fstream>
#include <setupapi.h>
#include <devguid.h>
#include <winioctl.h>
#include <regstr.h>
#include <conio.h>

#pragma comment(lib,"setupapi.lib")
extern "C" {
#include <hidsdi.h> 
};
// CScannerDlg 对话框

IMPLEMENT_DYNAMIC(CScannerDlg, CDialogEx)

CScannerDlg::CScannerDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_SCANNER_DIALOG, pParent)
{
}

CScannerDlg::~CScannerDlg()
{
}

void CScannerDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_COMBO_SCANNER, m_combo_scanner);
}


BEGIN_MESSAGE_MAP(CScannerDlg, CDialogEx)
	ON_CBN_DROPDOWN(IDC_COMBO_SCANNER, &CScannerDlg::OnCbnDropdownComboScanner)
	ON_BN_CLICKED(IDOK, &CScannerDlg::OnBnClickedOk)
END_MESSAGE_MAP()


// CScannerDlg 消息处理程序
//查找所有vidpid
void CScannerDlg::HID_FindAllDevices(unsigned short *FIFO_Length)
{
	GUID                             HidGuid;
	HDEVINFO                         DevInfo;
	HIDD_ATTRIBUTES					 DevAttributes;
	SP_DEVICE_INTERFACE_DATA         DevData;
	PSP_DEVICE_INTERFACE_DETAIL_DATA DevDetail;
	PHIDP_PREPARSED_DATA          PreparsedData;
	HIDP_CAPS                   Capabilities;
	ULONG                            Length;
	int                              Index;

	BOOL                             ok;
	HANDLE DevHandle;
	int DevCount = 0;
	vecVidPid.clear();
	/* Get GUID for all System HIDs */
	HidD_GetHidGuid(&HidGuid);
	/* Get Device Information for all present devices */
	DevInfo = SetupDiGetClassDevs(&HidGuid,
		NULL,
		NULL,
		(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)
		);
	DevData.cbSize = sizeof(DevData);
	DevDetail = NULL;
	Index = -1;
	*FIFO_Length = 0;
	/* Scan all Devices */
	do {
		Index++;
		/* Device Interface Element of a Device Information set */
		ok = SetupDiEnumDeviceInterfaces(DevInfo,
			0,
			&HidGuid,
			Index,
			&DevData
			);
		if (!ok) break;
		/* Get Device Interface Details - Get Length */
		ok = SetupDiGetDeviceInterfaceDetail(DevInfo,
			&DevData,
			NULL,
			0,
			&Length,
			NULL
			);

		/* Allocate memory for Device Detailed Data */
		DevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
		/* Set cbSize in the DevDetail structure */
		DevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
		/* Get Device Interface Details */
		ok = SetupDiGetDeviceInterfaceDetail(DevInfo,
			&DevData,
			DevDetail,
			Length,
			NULL,
			NULL
			);
		if (!ok)
		{
			free(DevDetail);
			DevDetail = NULL;
			continue;
		}

		/* Create File for Device Read/Write */
		DevHandle = CreateFile(DevDetail->DevicePath,
			0,
			FILE_SHARE_READ | FILE_SHARE_WRITE,
			(LPSECURITY_ATTRIBUTES)NULL,
			OPEN_EXISTING,
			0,
			NULL
			);
		if (DevHandle == INVALID_HANDLE_VALUE)
		{
			free(DevDetail);
			DevDetail = NULL;
			continue;
		}

		DevAttributes.Size = sizeof(DevAttributes);
		ok = HidD_GetAttributes(DevHandle, &DevAttributes);
		if (!ok)
		{
			free(DevDetail);
			CloseHandle(DevHandle);
			DevDetail = NULL;
			continue;
		}

		if (find(vecVidPid.begin(), vecVidPid.end(), _VID_PID_(DevAttributes.VendorID, DevAttributes.ProductID)) == vecVidPid.end())
		{
			vecVidPid.push_back(_VID_PID_(DevAttributes.VendorID, DevAttributes.ProductID));
			free(DevDetail);
			CloseHandle(DevHandle);
			DevDetail = NULL;
		}
	} while (DevCount < 20);
	SetupDiDestroyDeviceInfoList(DevInfo);
	return;
}

void CScannerDlg::OnCbnDropdownComboScanner()
{
	// TODO: 在此添加控件通知处理程序代码
	unsigned short* a;
	a = new unsigned short[100];
	memset(a, 0x00, 100);
	vecVidPid.clear();
	m_combo_scanner.ResetContent();

	HID_FindAllDevices(a);
	delete a;
	int i = 0;
	for (auto it = vecVidPid.begin(); it != vecVidPid.end(); it++)
	{
		CString strTmp;
		strTmp.Format(_T("VID:%04x,PID:%04x"), it->V_ID, it->P_ID);
		m_combo_scanner.InsertString(i, strTmp);
		i++;
	}
}


void CScannerDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	CString strTmp;
	int nSel = m_combo_scanner.GetCurSel();
	if (nSel != -1)
	{
		strTmp.Format(_T("%04x"), vecVidPid.at(nSel).V_ID);
		gParams.SetVID(strTmp);
		strTmp.Format(_T("%04x"), vecVidPid.at(nSel).P_ID);
		gParams.SetPID(strTmp);
		gParams.SaveXml();
	}
	else
	{
		gParams.SetVID(_T("FFFF"));
		gParams.SetPID(_T("FFFF"));
		gParams.SaveXml();
	}
	CDialogEx::OnOK();
}

窗口展示
在这里插入图片描述

发布了14 篇原创文章 · 获赞 6 · 访问量 3120

猜你喜欢

转载自blog.csdn.net/qq_39554698/article/details/99586564
今日推荐