USB学习笔记二《插拔检测+示例代码》

 USB热插拔检测:
方法一:
启动定时器,定时轮询注册表,这种方法容易死机。
方法二:
注册窗口,添加Windows消息 
ON_WM_DEVICECHANGE()映射。
步骤:
一: 要想添加消息映射,需改变三个地方:
1、 窗口头文件声明消息处理函数
afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData)
2、 源文件添加消息处理函数

BOOL CDownLoadDlg::OnDeviceChange(UINT nEventType,DWORD dwData)
{
    // TODO: 在此添加额外的初始化代码
} 
3、 源文件添加消息
 
BEGIN_MESSAGE_MAP(CDownLoadDlg, CDialog)
‘’‘’‘’‘’‘’
 
ON_WM_DEVICECHANGE()//USB消息
  END_MESSAGE_MAP()
二: 消息处理函数的OnDeviceChange 
 MSDN说明:
The framework calls this member function to notify an application or device driver of a change to the hardware configuration of a device or the computer.  
afx_msg BOOL OnDeviceChange(  UINT nEventType, 
                                                        DWORD_PTR dwData  
                                                      );  
Parameters
nEventType

An event type. See the Remarks section for a description of the available values

dwData

The address of a structure that contains event-specific data. Its meaning depends on the given event.

For devices that offer software-controllable features, such as ejection and locking, the operating system typically sends a DBT_DEVICEREMOVEPENDING message to let applications and device drivers end their use of the device gracefully.

If the operating system forcefully removes of a device, it may not send a DBT_DEVICEQUERYREMOVE message before doing so.

The nEvent parameter can be one of these values:

//DBT_DEVICEARRIVAL                              设备已插入,现在可用
//
//DBT_DEVICEQUERYREMOVE                  允许删除设备请求。任何应用程序都可以拒绝这个请求,取消删除。
//
//DBT_DEVICEQUERYREMOVEFAILED      请求删除一个设备已经被取消。
//
//DBT_DEVICEREMOVEPENDING              设备将被删除。不能否认。
//
//DBT_DEVICEREMOVECOMPLETE          设备已被删除。          
//
//DBT_DEVICETYPESPECIFIC                   特定于设备的事件
//
//DBT_CONFIGCHANGED                          当前配置发生了变化。
//
//DBT_DEVNODES_CHANGED                  设备节点已经改变了

例子:

BOOL CDownLoadDlg::OnDeviceChange(UINT nEventType,DWORD dwData)
{
// DEV_BROADCAST_DEVICEINTERFACE* dbd = (DEV_BROADCAST_DEVICEINTERFACE*) dwData;//这里进行信息匹配,比如guid等
PDEV_BROADCAST_HDRdbd =(PDEV_BROADCAST_HDR)dwData;


//针对各个事件进行处理.
m_StrResult.Empty();
switch (nEventType)
{
case DBT_DEVICEREMOVECOMPLETE:
if(dbd->dbch_devicetype==DBT_DEVTYP_DEVICEINTERFACE)
{
DEV_BROADCAST_DEVICEINTERFACE  *get_dbd;
get_dbd=(DEV_BROADCAST_DEVICEINTERFACE*) dwData;
//名字对比
unsigned shortlength,VID,PID,i;
unsigned char numb[8];
CString get_hid_name;
get_hid_name.Format(_T("%s"),get_dbd->dbcc_name);
length=get_hid_name.GetLength();
if(length<10)
{
return false;
}


for(i=0;i<length-3;i++)
{
if(('H'==get_hid_name.GetAt(i)) && ('I'==get_hid_name.GetAt(i+1)) && ('D'==get_hid_name.GetAt(i+2)))
break;
}
if(i==(length-3))
{
return false;
}
length=i;
for(i=0;i<4;i++)
{
if((get_hid_name.GetAt(i+8+length)<=0x39) && (get_hid_name.GetAt(i+8+length)>=0x30))
{
numb[i]=get_hid_name.GetAt(i+8+length);
numb[i]=numb[i]-0x30;
}
if((get_hid_name.GetAt(i+8+length)<=0x5A) && (get_hid_name.GetAt(i+8+length)>=0x41))
{
numb[i]=get_hid_name.GetAt(i+8+length);
numb[i]=numb[i]-0x37;
}
if((get_hid_name.GetAt(i+8+length)<=0x7A) && (get_hid_name.GetAt(i+8+length)>=0x61))
{
numb[i]=get_hid_name.GetAt(i+8+length);
numb[i]=numb[i]-0x57;
}


if((get_hid_name.GetAt(i+17+length)<=0x39) && (get_hid_name.GetAt(i+17+length)>=0x30))
{
numb[i+4]=get_hid_name.GetAt(i+17+length);
numb[i+4]=numb[i+4]-0x30;
}
if((get_hid_name.GetAt(i+17+length)<=0x5A) && (get_hid_name.GetAt(i+17+length)>=0x41))
{
numb[i+4]=get_hid_name.GetAt(i+17+length);
numb[i+4]=numb[i+4]-0x37;
}
if((get_hid_name.GetAt(i+17)<=0x7A+length) && (get_hid_name.GetAt(i+17+length)>=0x61))
{
numb[i+4]=get_hid_name.GetAt(i+17+length);
numb[i+4]=numb[i+4]-0x57;
}
}
VID=numb[0];
VID=VID<<4;
VID=VID & 0x00F0;
VID=VID |(numb[1] & 0x000F);
VID=VID<<4;
VID=VID & 0x0FF0;
VID=VID |(numb[2] & 0x000F);
VID=VID<<4;
VID=VID & 0xFFF0;
VID=VID |(numb[3] & 0x000F);


PID=numb[4];
PID=PID<<4;
PID=PID & 0x00F0;
PID=PID |(numb[5] & 0x000F);
PID=PID<<4;
PID=PID & 0x0FF0;
PID=PID |(numb[6] & 0x000F);
PID=PID<<4;
PID=PID & 0xFFF0;
PID=PID |(numb[7] & 0x000F);


if((VID==USB_VID) && (PID==USB_PID))
{
CloseUSB();
EditWrite(_T("下载器已移除\r\n"),_T("未连接"));
}
}
else
{
return false;
}
break;
case DBT_DEVICEARRIVAL:
if(hidHandle == INVALID_HANDLE_VALUE)
{
HIDFindFunc();
}
break;


default:
return false;
break;
}
return TRUE;
}

