当程序需要判断当前USB端口上是否插入某个USB设备时可用此方法。大概原理是遍历USB端口得到当前连接设备的PID和VID,从而可判断指定设备是否存在。
大致流程介绍:
1.在Windows中每个USB设备的设备描述符为:HCD0, HCD1,HCD2 .......等等,从而可以得到其相应的内核路径为:\\\\.\\HCD0,\\\\.\\HCD1 ......。
2.通过有效的HCD值得到这个USB设备对应的ROOTHUB信息。
3.遍历ROOTHUB上每个端口,这时就能得到PID和VID的信息。
大致代码如下:
1.
int HCNum = 0;
HANDLE hHCDev = INVALID_HANDLE_VALUE;
TCHAR HCName[16] = {'\0'};
CHAR rootHubName[MAX_PATH] = {'\0'};
for (HCNum = 0; HCNum < 10/*假设这台电脑上最多有10个USB口*/; HCNum++)
{
wsprintf(HCName, _T("\\\\.\\HCD%d"), HCNum); //USB口的内核路径。
hHCDev = CreateFile(HCName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hHCDev != INVALID_HANDLE_VALUE) //这个USB口上插着某个设备,但此时还无法得到这个设备的具体信息,需要其对应的ROOTHUB得到。
{
//得到这个USB设备的ROOTHUB信息。
//......
}
CloseHandle(hHCDev);
}
2.
typedef struct _USB_ROOT_HUB_NAME {
ULONG ActualLength; /* OUTPUT */
/* NULL terminated unicode symbolic name for the root hub */
WCHAR RootHubName[1]; /* OUTPUT */
} USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME;
PUSB_ROOT_HUB_NAME rootHubNameW = (PUSB_ROOT_HUB_NAME)ALLOC(nBytes);
DeviceIoControl(HostController, IOCTL_USB_GET_ROOT_HUB_NAME, NULL, 0, rootHubNameW, nBytes, &nBytes, NULL);
//HostController就是HCD为有效值时的USB端口的HANDLE.
3. 打开ROOTHUB的设备驱动:
CString str1(_T("\\\\.\\"));
CString str2(HubName);
str1 = str1 + str2;
// Try to hub the open device
hHubDevice = CreateFile(str1.GetBuffer(0), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
4.得到这个ROOTHUB上所有节点信息:
DeviceIoControl(hHubDevice, IOCTL_USB_GET_NODE_INFORMATION, info->HubInfo, sizeof(USB_NODE_INFORMATION), info->HubInfo, sizeof(USB_NODE_INFORMATION), &nBytes, NULL);
5.
ULONG index;
BOOL success;
PUSB_NODE_CONNECTION_INFORMATION connectionInfo;
PCHAR deviceDesc;
for (index=1; index <= NumPorts; index++)
{
ULONG nBytes;
nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) + sizeof(USB_PIPE_INFO) * 30;
connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)ALLOC(nBytes);
if (connectionInfo == NULL)
{
break;
}
connectionInfo->ConnectionIndex = index;
success = DeviceIoControl(hHubDevice, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, connectionInfo, nBytes, connectionInfo, nBytes, &nBytes, NULL);
if (!success)
{
FREE(connectionInfo);
continue;
}
if (connectionInfo->ConnectionStatus == DeviceConnected)
{
//Check connectionInfo->DeviceDescriptor.idVendor andconnectionInfo->DeviceDescriptor.idProduct here.
}
}
以上是通过遍历USB端口的方法检测设备是否插拔,其实Windows针对硬件设备的状态变化会向应用程序发送相关的消息,所以程序初始化的时候遍历一次判断设备是否存在,然后就可以通过接收Windows消息判断设备是否存在。
1.首先添加头文件:
#include <Dbt.h>
2.在程序初始化的时候注册相应请求,如果不注册就无法正确得到消息类型:
DEV_BROADCAST_DEVICEINTERFACE Filter;
ZeroMemory(&Filter,sizeof(Filter));
Filter.dbcc_size = sizeof(Filter); // size gets set to 29 with 1-byte packing or 32 with 4- or 8-byte packing
Filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
RegisterDeviceNotification(this->m_hWnd,&Filter,DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
3.相应消息:
OnDeviceChange(UINT nEventType, DWORD dwData)
{
DEV_BROADCAST_DEVICEINTERFACE * dbd = (DEV_BROADCAST_DEVICEINTERFACE*) dwData;
switch(nEventType)
{
case DBT_DEVICEREMOVECOMPLETE: //移除设备
break;
break;
default:
break;
}
}