Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit artikel wordt beschreven hoe KMDF-functiestuurprogramma's USB selectief onderbreken ondersteunen.
Als het USB-stuurprogramma functies of resources vereist die niet beschikbaar zijn in de gebruikersmodus, moet u een KMDF-functiestuurprogramma opgeven. KMDF-stuurprogramma's implementeren selectief onderbreken door relevante waarden in te stellen in een KMDF-initialisatiestructuur en vervolgens de juiste callbackfuncties op te geven. KMDF verwerkt de details van de communicatie met lagere stuurprogramma's om het apparaat te onderbreken en te hervatten.
Richtlijnen voor het selectief onderbreken in KMDF-stuurprogramma's
KMDF-stuurprogramma's met ondersteuning voor selectieve schorsing moeten de volgende richtlijnen volgen:
- Een KMDF-functiestuurprogramma moet de PPO zijn voor zijn apparaatstack. KMDF-functiestuurprogramma's zijn standaard de PPO.
- Een KMDF-functiestuurprogramma dat selectieve onderbreking ondersteunt, kan wachtrijen gebruiken met stroombeheer of wachtrijen zonder stroombeheer. Wachtrijobjecten voor PPO's worden standaard door energiebeheer beheerd.
Eigendom van energiebeleid en KMDF USB-stuurprogramma's
Standaard is het KMDF-functiestuurprogramma voor een USB-apparaat de PPO (Power Policy Owner) voor de stack van de apparaten. KMDF beheert het selectief pauzeren en hervatten namens deze driver.
I/O-wachtrijconfiguratie in KMDF-stuurprogramma's
Een KMDF-functiestuurprogramma dat selectieve onderbreking ondersteunt, kan wachtrijen gebruiken die worden beheerd door stroom of wachtrijen die geen stroombeheer hebben. Normaal gesproken configureert een stuurprogramma een wachtrij die niet door energie wordt beheerd voor het ontvangen van binnenkomende apparaat I/O-beheeraanvragen en configureert een of meer energiebeheer wachtrijen voor het ontvangen van lees-, schrijf-, en andere aanvragen die van energie afhankelijk zijn. Wanneer een aanvraag binnenkomt in een door stroom beheerde wachtrij, zorgt KMDF ervoor dat het apparaat zich in D0 bevindt voordat de aanvraag aan het stuurprogramma wordt gepresenteerd.
Als u een KMDF-filterstuurprogramma schrijft dat is gelaagd boven de VG in de apparaatstack, moet u geen door energie beheerde wachtrijen gebruiken. De reden hiervoor is hetzelfde als voor UMDF-stuurprogramma's. Het framework presenteert geen verzoeken uit energiebeheer-wachtrijen terwijl het apparaat in slaapstand is, dus het gebruik van dergelijke wachtrijen kan de apparaatstapel blokkeren.
Mechanisme voor selectief opschorten voor KMDF-functiestuurprogramma's
KMDF verwerkt het grootste deel van het werk dat nodig is om USB selectief onderbreken te ondersteunen. Het houdt I/O-activiteit bij, beheert de inactieve timer en verzendt de I/O-beheeraanvragen van het apparaat die ervoor zorgen dat het bovenliggende stuurprogramma (Usbhub.sys of Usbccgp.sys) het apparaat onderbreekt en hervat.
Als een KMDF-driver selectieve onderbreking ondersteunt, houdt KMDF de I/O-activiteit bij in alle stroombeheerwachtrijen die eigendom zijn van elk apparaatobject. Het framework start een niet-actieve timer wanneer het aantal I/O's nul bereikt. De standaardtime-outwaarde is 5 seconden.
Als een I/O-aanvraag aankomt bij een door stroom beheerde wachtrij die deel uitmaakt van het apparaatobject voordat de inactiviteitsperiode verloopt, annuleert het framework de timer voor inactiviteit en onderbreekt het apparaat niet.
Wanneer de inactieve timer verloopt, geeft KMDF de aanvragen uit die nodig zijn om het USB-apparaat in de onderbroken status te plaatsen. Als een functiestuurprogramma gebruikmaakt van een continue lezer op een USB-eindpunt, telt de herhaalde polling van de lezer niet als activiteit ten opzichte van de niet-actieve KMDF-timer. Binnen de callback-functie EvtDeviceD0Exit moet het USB-stuurprogramma de voortdurende lezer en andere I/O-doelen die worden ingevoerd door wachtrijen die niet stroom worden beheerd, handmatig stoppen om ervoor te zorgen dat het stuurprogramma geen I/O-aanvragen verzendt terwijl het apparaat zich niet in de werkende staat bevindt. Om de doelen te stoppen, roept de driver WdfIoTargetStop op en geeft WdfIoTargetWaitForSentIoToComplete als actie voor het doel op. Als reactie stopt het framework het I/O-doel pas nadat alle I/O-aanvragen die zich in de I/O-wachtrij van het doel bevinden, zijn voltooid en eventuele bijbehorende I/O-voltooiingsaanroepacties zijn uitgevoerd.
Standaard zet KMDF het apparaat om van de D0-energietoestand naar de energietoestand die is opgegeven in de niet-actieve instellingen door het stuurprogramma. Als onderdeel van de overgang roept KMDF de power callback-functies van de driver op dezelfde manier aan als voor elke andere uitschakelvolgorde.
Nadat het apparaat is onderbroken, hervat het framework automatisch het apparaat wanneer een van de volgende gebeurtenissen plaatsvindt:
- Er wordt een I/O-aanvraag ontvangen voor een van de door het stuurprogramma beheerde wachtrijen.
- De gebruiker schakelt USB selectief onderbreken uit met behulp van Apparaatbeheer.
- Het stuurprogramma roept WdfDeviceStopIdle aan, zoals beschreven in Voorkomen van USB-apparaatverhanging.
Om het apparaat te hervatten, stuurt KMDF een inschakelverzoek naar de onderliggende lagen van de apparaatstack en roept vervolgens de callbackfuncties van de stuurprogramma's op dezelfde manier aan als bij elke andere inschakelvolgorde.
Voor gedetailleerde informatie over de callbacks die betrokken zijn bij het uitschakelen en opstarten van sequenties, zie het white paper Plug and Play and Power Management in WDF Drivers.
USB-selectieve onderbreking in een KMDF-functiestuurprogramma ondersteunen
Om USB selectief onderbreken te implementeren in een KMDF-functiestuurprogramma:
- Initialiseer energiebeleidsinstellingen die zijn gerelateerd aan inactiviteit, inclusief time-out voor inactiviteit.
- Voeg eventueel logica toe om tijdelijk een onderbreking of hervatting te voorkomen wanneer het stuurprogramma bepaalt dat het apparaat niet moet worden onderbroken vanwege een open ingang of een andere reden die niet is gerelateerd aan de I/O-wachtrijen van het apparaat.
- In een USB-stuurprogramma voor een human interface-apparaat (HID) geeft u in de INF aan dat het selectieve onderbreking (selective suspend) ondersteunt.
Power Policy-instellingen initialiseren in een KMDF-functiestuurprogramma
Een KMDF-stuurprogramma gebruikt de WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS-structuur om ondersteuning te configureren voor USB-selectieve onderbreking. Het stuurprogramma moet eerst de structuur initialiseren en vervolgens velden instellen die details geven over de mogelijkheden van het stuurprogramma en het bijbehorende apparaat. Normaal gesproken vult het stuurprogramma deze structuur in de functie EvtDriverDeviceAdd of EvtDevicePrepareHardware .
De WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS-structuur initialiseren
Nadat het stuurprogramma het apparaatobject heeft gemaakt, gebruikt het stuurprogramma de functie WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT om de structuur te initialiseren. Deze functie heeft twee argumenten:
- Een aanwijzer naar de WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS structuur om te initialiseren.
- Een opsommingswaarde die ondersteuning voor selectieve onderbreking aangeeft. Het stuurprogramma moet IdleUsbSelectiveSuspend opgeven.
Als het stuurprogramma IdleUsbSelectiveSuspend opgeeft, initialiseert de functie de leden van de structuur als volgt:
- IdleTimeout is ingesteld op IdleTimeoutDefaultValue (momenteel 5000 milliseconden of 5 seconden).
- UserControlOfIdleSettings is ingesteld op IdleAllowUserControl .
- Ingeschakeld is ingesteld op WdfUseDefault, wat aangeeft dat selectief onderbreken is ingeschakeld, maar een gebruiker kan dit uitschakelen als het lid UserControlOfIdleSettings dit toestaat.
- DxState is ingesteld op PowerDeviceMaximum, dat gebruikmaakt van de gerapporteerde energiemogelijkheden voor het apparaat om de status te bepalen waarnaar het niet-actieve apparaat moet worden overgezet.
USB selectief onderbreken configureren
Nadat het stuurprogramma de WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS-structuur heeft geïnitialiseerd, kan het stuurprogramma andere velden in de structuur instellen en vervolgens WdfDeviceAssignS0IdleSettings aanroepen om deze instellingen door te geven aan het framework. De volgende velden zijn van toepassing op USB-functiestuurprogramma's:
IdleTimeout: het interval, in milliseconden, dat moet verlopen zonder een I/O-aanvraag te ontvangen voordat het framework het apparaat inactief beschouwt. Het stuurprogramma kan een ULONG-waarde opgeven of de standaardwaarde accepteren.
UserControlOfIdleSettings: of de gebruiker de niet-actieve instellingen van het apparaat kan wijzigen. Mogelijke waarden zijn IdleDoNotAllowUserControl en IdleAllowUserControl.
DxState: de energiestatus van het apparaat waarop het framework het apparaat onderbreekt. Mogelijke waarden zijn PowerDeviceD1, PowerDeviceD2 en PowerDeviceD3.
USB-stuurprogramma's mogen de eerste instelling van deze waarde niet wijzigen. De functie WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT stelt deze waarde in op PowerDeviceMaximum, waardoor het framework de juiste waarde kiest op basis van de mogelijkheden van het apparaat.
Het volgende codefragment is afkomstig uit het bestand Device.c van het osrusbfx2-voorbeeldstuurprogramma:
WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
NTSTATUS status = STATUS_SUCCESS;
//
// Initialize the idle policy structure.
//
WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings,
IdleUsbSelectiveSuspend);
idleSettings.IdleTimeout = 10000; // 10 sec
status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings);
if ( !NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
"WdfDeviceSetPowerPolicyS0IdlePolicy failed %x\n",
status);
return status;
}
In het voorbeeld roept het stuurprogramma WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT aan, waarbij IdleUsbSelectiveSuspend wordt gespecificeerd. Het stuurprogramma stelt IdleTimeout in op 10.000 milliseconden (10 seconden) en accepteert de standaardinstellingen van het framework voor DxState en UserControlOfIdleSettings. Aanvankelijk plaatst het framework het apparaat in de D3-status wanneer het apparaat niet actief is en wordt er een apparaatbeheer eigenschappenblad aangemaakt waarmee gebruikers met beheerdersrechten de ondersteuning voor inactieve apparaten kunnen in- of uitschakelen. Het stuurprogramma roept vervolgens WdfDeviceAssignS0IdleSettings aan om inactieve ondersteuning in te schakelen en deze instellingen te registreren bij het framework.
Een stuurprogramma kan WdfDeviceAssignS0IdleSettings op elk gewenst moment aanroepen nadat het apparaatobject is gemaakt. Hoewel de meeste stuurprogramma's deze methode in eerste instantie aanroepen vanuit de Callback evtDriverDeviceAdd , is dit mogelijk niet altijd mogelijk of zelfs wenselijk. Als een stuurprogramma ondersteuning biedt voor meerdere apparaten of apparaatversies, weet het stuurprogramma mogelijk niet alle apparaatmogelijkheden totdat er een query wordt uitgevoerd op de hardware. Dergelijke stuurprogramma's kunnen het aanroepen van WdfDeviceAssignS0IdleSettings tot de callback EvtDevicePrepareHardware uitstellen.
Op elk gewenst moment na de eerste aanroep naar WdfDeviceAssignS0IdleSettings kan het stuurprogramma de time-outwaarde voor inactiviteit en de status van het apparaat wijzigen waarin het apparaat inactief is. Als u een of meer instellingen wilt wijzigen, initialiseert het stuurprogramma gewoon een andere WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS structuur zoals eerder beschreven en roept WdfDeviceAssignS0IdleSettings opnieuw aan.
Voorkomen van USB-apparaatonderbreking
Soms mag een USB-apparaat niet worden uitgeschakeld, zelfs als er geen I/O-aanvragen aanwezig zijn binnen de time-outperiode, meestal wanneer een ingang voor het apparaat is geopend of het apparaat wordt opgeladen. Een USB-stuurprogramma kan voorkomen dat het framework een niet-actief apparaat in dergelijke situaties onderbreekt door WdfDeviceStopIdle aan te roepen en WdfDeviceResumeIdle aan te roepen wanneer het opnieuw acceptabel is dat het apparaat wordt onderbroken.
WdfDeviceStopIdle stopt de timer die niet actief is. Als de periode IdleTimeout niet is verlopen en het apparaat nog niet is onderbroken, annuleert het framework de niet-actieve timer en wordt het apparaat niet onderbroken. Als het apparaat al is opgeschort, herstelt het framework het apparaat naar de werkende staat. WdfDeviceStopIdlevoorkomt niet dat het framework het apparaat onderbreekt wanneer het systeem verandert in een Sx-slaapstand. Het enige effect is om apparaatvering te voorkomen terwijl het systeem de S0-werkstatus heeft. WdfDeviceResumeIdle start de timer voor inactiviteit opnieuw. Deze twee methoden onderhouden een referentietelling voor het apparaat, dus als het stuurprogramma WdfDeviceStopIdle meerdere keren aanroept, wacht het framework met het onderbreken van het apparaat totdat het stuurprogramma WdfDeviceResumeIdle hetzelfde aantal keren heeft aangeroepen. Een stuurprogramma mag WdfDeviceResumeIdleniet aanroepen zonder eerst WdfDeviceStopIdle aan te roepen.
Een registersleutel opnemen (alleen HID-stuurprogramma's)
KmDF bovenste filterstuurprogramma's voor USB HID-apparaten moeten aangeven in de INF dat ze selectieve onderbreking ondersteunen, zodat het door Microsoft geleverde HIDClass.sys poortstuurprogramma selectief onderbreken voor de HID-stack kan inschakelen. De INF moet een AddReg-instructie bevatten waarmee de sleutel SelectiveSuspendEnabled wordt toegevoegd en de waarde ervan wordt ingesteld op 1, zoals in de volgende tekenreeks wordt weergegeven:
HKR,,"SelectiveSuspendEnabled",0x00000001,0x1
Zie Hidusbfx2.inx in de WDK op %WinDDK%\BuildNumber\Src\Hid\ Hidusbfx2\sys voor een voorbeeld.
Ondersteuning voor extern ontwaken voor KMDF-stuurprogramma's
Net als bij selectief onderbreken biedt KMDF ondersteuning voor ontwaken, zodat een USB-apparaat een wake-signaal kan activeren terwijl het apparaat niets doet en het systeem of de werkstatus (S0) heeft of in een slaapstand (S1-S4) is. In KMDF-termen worden deze twee functies respectievelijk 'wake from S0' en 'wake from Sx' genoemd.
Voor USB-apparaten geeft wakeup alleen aan dat het apparaat zelf de overgang van een lagere energiestatus naar de werkstatus kan initiëren. Dus wat betreft USB-termen zijn waken van S0 en waken van Sx hetzelfde en worden ze „remote wake” genoemd.
KMDF USB-functiestuurprogramma's vereisen geen code om wake van S0 te ondersteunen, omdat KMDF deze mogelijkheid biedt als onderdeel van het selectieve onderbrekingsmechanisme. Om externe wake te ondersteunen wanneer het systeem zich in Sx bevindt, moet een functiestuurprogramma echter:
- Controleer of het apparaat externe wake ondersteunt door WdfUsbTargetDeviceRetrieveInformation aan te roepen.
- Schakel externe wake in door wake-instellingen te initialiseren en WdfDeviceAssignSxWakeSettings aan te roepen.
KMDF-stuurprogramma's configureren doorgaans wake-ondersteuning op hetzelfde moment dat ze ondersteuning configureren voor de selectieve USB-suspendemodus in de functie EvtDriverDeviceAdd of EvtDevicePrepareHardware.
Apparaatmogelijkheden controleren
Voordat een KMDF USB-functiestuurprogramma de energiebeleidsinstellingen voor inactief en activering initialiseert, moet het controleren of het apparaat externe activering ondersteunt. Voor informatie over hardwarefuncties van apparaten initialiseert het stuurprogramma een WDF_USB_DEVICE_INFORMATION structuur en roept WdfUsbTargetDeviceRetrieveInformation aan, meestal in de evtDriverDeviceAdd of EvtDevicePrepareHardware callback.
In de aanroep van WdfUsbTargetDeviceRetrieveInformation geeft het stuurprogramma een ingang door aan het apparaatobject en een aanwijzer naar de geïnitialiseerde WDF_USB_DEVICE_INFORMATION structuur. Zodra de functie succesvol is voltooid, bevat het Kenmerken-veld van de structuur vlaggen die aangeven of het apparaat zelfaangedreven is, op hoge snelheid kan werken en externe ontwaak ondersteunt.
In het volgende voorbeeld uit de Osrusbfx2 KMDF-sample ziet u hoe u deze methode aanroept om te bepalen of een apparaat remote wake ondersteunt. Nadat deze regels code zijn uitgevoerd, bevat de variabele waitWakeEnable TRUE als het apparaat externe wake ondersteunt en FALSE als dit niet het geval is:
WDF_USB_DEVICE_INFORMATION deviceInfo;
// Retrieve USBD version information, port driver capabilities and device
// capabilities such as speed, power, etc.
//
WDF_USB_DEVICE_INFORMATION_INIT(&deviceInfo);
status = WdfUsbTargetDeviceRetrieveInformation(
pDeviceContext->UsbDevice,
&deviceInfo);
waitWakeEnable = deviceInfo.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;
Externe ontwaakactie inschakelen
In USB-terminologie is een USB-apparaat ingeschakeld voor externe activering wanneer de DEVICE_REMOTE_WAKEUP functie is ingesteld. Volgens de USB-specificatie moet hostsoftware de externe ontwaakfunctie op een apparaat instellen 'alleen voordat' het apparaat in slaapstand wordt geplaatst. Het KMDF-functiestuurprogramma is alleen vereist om de wake-instellingen te initialiseren. KMDF en de door Microsoft geleverde USB-busstuurprogramma's geven de I/O-aanvragen uit en verwerken de hardwaremanipulatie die nodig is om externe ontwaakbewerking in te schakelen.
Wake-instellingen initialiseren
- Roep WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT aan om een WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS structuur te initialiseren. Met deze functie stelt u het ingeschakelde lid van de structuur in op WdfUseDefault, stelt u het DxState-lid in op PowerDeviceMaximum en stelt u het lid UserControlOfWakeSettings in op WakeAllowUserControl.
- Roep WdfDeviceAssignSxWakeSettings aan met de geïnitialiseerde structuur. Als gevolg daarvan is het apparaat in staat om uit de D3-status te ontwaken, en kan de gebruiker het wake-signaal in- of uitschakelen via de eigenschappenpagina van het apparaat in Apparaatbeheer.
In het volgende codefragment uit het osrusbfx2-voorbeeld ziet u hoe u wake-instellingen initialiseert naar de standaardwaarden:
WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings);
status = WdfDeviceAssignSxWakeSettings(Device, &wakeSettings);
if (!NT_SUCCESS(status)) {
return status;
}
Voor USB-apparaten die selectieve onderbreking ondersteunen, bereidt het onderliggende busstuurprogramma de hardware van het apparaat voor om te ontwaken. Usb-functiestuurprogramma's vereisen dus zelden een EvtDeviceArmWakeFromS0 callback. Het framework verzendt een selectieve suspend-aanvraag naar het USB-busstuurprogramma wanneer de tijdslimiet voor inactiviteit verloopt.
Om dezelfde reden vereisen USB-functiestuurprogramma's zelden een EvtDeviceWakeFromS0Triggered of EvtDeviceWakeFromSxTriggered terugroepfunctie. In plaats daarvan verwerken het framework en het onderliggende busstuurprogramma alle vereisten voor het retourneren van het apparaat naar de werkstatus.