Freigeben über


Serielle Bustreiberebene

Der serielle Bustreiber wird basierend auf einem von ACPI erstellten PDO geladen und kann die Systemressourcen, z. B. GPIO- und I2C-Controller, abfragen und darauf zugreifen, um die Signalsteuerung durchzuführen.

Beispielmechanismus für die Energiesteuerung

Bluetooth über USB verfügt über einen integrierten Mechanismus für In-Band-Signalisierung zur Unterstützung von Ruhe- und Aktivierungsfunktionen. In einer SoC-Plattform kann der Mechanismus zur Unterstützung der Stromversorgung jedoch flexibler (und anpassbar) mit verschiedenen Controllern sein.

Hier ist eine Beispielimplementierung, die die Leerlauf- und Aktivierungssignalisierung durchgeht:

  • Eine GPIO-Interrupt-Leitung HOST_WAKE – um dem Bluetooth-Controller zu signalisieren, wann er den Host aktivieren muss, um eine Anfrage von einem Remote-Gerät zu bearbeiten (z. B. eine Remote-Verbindung).
  • Eine GPIO-Signalleitung BT_ENABLE – wird von einem Bustreiber festgelegt und aktiviert, wenn das Radio aktiv ist (Kernstapel in D0) oder deaktiviert, wenn der Bluetooth-Kernstapel Leerlauf erkannt hat (Eintritt in D2).

Diese beiden GPIO-Linien in Form von Systemressourcen werden dem seriellen Bustreiber während des Treiberladens als regulärer Interrupt und neues GPIO-Signal gemeldet. Die Verbindungseigenschaften werden in der ACPI-Tabelle durch den Systemintegrator und den Bluetooth-Chipsatzanbieter (IHV) definiert. Ein serieller Bustreiber kann die Verbindungs-IDs dieses abhängigen Controllers abfragen und zwischenspeichern, um ihre Ressourcen zu öffnen und darauf zuzugreifen.

Starten, um den Leerlauf zu aktivieren

Der serielle Bustreiber ist erforderlich, um die folgenden Aufgaben für die Unterstützung des Leerlaufs im S0-Systemstromzustand auszuführen:

  1. Melden Sie PnP- und Energieverwaltungsfunktionen. Da es sich um ein integriertes Gerät handelt, sollte das entfernbare Flag für das untergeordnete PDO auf WdfFalse gesetzt werden.
  2. Melden Sie, dass es den Funktionstreiber (Bluetooth-Kerntreiber) im Leerlauf unterstützen kann.
  3. Behandeln Sie die Aktivierung und Deaktivierung zur Reaktivierung aus dem Ruhezustand und das Signal zur Reaktivierung.
  4. Erhalten Sie eine Benachrichtigung über den Energiestatus des Geräts und synchronisieren Sie den E/A-Abschluss mit dem aktuellen Energiestatus des Geräts.

Energieverwaltungsfunktionen

Das vom Bustreiber erstellte untergeordnete PDO legt die Stromversorgungsfunktionen fest, um die Unterstützung des Leerlaufzustands zu aktivieren. Das untergeordnete PDO wird vom Power Manager verwaltet und enthält Einstellungen zur Angabe von:

  • seiner Fähigkeit zur Unterstützung des D2-Gerätezustands.
  • seiner Fähigkeit, in den Leerlauf zu wechseln und aus D2 reaktiviert zu werden.
  • seiner Zuordnung des Systemzustands zu Gerätezuständen und die Synchronisierung mit dem Bluetooth-Kerntreiber.
WDF_DEVICE_POWER_CAPABILITIES_INIT(&PowerCaps);
…
PowerCaps.DeviceD1 = WdfFalse;
PowerCaps.DeviceD2 = WdfTrue;
…
PowerCaps.DeviceWake = PowerDeviceD2;

