1. 程式人生 > >USB學習筆記二《插拔檢測+示例程式碼》

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   A device has been inserted and is now available.

  • DBT_DEVICEQUERYREMOVE   Permission to remove a device is requested. Any application can deny this request and cancel the removal.

  • DBT_DEVICEREMOVEPENDING   Device is about to be removed. Cannot be denied.

  • DBT_CONFIGCHANGED   Current configuration has changed.

  • DBT_DEVNODES_CHANGED   Device node has changed.

//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;   } }

相關推薦

USB學習筆記檢測+示例程式碼

 USB熱插拔檢測:方法一:啟動定時器,定時輪詢登錄檔,這種方法容易宕機。 方法二: 註冊視窗,新增Windows訊息 ON_WM_DEVICECHANGE()對映。步驟: 一: 要想新增訊息對映,需改變三個地方:1、 視窗標頭檔案宣告訊息處理函式afx_msg BOOL

MFC學習筆記 — VC++中自動檢測串列埠熱事件

文章出處:(轉載文章,如有不妥,通知後我會立即刪除) 文章索引1 文章索引2 這裡主要利用Cwnd的ON_WM_DEVICECHANGE訊息來處理。 Windows作業系統傳送WM_DEVICECHANGE有些限制: 1、只有頂層窗體的程式才能收到這個訊息; 2、

opencv學習筆記十九:SIFT特徵點檢測與匹配

SIFT(Scale-invariant feature transform)是一種檢測區域性特徵的演算法,該演算法通過求一幅圖中的特徵點(interest points,or corner points)及其有關scale 和 orientation 的描述子得到特徵並進行

Unity學習筆記() 碰撞檢測與觸發檢測

正好看到了Roll a ball這個遊戲,於是就溫故一下碰撞檢測和觸發檢測 1.前期準備 中間省去建造一些基礎的物體的過程,最後呈現如下圖 我們的主角就是中間的球體 其GameObject名為player,我們在其身上添上剛體元件(Rigidbod

基於STM32的USB列舉過程學習筆記()

    接下來介紹USB裝置的列舉,列舉就是從裝置讀取各種描述符資訊,這樣主機就可以根據這些資訊來載入合適的驅動,從而知道是什麼樣的裝置,如何進行通訊。 列舉過程使用的是控制傳輸。控制傳輸可以保證資料的正確性。控制傳輸分三個過程:建立過程,可選資料過程及狀態過程。    

學習筆記)——基於opencv人臉檢測原理及實現

最近搞了幾天的人臉檢測,終於把大體框架和原理搞清楚了,現在寫出來供大家學習之用,如有不對之處,還請大家指正。也希望大家在學習opencv的過程中能將學習過程及重點記錄下來,以部落格的形式分析,畢竟opencv的教材還不太多,我們自己學習大部分要靠網上的資料。通過部落格分享的

USB裝置檢測

1)hub初始化時 hub_wq = alloc_workqueue(“usb_hub_wq”, WQ_FREEZABLE, 0); INIT_WORK(&hub->events, hub_event) queue_work(hub_wq, &am

USB轉串列埠熱檢測

         上位機與裝置進行串列埠通訊之前都需要指定PC通訊的串列埠號,這無疑給操作上帶來不便,更痛苦的是每次都得到裝置管理器檢視當前連線的串列埠。          那麼如何通過程式碼獲取當前可用串列埠列表?一是通種登錄檔獲取,操作比較複雜;微軟為我們提供更簡單

SpringMVC學習筆記:常用註解

title c學習 請求 pin 學習 lin att 詳解 stp 轉載請註明原文地址:http://www.cnblogs.com/ygj0930/p/6831976.html 一、用於定義類的註解:@Controller @Controller 用於標記在一個類上,

Scala學習筆記()(for循環相關)

spa nts multiple bool val turn 優化 n) 例子 Scala裏if...else語句 if語句不管是在哪種語言裏是使用最多的語句了. scala的if語句與java如出一轍. 舉個栗子就不再贅述: 一個 if 語句的語法: if(Boolean

ES6學習筆記()——字符串擴展

兩個 -m 開始 部分 學習筆記 erro xxx ocs 個數 相信很多人也和我一樣,不喜歡這樣循規蹈矩的逐條去學習語法,很枯燥乏味。主要是這樣學完一遍之後,沒過一段時間就忘到九霄雲外了。不如實際用到的時候研究它記得牢靠,所以我就整理成筆記,加深記憶的同時便於復習查看。

RabbitMQ基礎學習筆記(C#代碼示例

esp 輸出 出隊 csharp 實例代碼 為什麽 mode 規則 無需 一、定義: MQ是MessageQueue,消息隊列的簡稱(是流行的開源消息隊列系統,利用erlang語言開發)。MQ是一種應用程序對應用程序的通信方法。應用程序通過讀寫入隊和出隊的消息來通信

MySQL學習筆記(

發送 int 賦值 數據庫基礎知識 font 字符 需要 con spa -- 回顧 數據庫基礎知識: 關系型數據庫(磁盤),建立在關系模型上的數據庫,數據結構(二維表),浪費空間。 操作數據的指令集合:SQL(DDL,DML[DQL]和DCL) 完整性約束:表內和表之間(

Android第一行代碼學習筆記---在活動中使用Toast

一行代碼 就會 onclick log sta contex instance and undle Toast:是Android系統提供的一種非常好的提醒方式,在程序中可以使用它將一些短小的信息通知給用戶,這些信息會在一段時間後自動消失,並且不會占用任何屏幕空間。 首先需要

framework7學習筆記:基礎知識

部分 cnblogs query 基礎 logs code 自己 $$ pan 一:DOM7 framework7有自己的 DOM7 - 一個集成了大部分常用DOM操作的高性能庫。它的用法和jQuery幾乎是一樣的,包括大部分常用的方法和jquery風格的鏈式調用。 在開發

node.js學習筆記之版本問題

nodejs targe tle 下一個 .cn blank 網站 mage 功能 一、版本說明 進入node.js官網https://nodejs.org/en/download/ 點擊上面的【All download options】進入到所有下載列表的地址 下載地

Java基礎學習筆記 網絡編程

數據丟失 交互圖 主動 總結 交互 servers -- 處理 關閉 絡通信協議 通過計算機網絡可以使多臺計算機實現連接,位於同一個網絡中的計算機在進行連接和通信時需要遵守一定的規則,這就好比在道路中行駛的汽車一定要遵守交通規則一樣。在計算機網絡中,這些連接和通信的規則被

Java基礎學習筆記十三 Java核心語法之反射

負責 目錄 boolean tostring 筆記 str 編譯 三種 進制 類加載器 類的加載 當程序要使用某個類時,如果該類還未被加載到內存中,則系統會通過加載,鏈接,初始化三步來實現對這個類進行初始化。 加載就是指將class文件讀入內存,並為之創建一個Clas

Java基礎學習筆記十四 MySQL安裝圖解

password data 默認 count 重新 doc documents tran xp系統 、MYSQL的安裝 1、打開下載的mysql安裝文件mysql-5.5.27-win32.zip,雙擊解壓縮,運行“setup.exe”。

Java基礎學習筆記十七 DBUtils和連接池

ride 基本 代碼塊 ear 不同 一行 ria 靜態方法 ... DBUtils 如果只使用JDBC進行開發,我們會發現冗余代碼過多,為了簡化JDBC開發,本案例我們講采用apache commons組件一個成員:DBUtils。DBUtils就是JDBC的簡化開發工