Freigeben über


SerCx2-Custom-Receive-Transaktionen

Einige serielle Controllerhardware kann einen anderen Datenübertragungsmechanismus als PIO oder System-DMA zum Lesen von Daten aus einem seriellen Controller implementieren. Ein serieller Controllertreiber kann benutzerdefinierte Empfangstransaktionen unterstützen, um diesen Datenübertragungsmechanismus für die Verwendung von SerCx2 verfügbar zu machen.

Um eine benutzerdefinierte Empfangstransaktion zu starten, ruft SerCx2 die Ereignisrückruffunktion EvtSerCx2CustomReceiveTransactionStart des Treibers auf und stellt als Parameter die Leseanforderung (IRP_MJ_READ) und eine Beschreibung des Lesepuffers für die Transaktion bereit. In diesem Aufruf initiiert die Funktion die Transaktion und gibt zurück. Der Treiber ist dann für den Abschluss der Transaktion und das Abschließen der Leseanforderung verantwortlich.

Erstellen des benutzerdefinierten Empfangsobjekts

Bevor SerCx2 eine der EvtSerCx2CustomReceiveTransactionXxx**-Funktionen des seriellen Controllertreibers aufrufen kann, muss der Treiber die SerCx2CustomReceiveTransactionCreate-Methode aufrufen, um diese Funktionen bei SerCx2 zu registrieren. Diese Methode akzeptiert als Eingabeparameter einen Zeiger auf eine SERCX2_CUSTOM_RECEIVE_TRANSACTION_CONFIG-Struktur , die Zeiger auf die EvtSerCx2CustomReceiveTransaction-Xxx**-Funktionen des Treibers enthält.

Der Treiber muss die folgenden beiden Funktionen implementieren:

Optional kann der Treiber eine oder alle der folgenden drei Funktionen implementieren:

Die SerCx2CustomReceiveTransactionCreate-Methode erstellt ein benutzerdefiniertes Empfangsobjekt und stellt dem aufrufenden Treiber ein SERCX2CUSTOMRECEIVETRANSACTION-Handle für dieses Objekt bereit. Die EvtSerCx2CustomReceiveTransactionXxx**-Funktionen des Treibers verwenden alle diesen Handle als ersten Parameter. Die folgenden SerCx2-Methoden verwenden dieses Handle als ersten Parameter:

Hardwareinitialisierung und sauber

Einige serielle Controllertreiber müssen möglicherweise die Hardware des seriellen Controllers zu Beginn einer benutzerdefinierten Empfangstransaktion initialisieren oder den Hardwarestatus des seriellen Controllers am Ende der Transaktion sauber.

Wenn ein Treiber eine EvtSerCx2CustomReceiveTransactionInitialize-Ereignisrückruffunktion implementiert, ruft SerCx2 diese Funktion auf, um den seriellen Controller vor dem Starten der Transaktion zu initialisieren. Bei Implementierung muss die EvtSerCx2CustomReceiveTransactionInitialize-Funktion die SerCx2CustomReceiveTransactionInitializeComplete-Methode aufrufen, um SerCx2 darüber zu informieren, wenn der Treiber die Initialisierung des seriellen Controllers abgeschlossen hat.

Wenn der Treiber eine EvtSerCx2CustomReceiveTransactionCleanup-Ereignisrückruffunktion implementiert, ruft SerCx2 diese Funktion auf, um den Hardwarestatus nach Abschluss der Transaktion zu sauber. Falls implementiert, muss die EvtSerCx2CustomReceiveTransactionInitialize-Funktion die SerCx2CustomReceiveTransactionCleanupComplete-Methode aufrufen, um SerCx2 darüber zu informieren, wenn der Treiber das Bereinigen des seriellen Controllers abgeschlossen hat.

New-Data-Benachrichtigungen

Optional kann der serielle Controllertreiber eine Rückruffunktion des Ereignisses EvtSerCx2CustomReceiveTransactionEnableNewDataNotification implementieren. Falls implementiert, verwendet SerCx2 diese Funktion, um Intervalltimeouts effizient zu verwalten, die während der Behandlung von Leseanforderungen auftreten, die als benutzerdefinierte Empfangstransaktionen verarbeitet werden.

Ein Intervalltimeout tritt auf, wenn das Intervall zwischen zwei aufeinanderfolgenden Bytes, die vom seriellen Controller empfangen werden, eine vom Client angegebene maximale Zeit überschreitet. Nachdem ein Peripherietreiber eine Leseanforderung an SerCx2 gesendet hat, kann ein Intervalltimeout erst auftreten, wenn mindestens ein Byte Daten vom seriellen Peripheriegerät empfangen wurde. Die Zeit zwischen dem Eintreffen einer Leseanforderung und dem Empfang des ersten Byte an Daten vom Peripheriegerät kann erheblich länger sein als die Zeit, die erforderlich ist, um die restlichen Daten für die Leseanforderung zu empfangen, nachdem das erste Byte empfangen wurde. Weitere Informationen finden Sie unter SERIAL_TIMEOUTS.

