MFC工程按USB插口显示所有USB设备及插口(包括安卓)

10 篇文章 1 订阅
2 篇文章 0 订阅

  最近写资料用到按照USB顺序显示所有的USB设备(设备不用按照插入顺序,只需要插入对应USB插口即可),搜了很多资料没有找到想要的实现方式,便自己动手写了一些库文件(结合USB View以及WindowsAPI函数),并且成功移植到MFC工程(我使用的是VS2010工具)。

  首先看下USB View软件显示效果:
这里写图片描述

    我们看到USB View软件是以树结构显示了USB所有的插口(包括以及连接设备的插口和还未连接设备的插口),但是连接的设备信息却不齐全(比如如何判断是安卓设备以及设备的容器ID和名称等)。

    插入设备的数据采用WindowsAPI函数(WindowsAPI函数的缺点是只能查询到已经连接的设备信息,却不能确定设备信息对应的插口),对于这块我也纠结不少时间…

    后来进行猜想,采用USB View作为USB插口的遍历,然后结合算法把遍历到的数据进行配对,可以组成完成的USB数据信息。

  下面是我的实验计划:
    1.使用USB View函数库进行遍历并且保存所有的USB插口信息(保存已经插入和未插入的),其中树结构分为三级保存,第一级做为主要设备信息(USBHostControllers 主控制器),第二级做为hub设备信息(可以清楚知道hub下有几个USB插口),第三级做为当前hub下的USB插口信息。当然这只是USB View实现的功能;

    2.使用WindowsAPI遍历到所有的USB信息(其中包括Hub信息);

    3.根据USB View插口内的idVendor和idProduct信息进行匹配WindowAPI内所有相关的数据,配对成功后得到容器ID进行遍历剩下的设备信息确保设备信息的完整性以及不重复性,在匹配的过程中我们就可以到插入设备的名称,以及设备类型比如“Android”等,匹配成功后按照USB插口的顺序进行保存顺序(这里只按照计数的形式向后增加USB插口,不再使用树结构);

    4.由于USB View使用C语言写的库文件,需要把一些不兼容MFC的部分进行修改,比如隐藏USB View自带的树结构视图等。


  下面说下使用这个MFC工程的方式:

    首先下载WinDDK 7600.16385.1工具包,这个网上很多下载后,安装到默认的路径:C:\WinDDK; 安装完成后需要把使用的VS2010文件夹路径下的 VC\ include内的所有文件 拷贝覆盖到C:\WinDDK\7600.16385.1\inc\api 文件夹内;

    MFC工程下载地址:https://download.csdn.net/download/a29562268/10294175!

  这个工程可以直接使用,也可以移植内部的文件用来使用,由于修改的文件比较多,只贴出具体实现的文件:

  .h文件

/*
*李坤昱
*QQ:326087275@qq.com
*/
#include <stdio.h>
#include <vector>
#include "usbioctl.h "


//枚举出所有的设备信息,然后与USB view信息合并
struct  List_all_USB_devices 
{
	//设备类型 比如USB
	CString szDeviceInstanceID;
	//
	CString Device_Description;
	//设备描述
	CString szDesc;
	//
	CString Hardware_IDs;
	//
	CString pszId;
	//
	CString Bus_Reported_Device_Description;
	//
	CString Device_Manufacturer;
	//
	CString Device_Friendly_Name;
	//
	CString Device_Location_Info;
	//
	CString Device_Security_Descriptor_String;
	//容器ID
	CString ContainerId;
	//
	CString Device_Display_Category;
	//
	CString pszToken;
	//vid
	CString szVid;
	//pid
	CString szPid;
	//mi
	CString szMi;
	//如果当前这条数据已经写入设备结构,标记为1 不再进行匹配
	bool bIs;

	List_all_USB_devices():bIs(0)
	{

	}
};


struct Usb_List_Data 
{
	Usb_List_Data();
	//获取所有的USB设备信息
	bool GetAllUsbInfo(std::vector<List_all_USB_devices> & usb_Info);
private:
	//保存所有的USB信息
	std::vector<List_all_USB_devices> Usb_Devices;
private:
	//遍历USB设备
	void ListDevices (CONST GUID *pClassGuid, LPCTSTR pszEnumerator);
};