二、设备注册
如果想获得正确的
 nEventType 值,必须先在窗口初始化函数OnInitDialog()里面进行注册,否则值都是7,切要在函数最后(DoModal()函数之后)调用。注册函数用RegisterDeviceNotification()。
MSDN说明:

Registers the device or type of device for which a window will receive notifications.

Syntax

C++
HDEVNOTIFY WINAPI RegisterDeviceNotification( _In_  HANDLE hRecipient, _In_  LPVOID NotificationFilter, _In_  DWORD Flags);

Parameters

hRecipient [in]

A handle to the window or service that will receive device events for the devices specified in the NotificationFilter parameter. The same window handle can be used in multiple calls to RegisterDeviceNotification.

Services can specify either a window handle or service status handle.

NotificationFilter [in]

A pointer to a block of data that specifies the type of device for which notifications should be sent. This block always begins with the DEV_BROADCAST_HDR structure. The data following this header is dependent on the value of the dbch_devicetype member, which can be DBT_DEVTYP_DEVICEINTERFACE or DBT_DEVTYP_HANDLE. For more information, see Remarks.

Flags [in]

This parameter can be one of the following values.

Value Meaning
DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000

The hRecipient parameter is a 
window handle.

DEVICE_NOTIFY_SERVICE_HANDLE 0x00000001

The hRecipient parameter is a service
status handle.

 

In addition, you can specify the following value.

Value Meaning
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES 0x00000004

Notifies the recipient of device interface events for all device interface 
classes. (The dbcc_classguid member is ignored.)

This value can be used only if the 
dbch_devicetype member is 
DBT_DEVTYP_DEVICEINTERFACE.

 

Return value

If the function succeeds, the return value is a device notification handle.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Remarks

Applications send event notifications using the BroadcastSystemMessage function. Any application with a top-level window can receive basic notifications by processing the WM_DEVICECHANGE message. Applications can use theRegisterDeviceNotification function to register to receive device notifications.

Services can use the RegisterDeviceNotification function to register to receive device notifications. If a service specifies a window handle in the hRecipient parameter, the notifications are sent to the window procedure. IfhRecipient is a service status handle, SERVICE_CONTROL_DEVICEEVENT notifications are sent to the service control handler. For more information about the service control handler, see HandlerEx.

Be sure to handle Plug and Play device events as quickly as possible. Otherwise, the system may become unresponsive. If your event handler is to perform an operation that may block execution (such as I/O), it is best to start another thread to perform the operation asynchronously.

Device notification handles returned by RegisterDeviceNotification must be closed by calling the UnregisterDeviceNotification function when they are no longer needed.

The DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE events are automatically broadcast to all top-level windows for port devices. Therefore, it is not necessary to call RegisterDeviceNotification for ports, and the function fails if the dbch_devicetype member is DBT_DEVTYP_PORT. Volume notifications are also broadcast to top-level windows, so the function fails if dbch_devicetype is DBT_DEVTYP_VOLUME. OEM-defined devices are not used directly by the system, so the function fails if dbch_devicetype is DBT_DEVTYP_OEM.

例子:
bool CDownLoadDlg::RegisterHidDeviceNotify(void)
{
    GUID HidGuid;                                       /* temporarily stores Windows HID Class GUID */  
    DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;   /* un/plug notification filter */  
HDEVNOTIFY m_hDevNotify;
    /* Set up device notification (i.e. plug or unplug of HID Devices) */  
      
    /* 1) get the HID GUID */  
    HidD_GetHidGuid(&HidGuid);  
                  
    /* 2) clear the notification filter */  
    ZeroMemory( &NotificationFilter, sizeof(NotificationFilter));  
                  
    /* 3) assign the previously cleared structure with the correct data 
    so that the application is notified of HID device un/plug events */  
    NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);  
    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;  
    NotificationFilter.dbcc_classguid  = HidGuid;  
                  
  
  
    /* 4) register device notifications for this application */  
    m_hDevNotify = RegisterDeviceNotification(  this->GetSafeHwnd(),//AfxGetMainWnd()->m_hWnd,  
                                                &NotificationFilter,   
                                                DEVICE_NOTIFY_WINDOW_HANDLE);  
  
    /* 5) notify the calling procedure if the HID device will not be recognized */  
    if(!m_hDevNotify)
{
        return FALSE;
}
else
{
return TRUE;  
}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值