MFC工程按USB插口显示所有USB设备及插口(包括安卓)
最近写资料用到按照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
{//设备类型 比如USBCString 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;//容器IDCString ContainerId;//CString Device_Display_Category;//CString pszToken;//vidCString szVid;//pidCString szPid;//miCString 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;//vidCString szVid;//pidCString szPid;//miCString 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;} //容器IDif (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!这个项目可以顺利执行,如果有报错的情况,请参考前面配置的时候是否没有配置正确!
MFC工程按USB插口显示所有USB设备及插口(包括安卓)相关推荐
- STM32F103调试笔记(1)——microusb接入电脑后显示未知USB设备(代码43)
这真的是一个很傻的错误- 由于我最近刚接触stm32,就在b站搜stm32的视频来看,现学现卖现烧程序.终于烧好了,想要用串口调试助手的时候却用不了,设备管理器显示未知USB设备(设备描述符请求失败) ...
- CH330显示未知USB设备(设备描述符请求失败)
CH330接上电脑后显示未知USB设备(设备描述符请求失败),原因是:VCC脚的0.1uF退耦电容一定必不可少!!
- vmware虚拟机连接usb,显示:无法识别的usb设备,跟这台计算机连接的前一个usb设备工作不正常
vmware虚拟机连接usb,显示:无法识别的usb设备,跟这台计算机连接的前一个usb设备工作不正常 前提:vmware,usb3.0设备 解决方法:vmware菜单栏☞VM☞setting☞usb ...
- STM32实现USB摄像头显示到LCD屏幕上
第一章:简介 1.1 开发环境 USB摄像头型号:100w前置摄像头 主机型号:野火霸天虎开发版 外设:USB-HOST接口:连接USB摄像头设备 外部Sram:存放USB摄像头数据 LCD屏幕:显示 ...
- 取消usb计算机连接网络,usb连接(如何设置usb网络连接)
手机USB连接电脑地的方法: 第一步:将USB数据线连接电脑,并确保数据线完好 第二步:打开手机系统设置------开发者选项 第三步:点开开发者选项---------USB调试 . 我不会额...教 ...
- 安卓USB开发教程 三 USB Accessory
USB Accessory(配件模式) USB 配件模式允许用户连接专为 Android 设备设计的 USB 主机硬件.配件必须遵守 Android Accessory Development Kit ...
- 安卓USB开发教程 二 USB Host
USB Host(主机模式) 当 Android 设备处于 USB 主机模式时,它充当 USB 主机,为总线供电,并枚举连接的 USB 设备.Android 3.1 及更高版本支持 USB 主机模式. ...
- 安卓USB开发教程 一 USB Host 与 Accessory
安卓通过两种模式:USB Accessory 与 USB Host 模式支持多种 USB 外设与安卓 USB 配件(实现安卓配件协议的硬件).在 USB 配件模式下,外部 USB 硬件充当 USB 主 ...
- C++学习日记1:VS2015环境下,创建基于对话框的MFC工程
VS2015环境下,创建基于对话框的MFC工程 1.新建项目 文件→新建→项目, 确定工程名称,选择工程保存路径, →确定 2.进入[当前项目设置]. →下一步 3.进入[应用程序类型]界面. 设置[ ...
最新文章
- 评估“不合格”!教育部暂停山东大学、复旦大学、南京师范大学部分硕士、博士学位授权点...
- 漫画:什么是“低代码”开发平台?
- 【Java】5.5 深入构造器
- 阿里云移动端播放器高级功能---截图和音频波形
- android 模糊度处理_图像处理评价指标之模糊度、清晰度(待更新)
- Centos6.8安装Nginx+域名转发
- 关于mybatis的association和collection主键映射问题
- 第十一届中国开源黑客松+中国程序员节重磅来袭,这里将有你不能错过的精彩。...
- ESP32学习笔记(46)——MQTT客户端
- General Partial Label Learning via Dual Bipartite Graph Autoencoder
- Python学习笔记(5)-集成开发环境IDLE的使用与调试
- 【FL攻防综述】Privacy and Robustness in Federated Learning: Attacks and Defenses
- 地产钢铁银行成低市盈率三剑客
- LIN雨量传感器:MQB平台与PQ自带的传感器类型分析
- 如何根据样本估计总体的均值、比例与方差?如何进行参数估计及选择对应公式?
- 字节跳动2020秋招笔试题
- 八、chmod命令详细用法
- win7 上配置openGL开发环境(配套openGL 超级宝典Super Bible 6th)
- 基于OpenCV的形状检测
- 鸿蒙时代实力排名,鸿蒙时期神魔不敢进入四大禁区,九天银河上榜,第一堪称黑暗禁地...