typedef struct _STRING_DESCRIPTOR_NODE_
{
    struct _STRING_DESCRIPTOR_NODE *Next;
    UCHAR                           DescriptorIndex;
    USHORT                          LanguageID;
    USB_STRING_DESCRIPTOR           StringDescriptor[0];
} STRING_DESCRIPTOR_NODE_, *PSTRING_DESCRIPTOR_NODE_;


//
struct Usb_Info
{
	int Count;
	//
	int deviceNameSize;
	//
	BOOLEAN LowSpeed;
	//
	BOOLEAN DeviceIsHub;
	//
	USHORT DeviceAddress;
	//
	USB_CONNECTION_STATUS ConnectionStatus;
	//
	USHORT NumberOfOpenPipes;
	//
	PSTRING_DESCRIPTOR_NODE_             stringDescs;
	//
	PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfoEx;
	//
	PUSB_DESCRIPTOR_REQUEST             configDesc;
	//
	CString leafName;
	//
	CString driverKeyName;
	//
	CString deviceDesc;
};

//Hub
struct RootHub
{
	int Count;
	//
	int DeviceInfoType;
	//
	CString HubName;
	//
	int deviceNameSize;
	//
	CString deviceName;
	//
	CString leafName;
	//
	PUSB_NODE_INFORMATION   hubInfo;
	//
	PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo;
	//
	PUSB_DESCRIPTOR_REQUEST ConfigDesc;
	//
	PSTRING_DESCRIPTOR_NODE_ StringDescs;

	std::vector<Usb_Info> Usb;
};
//主机控制器
struct HostControllers
{
	//标记当前是第几个主机控制器
	int Count;
	//
	CString DeviceInfoType;
	//
	CString DriverKeyName;
	//
	CString DeviceId;
	//
	ULONG VendorID;
	//
	ULONG DeviceID;
	//
	ULONG SubSysID;
	//
	ULONG Revision;
	//
	CString rootHubName;
	//
	CString deviceDesc;

	std::vector<RootHub> Hub;
};

//获取计算机内树形结构形式 所有的USB相关信息,以及先后顺序(用来记录USB设备的位置)
struct Usb_Id
{
	bool GetAllUsbPlace(std::vector<HostControllers> & usb_host);
public:
	
	//设备连接数
	ULONG devicesConnected;
private:
	void GetAllUsbPlace_();
};

struct Usb_Port
{
	//标记是第几个USB插口
	int nCount;
	//
	ULONG VendorID;
	//
	ULONG ProductID;
	//
	CString Device_Description;
	//用来保存安卓设备名称
	CString Device_Description1;
	//
	CString Bus_Reported_Device_Description;
	//
	CString Device_Manufacturer;
	//
	CString Device_Location_Info;
	//
	CString ContainerId;
	//vid
	CString szVid;
	//pid
	CString szPid;
	//mi
	CString szMi;
	//
	USB_CONNECTION_STATUS ConnectionStatus;
};

//按循序整理出从Usb插口1开始,一直到最后的设备
struct Usb_SequenceInfo
{
	Usb_List_Data usb_list;
	Usb_Id Usb_id;
	bool GetUsbAllPorts(std::vector<Usb_Port> & port);
private:
	std::vector<Usb_Port> m_port;
private:
	void GetUsbPortsInfo();
	void WriteUsbPortsInfo(std::vector<List_all_USB_devices> usb_data,std::vector<HostControllers> usb_host);
};

  .cpp文件

/*
*李坤昱
*QQ:326087275@qq.com
*/
#include "StdAfx.h"
#include "Usb_.h"

#include "inc/usbview.h"
#include <windowsx.h>


#include <windows.h>  
#include <devguid.h>    // for GUID_DEVCLASS_CDROM etc  
#include <setupapi.h>  
#include <cfgmgr32.h>   // for MAX_DEVICE_ID_LEN, CM_Get_Parent and CM_Get_Device_ID  
#define INITGUID  
#include <tchar.h>  
#include "C:\WinDDK\7600.16385.1\inc\api\devpkey.h" 