PowerCaps.DeviceState[PowerSystemWorking]   = PowerDeviceD0;
PowerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD2;
PowerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
PowerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
PowerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD2;
PowerCaps.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;
..
WdfDeviceSetPowerCapabilities(ChildDevice, &PowerCaps);

Das untergeordnete PDO erstellt eine WDF-Warteschlange zum Empfangen der IOCTL-Anforderung (E/A-Steuerelement) vom Bluetooth-Kerntreiber. Bei solchen Anfragen werden vor dem Start des Geräts die Schnittstellenversion und die statischen Fähigkeiten abgefragt. Aus diesem Grund darf diese Warteschlange nicht über eine Energieverwaltung verwaltet werden.

QueueConfig.PowerManaged = WdfFalse;

QueueConfig.EvtIoDeviceControl = PdoIoQuDeviceControl;

Status = WdfIoQueueCreate(ChildDevice, 
                          &QueueConfig, 
                          WDF_NO_OBJECT_ATTRIBUTES,
                          &Queue);

Spezifische Bluetooth-Transportabfrage für die Leerlauffunktion

Neben der Berichterstellung von Energieverwaltungsfunktionen (wie im vorherigen Abschnitt hervorgehoben) antwortet das untergeordnete PDO auch auf die Abfrage des Bluetooth-Kerntreibers, um in den Leerlaufzustand zu wechseln. Um den Leerlauf in S0 zu unterstützen, wird dieses Flag festgelegt:

FdoExtension->BthXCaps.IsDeviceIdleCapable = TRUE;

Aktivieren und Deaktivieren aus dem Ruhezustand

Voraussetzung für die Leerlaufunterstützung ist die Fähigkeit, eine Reaktivierungsanforderung von einem Remote-Bluetoothgerät zu empfangen. Die Einrichtung für eine solche Reaktivierungsanforderung umfasst die Aktivierung aus dem Ruhezustand. Das PDO für die Bluetooth-Funktion kann registriert werden, um Rückrufe zum Durchführen von Aktivierungs-/Deaktivierungsaktionen zu empfangen:

WDF_PDO_EVENT_CALLBACKS_INIT(&Callbacks);

// Receive this callback to arming the device for wake
Callbacks.EvtDeviceEnableWakeAtBus  = PdoDevEnableWakeAtBus;

// Receive this callback to disarming the device for wake
Callbacks.EvtDeviceDisableWakeAtBus = PdoDevDisableWakeAtBus;

WdfPdoInitSetEventCallbacks(DeviceInit, &Callbacks);

Wenn die oben genannten Mechanismen unterstützt werden, kann der Bluetooth-Kerntreiber dann die Leerlauf- und Aktivierungsunterstützung aktivieren.

Benachrichtigung über den Energiestatus des Geräts

Untergeordnete PDO-Register erhalten einen Rückruf, um zu D0 zu wechseln und es zu verlassen, um über den Übergang des Gerätestromversorgungszustands benachrichtigt zu werden. Der aktuelle Gerätestromzustand wird verwendet, um den E/A-Abschluss zu synchronisieren – d. h., der normale E/A-Abschluss sollte nur in D0 abgeschlossen werden.

    //
    // Register to receive device power state change notification
    //
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);  

    PnpPowerCallbacks.EvtDeviceD0Entry = PdoDevD0Entry;
    PnpPowerCallbacks.EvtDeviceD0Exit  = PdoDevD0Exit; 

    
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, 
                                           &PnpPowerCallbacks);

Aus Ruhemodus aktivieren

Vor dem Wechsel in den Leerlauf erhält der serielle Bustreiber den Rückruf EvtDeviceEnableWakeAtBus zur Aktivierung aus dem Ruhezustand.

Der Mechanismus zur Aktivierung ist anbieterspezifisch für SoC-Plattformen und liegt somit außerhalb des Umfangs dieses Abschnitts. Windows erwartet jedoch, dass der Bustreiber bereit ist, ein Aktivierungssignal zu empfangen, und dass eine Rückruffunktion (z. B. ISR) vorhanden ist, um ein solches Signal zu verarbeiten.

