Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ten artykuł zawiera omówienie funkcji wstrzymania i zdalnego wznawiania dla urządzeń wielofunkcyjnych USB 3.0 (urządzeń złożonych). W tym artykule dowiesz się więcej na temat implementowania tych funkcji w sterowniku, który kontroluje urządzenie złożone. Artykuł dotyczy sterowników złożonych, które zastępują Usbccgp.sys.
Specyfikacja uniwersalnej magistrali szeregowej (USB) 3.0 definiuje nową funkcję o nazwie wstrzymanie funkcji. Funkcja umożliwia poszczególnym funkcjom urządzenia złożonego wprowadzanie stanu niskiego zasilania niezależnie od innych funkcji. Rozważ urządzenie złożone, które definiuje funkcję klawiatury i inną funkcję myszy. Użytkownik utrzymuje funkcję klawiatury w stanie roboczym, ale nie przenosi myszy przez pewien czas. Sterownik klienta myszy może wykryć stan bezczynności funkcji i wysłać funkcję do wstrzymania stanu, podczas gdy funkcja klawiatury pozostaje w stanie roboczym.
Całe urządzenie może przejść do stanu wstrzymania niezależnie od stanu zasilania dowolnej funkcji w urządzeniu. Jeśli określona funkcja i całe urządzenie wejdą w stan wstrzymania, stan wstrzymania funkcji jest zachowywany przez cały czas trwania tego stanu urządzenia, a także podczas przejść do i z tego stanu.
Podobnie jak funkcja zdalnego wznawiania urządzenia USB 2.0 (zobacz Zdalne wznawianie urządzeń USB), pojedyncza funkcja w urządzeniu złożonym USB 3.0 może wznawiać się ze stanu niskiego zasilania bez wpływu na stany zasilania innych funkcji. Ta funkcja jest nazywana zdalnym wznawianiem funkcji. Funkcja jest jawnie włączana przez hosta poprzez wysłanie żądania protokołu, które ustawia bity zdalnego wybudzania w firmware urządzenia. Ta procedura jest nazywana uzbrojeniem funkcji w celu zdalnego wzbudzenia. Aby uzyskać informacje o bitach związanych ze zdalnym wybudzaniem, odnieś się do Rysunku 9-6 w oficjalnej specyfikacji USB.
Jeśli funkcja jest uzbrojona w zdalne wznawianie, funkcja (w stanie wstrzymania) zachowuje wystarczającą moc, aby wygenerować sygnał wznawiania w przypadku wystąpienia zdarzenia użytkownika na urządzeniu fizycznym. W wyniku tego sygnału wznowienia sterownik klienta może następnie wyjść ze stanu wstrzymania skojarzonej funkcji. W przykładzie dotyczącym funkcji myszy na urządzeniu złożonym, gdy użytkownik porusza myszą w trybie bezczynności, funkcja myszy wysyła sygnał wznowienia do hosta. Na hoście stos sterowników USB wykrywa, która funkcja została obudzona i propaguje powiadomienie do sterownika klienta odpowiedniej funkcji. Sterownik klienta może następnie obudzić funkcję i przejść do stanu roboczego.
W przypadku sterownika klienta kroki wysyłania funkcji w celu wstrzymania stanu i przebudzenia funkcji są podobne do sterownika urządzenia z jedną funkcją wysyłającego całe urządzenie do stanu wstrzymania. Poniższa procedura zawiera podsumowanie tych kroków.
- Wykryj, kiedy skojarzona funkcja jest w stanie bezczynności.
- Wyślij bezczynny pakiet żądania we/wy (IRP).
- Prześlij żądanie uzbrojenia funkcji zdalnego wybudzania, wysyłając pakiet żądania WE/WY typu czekanie-wznawianie (IRP).
- Przenieś funkcję do stanu niskiego zużycia energii przez wysłanie IRP mocy Dx (D2 lub D3).
Aby uzyskać więcej informacji na temat powyższych kroków, zobacz "Wysyłanie bezczynnego żądania USB IRP" w selektywnym wstrzymaniu USB. Sterownik złożony tworzy obiekt urządzenia fizycznego (PDO) dla każdej funkcji na urządzeniu złożonym i obsługuje żądania zasilania wysyłane przez sterownik klienta (FDO stosu urządzenia funkcji). Aby sterownik klienta pomyślnie wejść i zakończyć stan wstrzymania dla funkcji, sterownik złożony musi obsługiwać funkcje wstrzymywania i zdalnego wznawiania oraz przetwarzać odebrane żądania zasilania.
W systemie Windows 8 stos sterowników USB dla urządzeń USB 3.0 obsługuje te funkcje. Ponadto implementacja funkcji wstrzymywanie funkcji i zdalne wznawianie funkcji została dodana do udostępnionego przez firmę Microsoft ogólnego sterownika nadrzędnego USB (Usbccgp.sys), który jest domyślnym sterownikiem złożonym systemu Windows. Jeśli piszesz niestandardowy sterownik złożony, sterownik musi obsługiwać żądania związane z wstrzymywaniem funkcji i zdalnymi żądaniami wznawiania, zgodnie z poniższą procedurą.
Krok 1. Określenie, czy stos sterowników USB obsługuje wstrzymanie funkcji
W procedurze uruchamiania urządzenia (IRP_MN_START_DEVICE) sterownika złożonego wykonaj następujące kroki:
- Wywołaj procedurę USBD_QueryUsbCapability , aby określić, czy bazowy stos sterowników USB obsługuje funkcję wstrzymania funkcji. Wywołanie wymaga prawidłowego uchwytu USBD, który uzyskałeś w poprzednim wywołaniu procedury USBD_CreateHandle.
Pomyślne wywołanie USBD_QueryUsbCapability określa, czy bazowy stos sterowników USB obsługuje wstrzymanie funkcji. Wywołanie może zwrócić kod błędu wskazujący, że sterownik USB nie obsługuje wstrzymania funkcji, lub że dołączone urządzenie nie jest urządzeniem wielofunkcyjnym USB 3.0.
- Jeśli wywołanie USBD_QueryUsbCapability wskazuje, że funkcja zawieszenia jest obsługiwana, zarejestruj urządzenie złożone w bazowym stosie sterowników USB. Aby zarejestrować urządzenie złożone, musisz wysłać żądanie sterowania wejście/wyjście IOCTL_INTERNAL_USB_REGISTER_COMPOSITE_DEVICE. Aby uzyskać więcej informacji na temat tego żądania, zobacz Jak zarejestrować urządzenie złożone.
Żądanie rejestracji używa struktury REGISTER_COMPOSITE_DEVICE , aby określić te informacje o sterowniku złożonym. Upewnij się, że ustawiono wartość CapabilityFunctionSuspend na 1, aby wskazać, że sterownik złożony obsługuje wstrzymanie funkcji.
Aby uzyskać przykład kodu pokazujący, jak określić, czy stos sterowników USB obsługuje wstrzymanie funkcji, zobacz USBD_QueryUsbCapability.
Krok 2: Obsługa bezczynnego IRP
Sterownik klienta może wysłać bezczynny protokół IRP (zobacz IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION). Żądanie jest wysyłane po wykryciu stanu bezczynności funkcji. Protokół IRP zawiera wskaźnik do procedury uzupełniania wywołania zwrotnego (nazywanej bezczynnością wywołania zwrotnego), która jest implementowana przez sterownik klienta. W ramach bezczynnego wywołania zwrotnego klient wykonuje zadania, takie jak anulowanie oczekujących transferów we/wy, tuż przed wysłaniem funkcji do stanu wstrzymania.
Uwaga
Bezczynny mechanizm IRP jest opcjonalny dla klienckich sterowników urządzeń USB 3.0. Jednak większość sterowników klienta jest zapisywana w celu obsługi urządzeń USB 2.0 i USB 3.0. Aby obsługiwać urządzenia USB 2.0, sterownik musi wysłać bezczynny protokół IRP, ponieważ sterownik złożony opiera się na tym IRP w celu śledzenia stanu zasilania każdej funkcji. Jeśli wszystkie funkcje są bezczynne, sterownik złożony wysyła całe urządzenie do wstrzymania stanu.
Po otrzymaniu bezczynnego protokołu IRP ze sterownika klienta sterownik złożony musi natychmiast wywołać wywołanie zwrotne bezczynności, aby powiadomić sterownik klienta, że sterownik klienta może wysłać funkcję do wstrzymania stanu.
Krok 3. Wysyłanie żądania powiadomienia o zdalnym wznawianiu
Sterownik klienta może przesłać żądanie, aby przygotować swoją funkcję do zdalnego wybudzania, przesyłając IRP_MJ_POWER IRP z pomocniczym kodem funkcji ustawionym na IRP_MN_WAIT_WAKE (wait-wake IRP). Sterownik klienta przesyła to żądanie tylko wtedy, gdy sterownik chce wprowadzić stan roboczy w wyniku zdarzenia użytkownika.
Po otrzymaniu IRP oczekiwania-budzenia, sterownik złożony musi wysłać żądanie sterowania we/wy IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION do stosu sterowników USB. Żądanie umożliwia stosowi sterowników USB powiadamianie sterownika złożonego, gdy stos odbiera powiadomienie o sygnałze wznowienia. IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION używa struktury REQUEST_REMOTE_WAKE_NOTIFICATION do określania parametrów żądania. Jedną z wartości, które musi określić sterownik złożony, jest uchwyt funkcji dla funkcji skonfigurowanej do zdalnego wznawiania. Sterownik złożony uzyskał ten uchwyt w poprzednim żądaniu zarejestrowania urządzenia złożonego za pomocą stosu sterowników USB. Aby uzyskać więcej informacji na temat rejestracji złożonych sterowników, zobacz artykuł Jak zarejestrować urządzenie złożone.
W IRP dla żądania sterownik złożony dostarcza wskaźnik do procedury uzupełniania (zdalne wznawianie), która jest implementowana przez sterownik złożony.
Poniższy przykładowy kod pokazuje, jak wysłać zdalne żądanie wznawiania.
/*++
Description:
This routine sends a IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION request
to the USB driver stack. The IOCTL is completed by the USB driver stack
when the function wakes up from sleep.
Parameters:
parentFdoExt: The device context associated with the FDO for the
composite driver.
functionPdoExt: The device context associated with the PDO (created by
the composite driver) for the client driver.
--*/
VOID
SendRequestForRemoteWakeNotification(
__inout PPARENT_FDO_EXT parentFdoExt,
__inout PFUNCTION_PDO_EXT functionPdoExt
)
{
PIRP irp;
REQUEST_REMOTE_WAKE_NOTIFICATION remoteWake;
PIO_STACK_LOCATION nextStack;
NTSTATUS status;
// Allocate an IRP
irp = IoAllocateIrp(parentFdoExt->topDevObj->StackSize, FALSE);
if (irp)
{
//Initialize the USBDEVICE_REMOTE_WAKE_NOTIFICATION structure
remoteWake.Version = 0;
remoteWake.Size = sizeof(REQUEST_REMOTE_WAKE_NOTIFICATION);
remoteWake.UsbdFunctionHandle = functionPdoExt->functionHandle;
remoteWake.Interface = functionPdoExt->baseInterfaceNumber;
nextStack = IoGetNextIrpStackLocation(irp);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION;
nextStack->Parameters.Others.Argument1 = &remoteWake;
// Caller's completion routine will free the IRP when it completes.
SetCompletionRoutine(functionPdoExt->debugLog,
parentFdoExt->fdo,
irp,
CompletionRemoteWakeNotication,
(PVOID)functionPdoExt,
TRUE, TRUE, TRUE);
// Pass the IRP
IoCallDriver(parentFdoExt->topDevObj, irp);
}
return;
}
Żądanie IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION jest wykonywane przez stos sterowników USB podczas procesu wznawiania po otrzymaniu powiadomienia o sygnałze wznawiania. W tym czasie stos sterowników USB wywołuje również rutynę kończenia zdalnego wybudzania.
Sterownik złożony musi utrzymywać oczekujące IRP oczekiwania i wybudzania oraz kolejkować je do późniejszego przetwarzania. Sterownik złożony musi ukończyć ten protokół IRP, gdy zdalna procedura uzupełniania wznawiania sterownika jest wywoływana przez stos sterowników USB.
Krok 4: Wyślij żądanie w celu aktywacji funkcji zdalnego wznawiania
Aby wysłać funkcję do stanu niskiego zasilania, sterownik klienta przesyła IRP_MN_SET_POWER IRP z żądaniem zmiany stanu zasilania urządzenia Windows Driver Model (WDM) na D2 lub D3. Zazwyczaj sterownik klienta wysyła IRP D2, jeśli sterownik wysłał wcześniej IRP w celu żądania zdalnego wybudzenia. W przeciwnym razie sterownik klienta wysyła IRP D3.
Po otrzymaniu D2 IRP, sterownik złożony musi najpierw określić, czy nierozstrzygnięty IRP typu wait-wake jest oczekujący w wyniku poprzedniego żądania wysłanego przez sterownik klienta. Jeśli ten protokół IRP oczekuje, sterownik złożony musi uzbroić funkcję w celu zdalnego wznawiania. Aby to zrobić, sterownik złożony musi wysłać żądanie kontroli SET_FEATURE do pierwszego interfejsu funkcji, aby umożliwić urządzeniu wysyłanie sygnału wznawiania. Aby wysłać żądanie kontroli, przydziel strukturę URB , wywołując procedurę USBD_UrbAllocate i wywołując makro UsbBuildFeatureRequest , aby sformatować adres URB dla żądania SET_FEATURE. W wywołaniu określ URB_FUNCTION_SET_FEATURE_TO_INTERFACE jako kod operacji i USB_FEATURE_FUNCTION_SUSPEND jako selektor funkcji. W parametrze Indeks ustaw bit 1 z najbardziej znaczących bajtów. Ta wartość jest kopiowana do pola wIndex w pakiecie instalacyjnym transferu.
W poniższym przykładzie pokazano, jak wysłać żądanie kontroli SET_FEATURE.
/*++
Routine Description:
Sends a SET_FEATURE for REMOTE_WAKEUP to the device using a standard control request.
Parameters:
parentFdoExt: The device context associated with the FDO for the
composite driver.
functionPdoExt: The device context associated with the PDO (created by
the composite driver) for the client driver.
Returns:
NTSTATUS code.
--*/
VOID
NTSTATUS SendSetFeatureControlRequestToSuspend(
__inout PPARENT_FDO_EXT parentFdoExt,
__inout PFUNCTION_PDO_EXT functionPdoExt,
)
{
PURB urb
PIRP irp;
PIO_STACK_LOCATION nextStack;
NTSTATUS status;
status = USBD_UrbAllocate(parentFdoExt->usbdHandle, &urb);
if (!NT_SUCCESS(status))
{
//USBD_UrbAllocate failed.
goto Exit;
}
//Format the URB structure.
UsbBuildFeatureRequest (
urb,
URB_FUNCTION_SET_FEATURE_TO_INTERFACE, // Operation code
USB_FEATURE_FUNCTION_SUSPEND, // feature selector
functionPdoExt->firstInterface, // first interface of the function
NULL);
irp = IoAllocateIrp(parentFdoExt->topDevObj->StackSize, FALSE);
if (!irp)
{
// IoAllocateIrp failed.
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
nextStack = IoGetNextIrpStackLocation(irp);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
// Attach the URB to the IRP.
USBD_AssignUrbToIoStackLocation(nextStack, (PURB)urb);
// Caller's completion routine will free the IRP when it completes.
SetCompletionRoutine(functionPdoExt->debugLog,
parentFdoExt->fdo,
irp,
CompletionForSuspendControlRequest,
(PVOID)functionPdoExt,
TRUE, TRUE, TRUE);
// Pass the IRP
IoCallDriver(parentFdoExt->topDevObj, irp);
Exit:
if (urb)
{
USBD_UrbFree( parentFdoExt->usbdHandle, urb);
}
return status;
}
Sterownik złożony wysyła następnie protokół IRP D2 do stosu sterowników USB. Jeśli wszystkie inne funkcje są w stanie wstrzymania, stos sterowników USB zawiesza port, manipulując pewnymi rejestrami portów na kontrolerze.
Uwagi
W przykładzie funkcji myszy, ponieważ funkcja zdalnego wznawiania jest włączona (zobacz krok 4), funkcja myszy generuje sygnał wznawiania na przewodzie nadrzędnym do kontrolera hosta, gdy użytkownik przełącza mysz. Następnie kontroler powiadamia stos sterowników USB, wysyłając pakiet powiadomień zawierający informacje o funkcji, która się obudziła. Aby uzyskać informacje o powiadomieniu o wybudzeniu, zobacz Rysunek 8-17 w specyfikacji USB 3.0.
Po otrzymaniu pakietu powiadomień stos sterowników USB kończy oczekujące żądanie IOCTL_INTERNAL_USB_REQUEST_REMOTE_WAKE_NOTIFICATION (patrz krok 3) i wywołuje procedurę wywołania zwrotnego ukończenia (zdalne wznawianie), która została określona w żądaniu i zaimplementowana przez sterownik złożony. Gdy powiadomienie dociera do sterownika złożonego, powiadamia odpowiedni sterownik klienta, że funkcja weszła w stan roboczy poprzez zakończenie IRP oczekiwania-budzenia, które sterownik klienta wysłał wcześniej.
W procedurze uzupełniania (zdalne wznawianie) sterownik złożony powinien dodać element roboczy do kolejki, aby zakończyć oczekujące operacje IRP typu wake-wait. W przypadku urządzeń USB 3.0 sterownik złożony budzi tylko funkcję, która wysyła sygnał wznowienia i pozostawia inne funkcje w stanie wstrzymania. Kolejkowanie elementu roboczego zapewnia zgodność z istniejącą implementacją sterowników funkcji urządzeń USB 2.0. Aby uzyskać informacje na temat kolejkowania elementu roboczego, zobacz IoQueueWorkItem.
Wątek roboczy kończy IRP oczekiwanie-wzbudzanie i wywołuje procedurę zakończenia sterownika klienta. Następnie procedura uzupełniania wysyła IRP D0, aby wprowadzić funkcję w stanie roboczym. Przed ukończeniem IRP typu wait-wake kompozytowy sterownik powinien wywołać funkcję PoSetSystemWake aby oznaczyć IRP typu wait-wake jako ten, który przyczynił się do wybudzenia systemu ze stanu wstrzymania. Menedżer zasilania rejestruje zdarzenie śledzenia zdarzeń dla Windows (ETW) (widoczne w globalnym kanale systemowym), które zawiera informacje o urządzeniach, które obudziły system.