#pragma comment (lib, "setupapi.lib") 


typedef BOOL (WINAPI *FN_SetupDiGetDevicePropertyW)(  
	__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  
	);  

char *strupr(char *str);

#define ARRAY_SIZE(arr)     (sizeof(arr)/sizeof(arr[0]))  

Usb_List_Data::Usb_List_Data()
{

}

// 获取所有的USB信息
void Usb_List_Data::ListDevices (CONST GUID *pClassGuid, LPCTSTR pszEnumerator)  
{  
	unsigned i, j;  
	DWORD dwSize, dwPropertyRegDataType;  
	DEVPROPTYPE ulPropertyType;  
	CONFIGRET status;  
	HDEVINFO hDevInfo;  
	SP_DEVINFO_DATA DeviceInfoData;  
	const static LPCTSTR arPrefix[3] = {TEXT("VID_"), TEXT("PID_"), TEXT("MI_")};  
	TCHAR szDeviceInstanceID [MAX_DEVICE_ID_LEN];  
	TCHAR szDesc[1024], szHardwareIDs[4096];  
	WCHAR szBuffer[4096];  
	LPTSTR pszToken, pszNextToken;  
	TCHAR szVid[MAX_DEVICE_ID_LEN], szPid[MAX_DEVICE_ID_LEN], szMi[MAX_DEVICE_ID_LEN];  
	FN_SetupDiGetDevicePropertyW fn_SetupDiGetDevicePropertyW = (FN_SetupDiGetDevicePropertyW)  
		GetProcAddress (GetModuleHandle (TEXT("Setupapi.dll")), "SetupDiGetDevicePropertyW");  

	// List all connected USB devices  
	hDevInfo = SetupDiGetClassDevs (pClassGuid, pszEnumerator, NULL,  
		pClassGuid != NULL ? DIGCF_PRESENT: DIGCF_ALLCLASSES | DIGCF_PRESENT);  
	if (hDevInfo == INVALID_HANDLE_VALUE)  
		return;  

	// Find the ones that are driverless  
	for (i = 0; ; i++)  {  
		List_all_USB_devices usb_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;  

		// Display device instance ID  
		_tprintf (TEXT("%s\n"), szDeviceInstanceID );  

		if (SetupDiGetDeviceRegistryProperty (hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC,  
			&dwPropertyRegDataType, (BYTE*)szDesc,  
			sizeof(szDesc),   // The size, in bytes  
			&dwSize))  
			//设备名称 
			_tprintf (TEXT("    Device Description: \"%s\"\n"), szDesc);  
		usb_dev.Device_Description.Format(_T("%s"),szDesc);
		if (SetupDiGetDeviceRegistryProperty (hDevInfo, &DeviceInfoData, SPDRP_HARDWAREID,  
			&dwPropertyRegDataType, (BYTE*)szHardwareIDs,  
			sizeof(szHardwareIDs),    // The size, in bytes  
			&dwSize)) {  
				LPCTSTR pszId;  
				_tprintf (TEXT("    Hardware IDs:\n"));  
				for (pszId=szHardwareIDs;  
					*pszId != TEXT('\0') && pszId + dwSize/sizeof(TCHAR) <= szHardwareIDs + ARRAYSIZE(szHardwareIDs);  
					pszId += lstrlen(pszId)+1) {  

						_tprintf (TEXT("        \"%s\"\n"), pszId); 
						usb_dev.pszId.Format(_T("%s"),pszId);
				}  
		}  

		// Retreive the device description as reported by the device itself  
		// On Vista and earlier, we can use only SPDRP_DEVICEDESC  
		// On Windows 7, the information we want ("Bus reported device description") is  
		// accessed through DEVPKEY_Device_BusReportedDeviceDesc  
		if (fn_SetupDiGetDevicePropertyW && fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc,  
			&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {  
				//设备类型
				if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc,  
					&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0))  
					_tprintf (TEXT("    Bus Reported Device Description: \"%ls\"\n"), szBuffer);  
				usb_dev.Bus_Reported_Device_Description = szBuffer;

				if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_Manufacturer,  
					&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {  
						_tprintf (TEXT("    Device Manufacturer: \"%ls\"\n"), szBuffer); 
						usb_dev.Device_Manufacturer = szBuffer;
				}  
				if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_FriendlyName,  
					&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {  
						_tprintf (TEXT("    Device Friendly Name: \"%ls\"\n"), szBuffer); 
						usb_dev.Device_Friendly_Name = szBuffer;
				}  
				if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_LocationInfo,  
					&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {  
						_tprintf (TEXT("    Device Location Info: \"%ls\"\n"), szBuffer);  
						usb_dev.Device_Location_Info = szBuffer;
				}  
				if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_SecuritySDS,  
					&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)) {  
						// See Security Descriptor Definition Language on MSDN  
						// (http://msdn.microsoft.com/en-us/library/windows/desktop/aa379567(v=vs.85).aspx)  
						_tprintf (TEXT("    Device Security Descriptor String: \"%ls\"\n"), szBuffer);  
						usb_dev.Device_Security_Descriptor_String = szBuffer;
				}  
				//容器ID
				if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_ContainerId,  
					&ulPropertyType, (BYTE*)szDesc, sizeof(szDesc), &dwSize, 0)) {  
						StringFromGUID2((REFGUID)szDesc, szBuffer, ARRAY_SIZE(szBuffer));  
						_tprintf (TEXT("    ContainerId: \"%ls\"\n"), szBuffer);  
						usb_dev.ContainerId = szBuffer;
				}  
				if (fn_SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_DeviceDisplay_Category,  
					&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0))  
					_tprintf (TEXT("    Device Display Category: \"%ls\"\n"), szBuffer); 
				usb_dev.Device_Display_Category = szBuffer;
		}  

		pszToken = _tcstok_s (szDeviceInstanceID , TEXT("\\#&"), &pszNextToken);  
		while(pszToken != NULL) {  
			szVid[0] = TEXT('\0');  
			szPid[0] = TEXT('\0');  
			szMi[0] = TEXT('\0');  
			for (j = 0; j < 3; j++) {  
				if (_tcsncmp(pszToken, arPrefix[j], lstrlen(arPrefix[j])) == 0) {  
					switch(j) {  
					case 0:  
						_tcscpy_s(szVid, ARRAY_SIZE(szVid), pszToken);  
						break;  
					case 1:  
						_tcscpy_s(szPid, ARRAY_SIZE(szPid), pszToken);  
						break;  
					case 2:  
						_tcscpy_s(szMi, ARRAY_SIZE(szMi), pszToken);  
						break;  
					default:  
						break;  
					}  
				}  
			}  
			if (szVid[0] != TEXT('\0'))  
			{
				_tprintf (TEXT("    vid: \"%s\"\n"), szVid);  
				usb_dev.szVid.Format(_T("%s"),szVid);
			}

			if (szPid[0] != TEXT('\0'))  
			{
				_tprintf (TEXT("    pid: \"%s\"\n"), szPid);
				usb_dev.szPid.Format(_T("%s"),szPid);
			}

			if (szMi[0] != TEXT('\0'))  
			{
				_tprintf (TEXT("    mi: \"%s\"\n"), szMi);  
				usb_dev.szMi.Format(_T("%s"),szMi);
			}

			pszToken = _tcstok_s (NULL, TEXT("\\#&"), &pszNextToken);  
		}  

		Usb_Devices.push_back(usb_dev);
	}  

	return;  
}  



