動態列舉
動態列舉 是驅動程式偵測和報告在系統執行時連線到系統之裝置數目和類型變更的能力。
如果連接到父裝置的裝置數目或類型取決於系統的組態,則總線驅動程式必須使用動態列舉。 其中有些裝置可能始終連接到系統,有些裝置可能會在系統運行時被插入或拔出。
例如,系統的 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 數次。 執行此程式最有效率的方式如下:
如果您以呼叫 WdfChildListBeginScan 和 WdfChildListEndScan括住驅動程式的動態列舉,架構會儲存子清單的所有變更。 當驅動程式呼叫 WdfChildListEndScan時,它會通知 PnP 管理員變更。 稍後,架構會呼叫總線驅動程式的 EvtChildListCreateDevice 子清單中每個裝置的回呼函式。 此回呼函式會呼叫 WdfDeviceCreate,為每個新裝置建立 PDO。
當您的驅動程式呼叫 WdfChildListBeginScan時,架構會將所有先前報告的裝置標示為不存在。 因此,驅動程式必須為驅動程式可偵測的所有子系呼叫 WdfChildListAddOrUpdateChildDescriptionAsPresent,而不僅僅是新發現的子系。 若要將單一子項添加到子項列表,驅動程式可以單次呼叫 WdfChildListUpdateAllChildDescriptionsAsPresent,而無需先呼叫 WdfChildListBeginScan。
更新動態子清單
若要更新動態子清單中的資訊,請使用下列其中一種方法:
當父裝置收到表示子裝置抵達或移除的中斷時,如果裝置已插入,驅動程式的 EvtInterruptDpc 回呼函式會呼叫 WdfChildListAddOrUpdateChildDescriptionAsPresent;如果裝置已拔除,則呼叫 WdfChildListUpdateChildDescriptionAsMissing。
驅動程式可以提供 EvtChildListScanForChildren 回呼函式,每當父裝置進入其工作(D0)狀態時,框架都會呼叫此函式。 此回呼函式應該藉由呼叫 WdfChildListBeginScan、WdfChildListAddOrUpdateChildDescriptionAsPresent (或 WdfChildListUpdateAllChildDescriptionsAsPresent] 和 WdfChildListEndScan來列舉所有子裝置。
您可以在驅動程式中使用其中一種或兩種技術。
遍歷動態子列表
若要檢查子清單的內容,您的驅動程式可以使用下列其中一種技術來遍歷清單:
若要一次取得每個子裝置描述的內容,驅動程式可以:
呼叫 WdfChildListBeginIteration時,驅動程式會指定 WDF_RETRIEVE_CHILD_FLAGS型別旗標,指出架構是否應該擷取所有裝置描述或只擷取子集。 WdfChildListRetrieveNextDevice 找到符合條件的子裝置時,它會擷取子裝置的識別和位址描述,以及其裝置物件的控制代碼。
若要取得目前包含在子裝置描述中的位址描述,您的驅動程式可以呼叫 WdfChildListRetrieveAddressDescription,並指定識別描述。 架構會遍歷子清單,直到找到具有相符識別描述的子裝置為止。 然後,它會擷取位址描述。
如果您需要取得與特定子裝置相關聯的框架設備物件的控制代號,驅動程式可以呼叫 WdfChildListRetrievePdo。 架構會搜尋子清單,直到找到具有相符識別描述的子裝置為止,然後傳回裝置物件控制代碼。 若要保護呼叫端免於在另一個執行緒上突然移除 PDO,請將呼叫用 WdfChildListBeginIteration 包覆,並用 WdfChildListEndIteration結束。
存取 PDO 的識別和位址描述
您的驅動程式可以呼叫下列方法來存取 PDO 的識別描述或位址描述:
WdfPdoRetrieveIdentificationDescription,它會擷取與 PDO 相關聯的識別描述。
WdfPdoRetrieveAddressDescription,它會擷取與 PDO 相關聯的位址描述。
WdfPdoUpdateAddressDescription,它會更新與 PDO 相關聯的位址描述。
處理重新列舉要求
支援動態列舉的架構型總線驅動程式可以接收到透過 REENUMERATE_SELF_INTERFACE_STANDARD 介面重新列舉特定子裝置的請求。 如需詳細資訊,請參閱 處理列舉要求。