In den Leerlauf wechseln

Der Bluetooth-Kerntreiber ermöglicht einen zeitbasierten Leerlauferkennungsmechanismus. Wenn die Leerlaufanforderungen erfüllt sind, beginnt der Kerntreiber mit der Initialisierung des Stapels, um in den Leerlaufzustand zu wechseln. Er ruft PoRequestPowerIrp auf, um die Leistung festzulegen, um zusammen mit einer Vervollständigungsfunktion zu D2 zu wechseln. Nachdem der Bustreiber das IRP abgeschlossen hat, wird diese Vervollständigungsfunktion aufgerufen. Zu diesem Zeitpunkt ist der Übergang zu D2 abgeschlossen.

Beim Übergang in den Leerlaufzustand bricht der Bluetooth-Kerntreiber alle ausstehenden Leseanforderungen ab und startet sie neu, wenn er wieder aktiv wird. Damit der serielle Bustreiber selbst in den Leerlauf wechseln kann, ist eine leere, stromverwaltete Warteschlange erforderlich.

Zusätzlich zum Leerlauftimeout berücksichtigt der Bluetooth-Kerntreiber viele verschiedene Situationen, bevor er in den Leerlaufzustand wechselt, z. B.:

  • Er wartet auf den Abschluss eines HCI-Befehls, den er ausgestellt hat. Hinweis: Der Bluetooth-Kerntreiber wechselt erst nach Abschluss in den Leerlauf.
  • Alle verbundenen Geräte befinden sich im Ermittlungsmodus.

In diesem Leerlaufzustand kann der Multifunktionscontroller seine Leistung durch die Bluetooth-Funktion drosseln, muss aber weiterhin Strom liefern, um seine flüchtigen Einstellungen und Konfigurationen beizubehalten. Anschließend kann er mithilfe seines Aktivierungsmechanismus den Stapel wieder in den aktiven Zustand (D0) wecken, wonach die E/A-Kommunikation fortgesetzt werden kann.

Aus dem Ruhezustand aktivieren

Während die Bluetooth-Funktion mit einem oder mehreren Geräten gekoppelt ist und sich im Ruhezustand befindet, sucht ihr Funk regelmäßig nach Anfragen von den gekoppelten Geräten. Wenn ein gekoppeltes Gerät eine Anforderung initiiert und vom Bluetooth-Funk empfangen wird, beginnt der Prozess zum Fortsetzen des aktiven Zustands. Sobald der Gerätestapel aktiv (D0) fortgesetzt wurde, können die Treiber mit der Wartung dieser Remoteanforderung beginnen.

Diese Remote-Anforderung wird von der Verarbeitungsfunktion des Aktivierungssignals im Bustreiber verarbeitet, wie im letzten Abschnitt beschrieben. Diese Verarbeitungsfunktion des Aktivierungssignals soll sicherstellen, dass der Gerätezustand des PDO tatsächlich im D2-Zustand ist und dann WdfDeviceIndicateWakeStatus (PDO, success status) aufrufen, um KMDF zu benachrichtigen, dass das W/W (Wait Wake) IRP abgeschlossen werden soll. Zu diesem Zeitpunkt kann die Abschlussfunktion dieses W/W-IRP aufgerufen und von seinem Initiator – dem Bluetooth-Kerntreiber und dem Besitzer der Energierichtlinie – verarbeitet werden.

Der Abschluss des W/W IRP löst den Bluetooth-Kerntreiber aus, um einen Übergang zu D0 zu initiieren. Er fordert PoRequestPowerIrp mit einer Abschlussfunktion an, um den Geräteenergiestatus auf D0 zu setzen.

Vor der Wiederaufnahme des aktiven D0-Zustands erhält der serielle Bustreiber möglicherweise eine Benachrichtigung EvtDeviceDisableWakeAtBus. Damit ist der Vorgang zur Umkehrung dessen, was EvtDeviceEnableWakeAtBus zuvor getan hat, abgeschlossen.