SerCx2 ruft die EvtSerCx2CustomReceiveTransactionEnableNewDataNotification-Funktion auf, wenn sie implementiert ist, um eine New-Data-Benachrichtigung zu aktivieren. Wenn diese Benachrichtigung aktiviert ist und der serielle Controller ein oder mehrere Bytes neuer Daten vom Peripheriegerät empfängt oder bereits Daten in seinem Empfangs-FIFO enthält, muss der serielle Controllertreiber die SerCx2CustomReceiveTransactionNewDataNotification-Methode aufrufen, um SerCx2 zu benachrichtigen.

Um ein mögliches Intervalltimeout zu erkennen, ruft SerCx2 in regelmäßigen Abständen die Ereignisrückruffunktion EvtSerCx2CustomReceiveTransactionQueryProgress auf, um zu überprüfen, ob Daten während des vorherigen Intervalls empfangen wurden. Wie SerCx2 den Empfang des ersten Datenbytes erkennt, hängt davon ab, ob der serielle Controllertreiber eine EvtSerCx2CustomReceiveTransactionEnableNewDataNotification-Funktion implementiert. Wenn diese Funktion implementiert ist, ruft SerCx2 die Funktion auf, um eine New-Data-Benachrichtigung zu aktivieren, und wird vom Treiber benachrichtigt, wenn das erste Byte von Daten empfangen wird. Andernfalls ruft SerCx2 regelmäßig die EvtSerCx2CustomReceiveTransactionQueryProgress-Funktion auf, um den Empfang des ersten Byte zu erkennen, und muss den Prozessor möglicherweise regelmäßig reaktivieren, um diese Aufrufe auszuführen. Daher kann ein Treiber, der eine EvtSerCx2CustomReceiveTransactionEnableNewDataNotification-Funktion implementiert, den Energieverbrauch reduzieren, da der Prozessor nicht so oft aktiviert werden muss.

SerCx2 bricht eine ausstehende Benachrichtigung für neue Daten für eine benutzerdefinierte Empfangstransaktion nicht explizit ab. Der Treiber des seriellen Controllers muss jedoch möglicherweise implizit eine New-Data-Benachrichtigung abbrechen, wenn die Benachrichtigung aktiviert ist und der Treiber die zugeordnete Leseanforderung aus einem der folgenden Gründe ausführen muss:

  • Das Zeitüberschreitungsout der Leseanforderung oder wird abgebrochen.
  • Der serielle Controller beendet den D0-Gerätestromzustand, um in einen Energiesparzustand zu gelangen.

Der Treiber ruft in der Regel eine Methode wie WdfRequestComplete auf, um die Anforderung abzuschließen. Der Treiber darf serCx2CustomReceiveTransactionNewDataNotification nie aufrufen, nachdem die Anforderung abgeschlossen wurde.

Zugreifen auf das Anforderungsobjekt

Um eine benutzerdefinierte Empfangstransaktion zu starten, ruft SerCx2 die EvtSerCx2CustomReceiveTransactionStart-Funktion des Treibers auf und übergibt die zugeordnete Leseanforderung (gekapselt in einem WDFREQUEST-Objekthandle) als Parameter an diese Funktion. Der Treiber ist für das Aufrufen einer Methode wie WdfRequestComplete verantwortlich, um diese Anforderung abzuschließen, wenn die Transaktion abgeschlossen ist. Es sei denn, die Anforderung kann sofort abgeschlossen werden, bevor die EvtSerCx2CustomReceiveTransactionStart-Funktion zurückgegeben wird, muss der Treiber eine Methode wie WdfRequestMarkCancelableEx aufrufen, um die Anforderung als abbruchfähig zu markieren.

Der Serielle Controllertreiber darf keine Methode wie WdfRequestRetrieveOutputBuffer verwenden, um auf den Datenpuffer in der Leseanforderung zuzugreifen. Stattdessen sollte der Treiber die Parameterwerte Mdl, Offset und Length verwenden, die an die Funktion EvtSerCx2CustomReceiveTransactionStart übergeben wurden, um auf diesen Puffer zuzugreifen.

Während einer benutzerdefinierten Empfangstransaktion muss der Treiber möglicherweise Informationen zur Transaktion in einem Kontext speichern, der an das Anforderungsobjekt angefügt ist. In diesem Fall kann die EvtDriverDeviceAdd-Ereignisrückruffunktion des Treibers die WdfDeviceInitSetRequestAttributes-Methode aufrufen, um die Attribute festzulegen, die für Anforderungsobjekte verwendet werden sollen. Diese Attribute umfassen den Namen und die Zuordnungsgröße, die für Anforderungskontexte verwendet werden sollen. Die in diesem Aufruf angegebenen Anforderungsattribute müssen mit den Anforderungsattributen übereinstimmen, die der Treiber im Aufruf der SerCx2InitializeDevice-Methode angibt. Diese Attribute werden im RequestAttributes-Member der SERCX2_CONFIG-Struktur angegeben, die der Treiber an SerCx2InitializeDevice übergibt. Weitere Informationen finden Sie unter SERCX2_CONFIG.

Bei einer Leseanforderung, die der serielle Controllertreiber zu Beginn einer benutzerdefinierten Empfangstransaktion empfängt, wird der vom Treiberframework zugewiesene Anforderungskontext nicht initialisiert. Der Treiber sollte als bewährte Methode die RtlZeroMemory-Routine aufrufen, um diesen Anforderungskontext auf alle Nullen zu initialisieren.