Dynamische Enumeration
Die dynamische Enumeration ist die Fähigkeit eines Treibers, Änderungen an der Anzahl und dem Typ der Geräte zu erkennen und zu melden, die während der Systemausführung mit dem System verbunden sind.
Bustreiber müssen eine dynamische Enumeration verwenden, wenn die Anzahl oder die Typen von Geräten, die mit dem übergeordneten Gerät verbunden sind, von der Konfiguration eines Systems abhängen. Einige dieser Geräte sind möglicherweise immer mit dem System verbunden, und einige werden möglicherweise ein- und getrennt, während das System ausgeführt wird.
Beispielsweise sind die Anzahl und der Typ der Geräte, die an den PCI-Bus eines Systems angeschlossen sind, systemabhängig, aber sie sind dauerhaft, es sei denn, ein Benutzer schaltet die Stromversorgung aus, öffnet das Gehäuse und fügt ein Gerät mithilfe eines Schraubenziehers hinzu oder entfernt es. Andererseits kann ein Benutzer USB-Geräte hinzufügen oder entfernen, indem er ein Kabel ein- oder aussteckt, während das System ausgeführt wird.
Dynamische untergeordnete Listen
Das Framework ermöglicht Treibern die Unterstützung der dynamischen Enumeration durch Bereitstellung von Frameworkobjekten für untergeordnete Listen. Jedes untergeordnete Listenobjekt stellt eine Liste der untergeordneten Geräte dar, die mit einem übergeordneten Gerät verbunden sind. Der Bustreiber für das übergeordnete Gerät muss die untergeordneten Geräte des übergeordneten Geräts identifizieren, sie der untergeordneten Liste des übergeordneten Geräts hinzufügen und ein physisches Geräteobjekt (PDO) für jedes untergeordnete Gerät erstellen.
Jedes Mal, wenn ein Treiber ein Frameworkgeräteobjekt erstellt, das eine FDO für ein Gerät darstellt, erstellt das Framework eine leere untergeordnete Standardliste für das Gerät. Ihr Treiber kann ein Handle für die untergeordnete Standardliste eines Geräts abrufen, indem er WdfFdoGetDefaultChildList aufruft. Wenn Sie einen Bustreiber schreiben, der die untergeordneten Elemente eines Geräts auflistet, kann Ihr Treiber der standardmäßigen untergeordneten Liste untergeordnete Elemente hinzufügen. Wenn Sie zusätzliche untergeordnete Listen erstellen müssen, kann Ihr Treiber WdfChildListCreate aufrufen.
Bevor ein Treiber eine untergeordnete Liste verwenden kann, muss er das untergeordnete Listenobjekt konfigurieren, indem er eine WDF_CHILD_LIST_CONFIG-Struktur initialisiert und die Struktur entweder an WdfFdoInitSetDefaultChildListConfig für die untergeordnete Standardliste oder an WdfChildListCreate für zusätzliche untergeordnete Listen übergeben.
Dynamische untergeordnete Beschreibungen
Jedes Mal, wenn ein Bustreiber ein untergeordnetes Gerät identifiziert, muss er die Beschreibung des untergeordneten Geräts einer untergeordneten Liste hinzufügen. Eine untergeordnete Beschreibung besteht aus einer erforderlichen Identifikationsbeschreibung und einer optionalen Adressbeschreibung.
Identifikationsbeschreibung Eine Identifikationsbeschreibung ist eine Struktur, die Informationen enthält, die jedes Gerät, das der Treiber aufzählt, eindeutig identifiziert. Der Treiber definiert diese Struktur, aber sein erstes Element muss eine WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER-Struktur sein.
In der Regel enthält eine Identifikationsbeschreibung die Geräteidentifikationszeichenfolgen eines Geräts, möglicherweise eine Seriennummer und Informationen zum Standort des Geräts auf dem Bus, z. B. eine Slotnummer.
Der Treiber kann die folgenden Rückruffunktionen bereitstellen, die es dem Framework ermöglichen, die Informationen in einer Identifikationsbeschreibung zu bearbeiten:
EvtChildListIdentificationDescriptionCompare, das den Inhalt zweier Identifikationsbeschreibungsstrukturen vergleicht.
EvtChildListIdentificationDescriptionCopy, das den Inhalt einer Identifikationsbeschreibungsstruktur in eine andere kopiert.
EvtChildListIdentificationDescriptionDuplicate, das eine neue Identifikationsbeschreibung erstellt, indem eine vorhandene Identifikationsbeschreibungsstruktur dupliziert und ggf. zusätzliche Puffer zugewiesen werden.
EvtChildListIdentificationDescriptionCleanup, das puffert, die von der Rückruffunktion EvtChildListIdentificationDescriptionDuplicate zugeordnet wurden.
In der Regel müssen Sie diese Rückruffunktionen bereitstellen, wenn die Identifikationsbeschreibungsstrukturen Ihres Treibers Zeiger auf dynamisch zugeordnete Puffer enthalten. Weitere Informationen zum Zweck dieser Rückruffunktionen finden Sie auf den Entsprechenden Referenzseiten.
Adressbeschreibung Eine Adressbeschreibung ist eine Struktur, die Informationen enthält, die der Treiber benötigt, damit er auf das Gerät auf seinem Bus zugreifen kann, wenn sich die Informationen ändern können, während das Gerät angeschlossen ist. Der Treiber definiert diese Struktur, aber sein erstes Element muss eine WDF_CHILD_ADDRESS_DESCRIPTION_HEADER-Struktur sein.
Adressbeschreibungen sind optional. Wenn sich die Adressinformationen eines Geräts zwischen dem Ein- und Ausstecken des Geräts nicht ändern können, können alle Adressinformationen des Geräts in einer Identifikationsbeschreibung gespeichert werden. Beispielsweise weisen USB-Controller Geräten Adressen zu, wenn die Geräte angeschlossen sind, und diese Adressen ändern sich nicht.
Andererseits verwenden einige Busse Adressinformationen, die sich ändern können. Der IEEE 1394-Bus verwendet beispielsweise eine "Generation Count", d. h. die Anzahl von Busrücksetzungen, die aufgetreten sind. Jede asynchrone E/A-Anforderung an ein IEEE 1394-Gerät muss die Anzahl der Generation enthalten. Da sich diese Adressinformationen ändern können, muss ihr Treiber sie in einer Adressbeschreibung speichern.
Der Treiber kann die folgenden Rückruffunktionen bereitstellen, um die Informationen in einer Adressbeschreibung zu bearbeiten:
EvtChildListAddressDescriptionCopy, das den Inhalt einer Adressbeschreibungsstruktur in eine andere kopiert.
EvtChildListAddressDescriptionDuplicate, das eine neue Adressbeschreibung erstellt, indem eine vorhandene Adressbeschreibungsstruktur dupliziert und ggf. zusätzliche Puffer zugewiesen werden.
EvtChildListAddressDescriptionCleanup, das puffert, die von der Rückruffunktion EvtChildListAddressDescriptionDuplicate zugewiesen wurden.
In der Regel müssen Sie diese Rückruffunktionen bereitstellen, wenn die Adressbeschreibungsstrukturen Ihres Treibers Zeiger auf dynamisch zugeordnete Puffer enthalten. Weitere Informationen zum Zweck dieser Rückruffunktionen finden Sie auf den Entsprechenden Referenzseiten.
Hinzufügen von Geräten zu einer dynamischen untergeordneten Liste
Wenn das Framework die Rückruffunktion EvtDriverDeviceAdd eines Bustreibers aufruft, muss die Rückruffunktion WdfDeviceCreate aufrufen, um eine FDO für das übergeordnete Gerät zu erstellen, bei dem es sich in der Regel um einen Busadapter handelt. Weitere Informationen zum Erstellen einer FDO finden Sie unter Erstellen von Geräteobjekten in einem Funktionstreiber. Der Treiber muss dann die untergeordneten Elemente des übergeordneten Geräts auflisten und die untergeordneten Elemente einer untergeordneten Liste hinzufügen.
Optional kann der Treiber WdfDeviceSetBusInformationForChildren aufrufen, um dem Framework Informationen zum Bus bereitzustellen. Dies wird empfohlen, da es für untergeordnete Geräte und Apps einfacher wird, den Bus zu identifizieren.
Um untergeordnete Elemente zu einer untergeordneten Liste hinzuzufügen, muss der Treiber WdfChildListAddOrUpdateChildDescriptionAsPresent für jedes untergeordnete Gerät aufrufen, das er findet. Dieser Aufruf informiert das Framework darüber, dass ein Treiber ein untergeordnetes Gerät ermittelt hat, das mit einem übergeordneten Gerät verbunden ist. Wenn Ihr Treiber WdfChildListAddOrUpdateChildDescriptionAsPresent aufruft, liefert er eine Identifikationsbeschreibung und optional eine Adressbeschreibung.
Nachdem der Treiber WdfChildListAddOrUpdateChildDescriptionAsPresent aufgerufen hat, um ein neues Gerät zu melden, informiert das Framework den PnP-Manager darüber, dass das neue Gerät vorhanden ist. Der PnP-Manager erstellt dann einen Gerätestapel und einen Treiberstapel für das neue Gerät. Im Rahmen dieses Prozesses ruft das Framework die Rückruffunktion EvtChildListCreateDevice des Bustreibers auf. Diese Rückruffunktion muss WdfDeviceCreate aufrufen, um ein PDO für das neue Gerät zu erstellen.
In der Regel sind mehrere untergeordnete Geräte mit einem übergeordneten Gerät verbunden, sodass der Bustreiber WdfChildListAddOrUpdateChildDescriptionAsPresent mehrmals aufrufen muss. Dies ist am effizientesten:
Rufen Sie WdfChildListBeginScan auf.
Rufen Sie WdfChildListAddOrUpdateChildDescriptionAsPresent für jedes untergeordnete Gerät auf.
Rufen Sie WdfChildListEndScan auf.
Wenn Sie die dynamische Enumeration Ihres Treibers mit Aufrufen von WdfChildListBeginScan und WdfChildListEndScan umgeben, speichert das Framework alle Änderungen an der untergeordneten Liste und benachrichtigt den PnP-Manager über die Änderungen, wenn der Treiber WdfChildListEndScan aufruft. Zu einem späteren Zeitpunkt ruft das Framework die EvtChildListCreateDevice-Rückruffunktion des Bustreibers für jedes Gerät in der untergeordneten Liste auf. Diese Rückruffunktion ruft WdfDeviceCreate auf, um ein PDO für jedes neue Gerät zu erstellen.
Wenn Ihr Treiber WdfChildListBeginScan aufruft, markiert das Framework alle zuvor gemeldeten Geräte als nicht mehr vorhanden. Daher muss der Treiber WdfChildListAddOrUpdateChildDescriptionAsPresent für alle untergeordneten Elemente aufrufen, die der Treiber erkennen kann, nicht nur neu ermittelte untergeordnete Elemente. Um einer untergeordneten Liste ein einzelnes untergeordnetes Element hinzuzufügen, kann der Treiber WdfChildListUpdateAllChildDescriptionsAsPresent aufrufen, ohne zuerst WdfChildListBeginScan aufzurufen.
Aktualisieren einer dynamischen untergeordneten Liste
Es gibt zwei gängige Möglichkeiten, die Informationen in einer dynamischen untergeordneten Liste zu aktualisieren:
Wenn ein übergeordnetes Gerät einen Interrupt empfängt, der das Ein- oder Entfernen eines untergeordneten Geräts angibt, ruft die EvtInterruptDpc-Rückruffunktion des Treibers WdfChildListAddOrUpdateChildDescriptionAsPresent auf, wenn ein Gerät angeschlossen wurde, oder WdfChildListUpdateChildDescriptionAsMissing , wenn ein Gerät getrennt wurde.
Der Treiber kann eine EvtChildListScanForChildren-Rückruffunktion bereitstellen, die das Framework jedes Mal aufruft, wenn das übergeordnete Gerät in seinen Arbeitszustand (D0) wechselt. Diese Rückruffunktion sollte alle untergeordneten Geräte aufzählen, indem WdfChildListBeginScan, WdfChildListAddOrUpdateChildDescriptionAsPresent (oder WdfChildListUpdateAllChildDescriptionsAsPresent) und WdfChildListEndScan aufgerufen werden.
Sie können eine oder beide dieser Techniken in Ihrem Treiber verwenden.
Durchlaufen einer dynamischen untergeordneten Liste
Wenn Der Treiber den Inhalt einer untergeordneten Liste untersuchen soll, kann er die Liste mit einer der folgenden Techniken durchlaufen:
Um den Inhalt der einzelnen untergeordneten Gerätebeschreibungen einzeln abzurufen, kann der Treiber Folgendes ausführen:
- Rufen Sie WdfChildListBeginIteration auf.
- Rufen Sie WdfChildListRetrieveNextDevice so oft wie nötig auf.
- Rufen Sie WdfChildListEndIteration auf.
Beim Aufrufen von WdfChildListBeginIteration gibt der Treiber ein WDF_RETRIEVE_CHILD_FLAGS typisiertes Flag an, das angibt, ob das Framework alle Gerätebeschreibungen oder nur eine Teilmenge abrufen soll. Wenn WdfChildListRetrieveNextDevice eine Übereinstimmung findet, ruft es die Identifikations- und Adressbeschreibungen des untergeordneten Geräts sowie ein Handle für das Geräteobjekt ab.
Wenn Sie die Adressbeschreibung abrufen müssen, die derzeit in einer untergeordneten Gerätebeschreibung enthalten ist, kann Ihr Treiber WdfChildListRetrieveAddressDescription aufrufen und eine Identifikationsbeschreibung angeben. Das Framework durchläuft die untergeordnete Liste, bis es ein untergeordnetes Gerät mit einer entsprechenden Identifikationsbeschreibung findet, und ruft dann die Adressbeschreibung ab.
Wenn Sie ein Handle für das Framework-Geräteobjekt abrufen müssen, das einem bestimmten untergeordneten Gerät zugeordnet ist, kann Ihr Treiber WdfChildListRetrievePdo aufrufen. Das Framework durchläuft die untergeordnete Liste, bis es ein untergeordnetes Gerät mit einer entsprechenden Identifikationsbeschreibung findet, und gibt dann ein Geräteobjekthandle zurück. Stellen Sie sicher, dass Sie den Aufruf mit WdfChildListBeginIteration und WdfChildListEndIteration umschließen , um den Aufrufer vor dem plötzlichen Entfernen des PDO in einem anderen Thread zu schützen.
Zugreifen auf die Identifikations- und Adressbeschreibungen einer PDO
Ihr Treiber kann die folgenden Methoden aufrufen, um auf die Identifikations- oder Adressbeschreibung eines PDO zuzugreifen:
WdfPdoRetrieveIdentificationDescription, die die Identifikationsbeschreibung abruft, die einer PDO zugeordnet ist.
WdfPdoRetrieveAddressDescription, die die Adressbeschreibung abruft, die einer PDO zugeordnet ist.
WdfPdoUpdateAddressDescription aktualisiert die Adressbeschreibung, die einem PDO zugeordnet ist.
Behandeln von Re-Enumerationsanforderungen
Frameworkbasierte Bustreiber, die dynamische Enumeration unterstützen, können eine Anforderung zum erneuten Auflisten eines bestimmten untergeordneten Geräts über die REENUMERATE_SELF_INTERFACE_STANDARD-Schnittstelle empfangen. Weitere Informationen finden Sie unter Behandeln von Enumerationsanforderungen.