Windows驅動之PNP狀態轉換
即插即用(Plug and Play – PnP)管理器使用主功能碼爲IRP_MJ_PNP
的IRP與設備驅動程序交換信息和請求。
在WDM中,PnP請求扮演了兩個角色。
- 在第一個角色中,這些請求指示驅動程序何時以及如何配置或取消其硬件或自身的設置。
- PnP管理器使用
IRP_MN_START_DEVICE
來通知功能驅動程序其硬件被賦予了什麼I/O資源,以及指導功能驅動程序做任何必要的硬件或軟件設置以便設備能正常工作。 IRP_MN_STOP_DEVICE
告訴功能驅動程序關閉設備。IRP_MN_REMOVE_DEVICE
告訴功能驅動程序關閉設備並釋放與之關聯的設備對象
- PnP管理器使用
- PnP請求的第二個角色是指導驅動程序完成一系列狀態轉換。
- WORKING和STOPPED是設備的兩個基本狀態。
- 當你創建設備對象後,設備就立即進入STOPPED狀態。
- WORKING狀態指出設備是全部可操作的。
- 此外,還有兩個中間狀態,PENDINGSTOP和PENDINGREMOVE,它們出現在WORKING狀態前。
- SURPRISEREMOVED發生在物理硬件突然被移去的情況下。
我們先來看IRP_MJ_PNP
的副功能碼.
1. IRP_MN_XXX
IRP_MJ_PNP
的副功能碼有如下這些:
IRP副功能碼 | 描述 |
---|---|
IRP_MN_START_DEVICE |
配置並初始化設備 |
IRP_MN_QUERY_REMOVE_DEVICE |
設備可以被安全地刪除嗎? |
IRP_MN_REMOVE_DEVICE |
關閉並刪除設備 |
IRP_MN_CANCEL_REMOVE_DEVICE |
忽略以前的QUERY_REMOVE |
IRP_MN_STOP_DEVICE |
關閉設備 |
IRP_MN_QUERY_STOP_DEVICE |
設備可以被安全地關閉嗎? |
IRP_MN_CANCEL_STOP_DEVICE |
忽略以前的QUERY_STOP |
IRP_MN_QUERY_DEVICE_RELATIONS |
給出與指定特徵相關的設備列表 |
IRP_MN_QUERY_INTERFACE |
獲得直接調用函數地址 |
IRP_MN_QUERY_CAPABILITIES |
取設備能力 |
IRP_MN_QUERY_RESOURCES* |
取引導配置 |
IRP_MN_QUERY_RESOURCE_REQUIREMENTS* |
取I/O資源需求 |
IRP_MN_QUERY_DEVICE_TEXT* |
獲得描述信息或位置串 |
IRP_MN_FILTER_RESOURCE_REQUIREMENTS |
修改I/O資源需求列表 |
IRP_MN_READ_CONFIG* |
讀配置空間 |
IRP_MN_WRITE_CONFIG* |
寫配置空間 |
IRP_MN_EJECT* |
彈出設備 |
IRP_MN_SET_LOCK* |
設備彈出鎖定/解除 |
IRP_MN_QUERY_ID* |
取設備硬件ID |
IRP_MN_QUERY_PNP_DEVICE_STATE |
取設備狀態 |
IRP_MN_QUERY_BUS_INFORMATION* |
取父總線類型 |
IRP_MN_DEVICE_USAGE_NOTIFICATION |
通知分頁、dump、睡眠文件被創建或刪除 |
IRP_MN_SURPRISE_REMOVAL |
通知設備已經被刪除 |
2. 狀態轉換
PNP設備的狀態圖如下:
2.1 Not Present
- 首先,當設備沒有插入的時候,屬於NotPresent狀態,這個時候這個狀態唯一可以轉換的是插入設備,進入Stopped狀態。
- 其次,如果設備插入之後被拔出了,那麼這個狀態也會回到NotPresent狀態,拔出的時候會受到REMOVE_DEVICE的消息。
2.2 Stopped
- 當設備插入的時候,調用AddDevice創建一個功能性的設備對象來處理功能,這個時候,設備的狀態就是Stopped,表明這個設備並沒有開始工作。
- 如果一個正在處於工作狀態的設備,如果停止的話,就會收到一個STOP_DEVICE的消息。
- 在working和stop中間,有一個pendingstop的狀態,表明開始請求停止設備,在pendingstop狀態下,可以cancel_stop_device,也可以stop_device.
2.3 working
- 當一個stop的設備,調用Start_Device之後,這個設備就處於working狀態了,說明這個設備可以相應所有請求了。
- 一個woring的設備,可以stop_device將設備停止,此時設備狀態爲stopped狀態。
- 當然如果一個working的設備之間被拔出,那麼通過remove_device將設備變成拔出狀態。