介绍Windows侦测遍历Usb设备(PID&VID)及相应其插拔状态的方法

     当程序需要判断当前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;
	}
}









展开阅读全文

没有更多推荐了,返回首页