Nachdem der Bluetooth-Treiberstapel auf D0 fortgesetzt wird, kann der serielle Bustreiber die Remote-Geräteanforderung abschließen.

Einige Ereignisse müssen im seriellen Bustreiber synchronisiert werden, z. B.:

  • Beim Wechsel zu D2 sollte bereits ein ausstehendes W/W Irp vorhanden sein. Dies ist der Zeitpunkt, zu dem die Aktivierung zum Empfangen des Aktivierungssignals erfolgen sollte, und nicht beim Empfangen eines W/W Irp. Das Aktivierungssignal kann nur im D2-Zustand ausgeführt werden.
  • Wenn Daten beim Eintritt in D2 eingehen (um ein Paket zu bilden) und keine ausstehende Leseanforderung in der Warteschlange vorhanden ist, kann der Bustreiber die eingehenden Daten zwischenspeichern und zu D2 wechseln. Anschließend kann der W/W-IRP (erfolgreich) abgeschlossen werden, um das System wieder in D0 zu aktivieren und die Lese-Anforderung erneut zu senden und abzuschließen.
  • Bthport bricht alle ausstehenden Leseanforderungen ab und wartet vor dem Eintritt in D2 auf den Abschluss. Gleichzeitig hat der serielle Bustreiber möglicherweise ein vollständiges HCI-Paket empfangen und eine Lese-Anforderung aus der Warteschlange genommen, um dieses HCI-Paket zurückzugeben. Der serielle Bustreiber sollte diese Anforderung abschließen und kann dann zu D2 wechseln.

Eine von einer Bluetooth-Anwendung auf der Hostseite initiierte Aktion kann den Stapel auch aus dem Leerlauf aktivieren. In diesem Fall ist nur der Übergang des Gerätestromversorgungszustands erforderlich und diese Aktion wird vom Bluetooth-Kerntreiber initiiert.

Um die Einschaltzeit zu verkürzen, sollten die Rückruffunktionen (z. B. EnterD0 und Wake) im seriellen Bustreiber nicht als auslagerbar gekennzeichnet werden.

Ein Flussdiagramm zur Darstellung der Zustandsübergänge Leerlauf/Aktivieren, Aktivieren/Deaktivieren und Gerätestrom

Im Folgenden finden Sie ein vereinfachtes Flussdiagramm, das eine typische Sequenz und Logik für die Leerlauf- und Aktivierungsunterstützung veranschaulicht. Diese Logik erstreckt sich über viele Treiber und Threads, und es gibt Ausnahmen sowie Sonderfälle, die nicht ausdrücklich erwähnt werden (beispielsweise kann eine Anwendung auf der Hostseite den Stapel auch aus dem Leerlaufzustand aktivieren).

Flussdiagramm zur Veranschaulichung von Bluetooth-Geräte-Energiezustandsübergängen für Leerlauf- und Aktivierungsunterstützung.

Eigene Energieverwaltung des Bustreibers

Der serielle Bustreiber ist ein Funktionstreiber (FD) und der Power Policy Owner (PPO) seiner Ebene. Daher muss er seine eigene Energieverwaltung bewältigen. Nachdem alle untergeordneten Geräte in einen niedrigeren Energiesparzustand gewechselt sind, kann das Gerät selbst in einen niedrigeren Energiesparzustand wechseln. Wenn der Treiber bereit ist, in diesen Zustand mit geringerem Stromverbrauch zu wechseln, kann er alle ausstehenden E/A-Anfragen an den UART-Controller-Treiber abbrechen. Dadurch kann auch der UART-Treiber in einen Zustand mit geringerem Stromverbrauch wechseln. Der UART-Treiber sollte jedoch die Geräteeinstellungen (einschließlich der Baudrate) beibehalten und wiederherstellen, wenn der Energiezustand später wieder aktiv fortgesetzt wird.