動態列舉
動態列舉 是驅動程式偵測及報告在系統執行時連線至系統之裝置數目和類型變更的能力。
如果連線到父裝置的裝置數目或類型取決於系統的設定,匯流排驅動程式就必須使用動態列舉。 其中有些裝置可能一律連線到系統,有些裝置可能會在系統執行時插入和取消叢集。
例如,插入系統 PCI 匯流排的裝置數目和類型與系統相依,但除非使用者關閉電源、開啟案例,以及使用螺絲起子來新增或移除裝置,否則它們是永久的。 另一方面,使用者可以在系統執行時插入或取消連接纜線,來新增或移除 USB 裝置。
動態子清單
架構可讓驅動程式藉由提供架構子清單物件來支援動態列舉。 每個子清單物件都代表連接到父裝置的子裝置清單。 父裝置的匯流排驅動程式必須識別父裝置的子裝置、將它們新增至父裝置的子清單,以及為每個子系建立實體裝置物件 (PDO) 。
每次驅動程式建立代表裝置 FDO 的架構裝置物件時,架構都會為裝置建立空白的預設子清單。 驅動程式可以藉由呼叫 WdfFdoGetDefaultChildList來取得裝置預設子清單的控制碼。 一般而言,如果您要撰寫列舉裝置子系的匯流排驅動程式,您的驅動程式可以將子系新增至預設子清單。 如果您需要建立其他子清單,驅動程式可以呼叫 WdfChildListCreate。
在驅動程式可以使用子清單之前,它必須先初始化 WDF_CHILD_LIST_CONFIG結構, 並將結構傳遞至 WdfFdoInitSetDefaultChildListConfig、預設子清單或 WdfChildListCreate,來設定子清單物件。
動態子描述
每次匯流排驅動程式識別子裝置時,都必須將子裝置的描述新增至子清單。 子描述是由必要的識別描述和選擇性位址描述所組成。
識別描述 識別描述是一種結構,其中包含可唯一識別驅動程式列舉之每個裝置的資訊。 驅動程式會定義這個結構,但其第一個成員必須是 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER 結構。
一般而言,識別碼描述包含裝置的 裝置識別碼字串、可能是序號,以及有關匯流排上裝置位置的資訊,例如插槽號碼。
驅動程式可以提供下列一組回呼函式,讓架構能夠操作識別描述中的資訊:
EvtChildListIdentificationDescriptionCompare,它會比較兩個識別描述結構的內容。
EvtChildListIdentificationDescriptionCopy,它會將一個識別描述結構的內容複寫到另一個識別描述結構。
EvtChildListIdentificationDescriptionDuplicate,它會藉由複製現有的識別描述結構來建立新的識別描述,並視需要配置其他緩衝區。
EvtChildListIdentificationDescriptionCleanup,它會解除配置 EvtChildListIdentificationDescriptionDuplicate 回呼函式所配置的緩衝區。
一般而言,如果驅動程式的識別描述結構包含動態配置緩衝區的指標,您將需要提供這些回呼函式。 如需這些回呼函式用途的詳細資訊,請參閱其參考頁面。
位址描述 位址描述是一種結構,其中包含驅動程式所需的資訊,以便在裝置插入時變更裝置時存取其匯流排上的裝置。 驅動程式會定義這個結構,但其第一個成員必須是 WDF_CHILD_ADDRESS_DESCRIPTION_HEADER 結構。
位址描述是選擇性的。 如果裝置的位址資訊無法在裝置插入和取消叢集的時間之間變更,則所有裝置的位址資訊都可以儲存在識別碼描述中。 例如,USB 控制器會在裝置插入時將位址指派給裝置,而且這些位址不會變更。
另一方面,有些匯流排會使用可變更的定址資訊。 例如,IEEE 1394 匯流排使用「世代計數」,也就是已發生的匯流排重設數目。 IEEE 1394 裝置的每個非同步 I/O 要求都必須包含產生計數。 因為此位址資訊可能會變更,所以您的驅動程式必須將它儲存在位址描述中。
驅動程式可以提供下列一組回呼函式,以操作位址描述中的資訊:
EvtChildListAddressDescriptionCopy,它會將一個位址描述結構的內容複寫到另一個位址描述結構。
EvtChildListAddressDescriptionDuplicate,它會複製現有的位址描述結構,並視需要配置其他緩衝區來建立新的位址描述。
EvtChildListAddressDescriptionCleanup,它會解除配置 EvtChildListAddressDescriptionDuplicate 回呼函式所配置的緩衝區。
一般而言,如果您的驅動程式的位址描述結構包含動態配置的緩衝區指標,您將需要提供這些回呼函式。 如需這些回呼函式用途的詳細資訊,請參閱其參考頁面。
將裝置新增至動態子清單
當架構呼叫匯流排驅動程式的 EvtDriverDeviceAdd 回呼函式時,回呼函式必須呼叫 WdfDeviceCreate 來建立父裝置的 FDO,這通常是匯流排介面卡。 如需建立 FDO 的詳細資訊,請參閱 在函式驅動程式中建立裝置物件。 驅動程式接著必須列舉父裝置的子系,並將子系新增至子清單。
或者,驅動程式可以呼叫 WdfDeviceSetBusInformationForChildren 來提供架構與匯流排的相關資訊。 建議這樣做,因為它可讓您更輕鬆地讓子裝置和應用程式識別公車。
若要將子系新增至子清單,驅動程式必須針對找到的每個子裝置呼叫 WdfChildListAddOrUpdateChildDescriptionAsPresent 。 此呼叫會通知架構驅動程式已探索到連接到父裝置的子裝置。 當您的驅動程式呼叫 WdfChildListAddOrUpdateChildDescriptionAsPresent時,它會提供識別描述,並選擇性地提供位址描述。
驅動程式呼叫 WdfChildListAddOrUpdateChildDescriptionAsPresent 來報告新裝置之後,架構會通知 PnP 管理員新裝置存在。 接著,PnP 管理員會為新裝置建置裝置堆疊和驅動程式堆疊。 在此程式中,架構會呼叫匯流排驅動程式的 EvtChildListCreateDevice 回呼函式。 此回呼函式必須呼叫 WdfDeviceCreate ,以建立新裝置的 PDO。
一般而言,數個子裝置會連線到父系,因此匯流排驅動程式需要呼叫 WdfChildListAddOrUpdateChildDescriptionAsPresent 數次。 執行這項操作最有效率的方式如下:
針對每個子裝置呼叫 WdfChildListAddOrUpdateChildDescriptionAsPresent 。
如果您以呼叫 WdfChildListBeginScan 和 WdfChildListEndScan 括住驅動程式的動態列舉,架構會將所有變更儲存到子清單,並在驅動程式呼叫WdfChildListEndScan時通知 PnP 管理員變更。 在稍後,架構會針對子清單中的每個裝置呼叫匯流排驅動程式的 EvtChildListCreateDevice 回呼函式。 此回呼函式會呼叫 WdfDeviceCreate ,為每個新裝置建立 PDO。
當您的驅動程式呼叫 WdfChildListBeginScan時,架構會將所有先前回報的裝置標示為不再存在。 因此,驅動程式必須針對驅動程式可以偵測的所有子系呼叫 WdfChildListAddOrUpdateChildDescriptionAsPresent ,而不只是新探索到的子系。 若要將單一子系新增至子清單,驅動程式可以對 WdfChildListUpdateAllChildDescriptionsAsPresent 進行單一呼叫,而不需要先呼叫 WdfChildListBeginScan。
更新動態子清單
有兩種常見方式可以更新動態子清單中的資訊:
當父裝置收到指出子系抵達或移除的中斷時,如果裝置已取消插入或移除WdfChildListUpdateChildListAddOrUpdateChildDescriptionAsPresent,則驅動程式的EvtInterruptDpc回呼函式會呼叫WdfChildListUpdAteChildDescriptionAsMissing。
驅動程式可以提供 EvtChildListScanForChildren 回呼函式,此函式會在每次父裝置進入其運作 (D0) 狀態時呼叫該函式。 此回呼函式應該藉由呼叫 WdfChildListBeginScan、 WdfChildListAddOrUpdateChildDescriptionAsPresent (或 WdfChildListUpdateAllChildDescriptionsAsPresent) 和 WdfChildListEndScan來列舉所有子裝置。
您可以在驅動程式中使用其中一種或兩種技術。
周遊動態子清單
如果您想要讓驅動程式檢查子清單的內容,可以使用下列其中一種技術來周遊清單:
若要取得每個子裝置描述的內容,一次一個,驅動程式可以:
呼叫 WdfChildListBeginIteration時,驅動程式會指定 WDF_RETRIEVE_CHILD_FLAGS類型的旗標,指出架構應該擷取所有裝置描述,還是只擷取子集。 當 WdfChildListRetrieveNextDevice 找到相符專案時,它會擷取子裝置的識別和位址描述,以及其裝置物件的控制碼。
如果您需要取得目前包含在子裝置描述中的位址描述,您的驅動程式可以呼叫 WdfChildListRetrieveAddressDescription,並指定識別碼描述。 架構會周遊子清單,直到找到具有相符識別碼描述的子裝置為止,然後擷取位址描述。
如果您需要取得與特定子裝置相關聯之架構裝置物件的控制碼,驅動程式可以呼叫 WdfChildListRetrievePdo。 架構會周遊子清單,直到找到具有相符識別描述的子裝置為止,然後傳回裝置物件控制碼。 請務必使用 WdfChildListBeginIteration 和 WdfChildListEndIteration 包裝呼叫,以防止呼叫端在另一個執行緒上突然移除 PDO。
存取 PDO 的識別和位址描述
您的驅動程式可以呼叫下列方法來存取 PDO 的識別描述或位址描述:
WdfPdoRetrieveIdentificationDescription,它會擷取與 PDO 相關聯的識別碼描述。
WdfPdoRetrieveAddressDescription,它會擷取與 PDO 相關聯的位址描述。
WdfPdoUpdateAddressDescription,它會更新與 PDO 相關聯的位址描述。
處理重新列舉要求
支援動態列舉的架構型匯流排驅動程式可以接收透過 REENUMERATE_SELF_INTERFACE_STANDARD 介面繼續特定子裝置的要求。 如需詳細資訊,請參閱 處理列舉要求