bool Usb_List_Data::GetAllUsbInfo(std::vector<List_all_USB_devices> & usb_Info)
{
	ListDevices(NULL, _T("USB"));
	usb_Info = Usb_Devices;
	return (usb_Info.size() > 0 ? true : false);
}



std::vector<HostControllers> host;


bool Usb_Id::GetAllUsbPlace(std::vector<HostControllers> & usb_host)
{
	GetAllUsbPlace_();
	usb_host = host;
	return (usb_host.size() > 0 ? true : false);
}


void Usb_Id::GetAllUsbPlace_()
{
	host.clear();
	EnumerateHostControllers(0,&devicesConnected);
}



void Usb_SequenceInfo::GetUsbPortsInfo()
{
	std::vector<List_all_USB_devices> usb_data;
	usb_list.GetAllUsbInfo(usb_data);

	std::vector<HostControllers> usb_host;
	Usb_id.GetAllUsbPlace(usb_host);
	WriteUsbPortsInfo(usb_data,usb_host);
}

void Usb_SequenceInfo::WriteUsbPortsInfo(std::vector<List_all_USB_devices> usb_data,std::vector<HostControllers> usb_host)
{
	if (0 >= usb_data.size() && 0 >= usb_host.size())
	{
		AfxMessageBox(_T("无法获取到USB的接口位置!"));
	}
	//合并信息组成一条完整usb设备信息
	m_port.clear();
	int count = 0;
	for (auto it = usb_host.begin();it != usb_host.end();it++)
	{
		for (auto Usb = it->Hub.begin();Usb != it->Hub.end();Usb++)
		{
			for (auto UsbInfo = Usb->Usb.begin();UsbInfo != Usb->Usb.end();UsbInfo++)
			{
				Usb_Port port;
				port.ConnectionStatus = UsbInfo->ConnectionStatus;
				if (DeviceConnected == port.ConnectionStatus)
				{
					if ((UsbInfo->connectionInfoEx) && (NULL !=  UsbInfo->connectionInfoEx) /*&& (0 != *UsbInfo->connectionInfoEx->DeviceDescriptor)*/)
					{
						port.VendorID = UsbInfo->connectionInfoEx->DeviceDescriptor.idVendor;
						port.ProductID = UsbInfo->connectionInfoEx->DeviceDescriptor.idProduct;

						//设备的id数字有的是16进制 有的是10进制
						CString StrVendor,StrProduct;
						StrVendor.Format(_T("VID_%04X"),port.VendorID);
						StrProduct.Format(_T("PID_%04X"),port.ProductID);
					
						CString StrVendor_,StrProduct_;
						StrVendor_.Format(_T("VID_%d"),port.VendorID);
						StrProduct_.Format(_T("PID_%d"),port.ProductID);
						//在所有设备信息里进行匹配
						for (auto data = usb_data.begin();data != usb_data.end();data++)
						{
							if (data->bIs == true)
								continue;
							//进行记录数据,然后继续遍历相同容器ID的
							if ((data->szVid == StrVendor && data->szPid == StrProduct)
								|| (data->szVid == StrVendor_ && data->szPid == StrProduct_))
							{
								port.szVid = data->szVid;
								port.szPid = data->szPid;
								data->bIs = true;
								port.Device_Description = data->Device_Description;
								port.Bus_Reported_Device_Description = data->Bus_Reported_Device_Description;
								port.Device_Manufacturer = data->Device_Manufacturer;
								port.Device_Location_Info = data->Device_Location_Info;
								port.ContainerId = data->ContainerId;
								port.szMi = data->szMi;
								if (!port.ContainerId.IsEmpty())
								{
									//遍历一边相同容器ID的信息,找出设备名称
									for (auto data1 = usb_data.begin();data1 != usb_data.end();data1++)
									{
										if (port.ContainerId == data1->ContainerId)
										{
											if (!data1->bIs)
											{
												//如果设备描述已经是Android了,那么修改为设备名称
												/*
												这么做的原因是Device_Description或Bus_Reported_Device_Description其中有一个表示设备名称,
												遍历的时候可能会被Android字节覆盖掉,这样可以保证保留设备名称
												*/
												if (port.Device_Description1.IsEmpty() || _T("Android") != data->Bus_Reported_Device_Description)
												{
													port.Device_Description1 = data1->Device_Description;
												}
												data1->bIs = true;
											}
										}
									}
								}
							}


						}

					}
				}
				port.nCount = ++count;
				m_port.push_back(port);
			}
		}
	}
}


bool Usb_SequenceInfo::GetUsbAllPorts(std::vector<Usb_Port> & port)
{
	GetUsbPortsInfo();
	port = m_port;
	return (port.size() > 0 ? true : false);
}

  MFC工程下载地址:https://download.csdn.net/download/a29562268/10294175!这个项目可以顺利执行,如果有报错的情况,请参考前面配置的时候是否没有配置正确!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坤昱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值