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.
Uwaga
Ten artykuł jest przeznaczony dla deweloperów sterowników urządzeń. Jeśli występują problemy z urządzeniem USB, zobacz Rozwiązywanie problemów z USB-C w systemie Windows
Ten artykuł zawiera informacje o krokach, które warto podjąć, gdy przesyłanie danych do potoku USB kończy się niepowodzeniem. Mechanizmy opisane w tym artykule obejmują operacje przerywania, resetowania i cykliczne portów dla rur zbiorczych, przerwań i izochronicznych.
Sterownik klienta USB komunikuje się z urządzeniem, wysyłając transfery kontroli do domyślnego punktu końcowego oraz przesyłając dane do zbiorczych, przerwań i izochronicznych punktów końcowych urządzenia. Czasami te transfery mogą się nie powieść z różnych powodów, takich jak zablokowanie w punkcie końcowym. Jeśli transfer zakończy się niepowodzeniem, skojarzony potok nie może przetwarzać żądań, dopóki warunek błędu nie zostanie wyczyszczony.
W przypadku transferów sterowania stos sterowników USB automatycznie usuwa warunki błędu. W przypadku transferów danych klient musi podjąć odpowiednie kroki, aby naprawić sytuację błędną. Gdy transfer danych nie powiedzie się, stos sterowników USB zgłasza błąd do sterownika klienta poprzez niepoprawne kody stanu USBD. Na podstawie kodu stanu sterownik może następnie zapewnić mechanizm odzyskiwania błędów.
Ten artykuł zawiera wskazówki dotyczące odzyskiwania błędów za pomocą tych operacji.
- Resetowanie potoku USB
- Zresetuj port USB, do którego urządzenie jest podłączone
- Zresetuj port USB, aby ponownie zidentyfikować urządzenie dla sterownika użytkownika końcowego.
Aby wyczyścić warunek błędu, zacznij od operacji resetowania potoku i wykonaj bardziej złożone operacje, takie jak resetowanie portu i cykliczne resetowanie portu, tylko wtedy, gdy jest to konieczne.
Informacje o koordynowaniu różnych mechanizmów odzyskiwania:
Sterownik klienta musi koordynować różne operacje odzyskiwania i upewnić się, że w danym momencie jest używana tylko jedna metoda. Rozważmy na przykład urządzenie z dwoma punktami końcowymi: zbiorczą i przerywaną. Po wysłaniu kilku żądań przesyłania danych do urządzenia, sterownik zauważa, że żądania kończą się niepowodzeniem w kanale masowym. Aby poradzić sobie z tymi błędami, sterownik resetuje potok zbiorczy. Jednak ta operacja nie rozwiązuje błędów transferu i transfery zbiorcze nadal kończą się niepowodzeniem. W związku z tym sterownik wysyła żądanie zresetowania portu USB. Tymczasem transfery zaczynają się nie powodzić w kanale przerwań, a potem pojawia się żądanie zresetowania urządzenia. Aby rozwiązać problemy związane z awariami transferu przerwań, sterownik wystawia żądanie zresetowania potoku na potoku przerwania. Jeśli te dwie operacje nie są skoordynowane, sterownik może uruchomić jednocześnie dwie operacje resetowania urządzenia z powodu awarii w obu kanałach komunikacyjnych. Te jednoczesne operacje mogą być problematyczne.
Sterownik klienta musi upewnić się, że w danym momencie sterownik wykonuje tylko jedną operację reset-port lub cycle-port. Podczas tych operacji żadne resetowanie potoku nie powinno być w toku, a sterownik nie może wydać nowego żądania resetowania potoku.
Co musisz wiedzieć
W tym artykule użyto Kernel-Mode Driver Framework (KMDF).
Wymagania wstępne
Sterownik klienta musiał utworzyć obiekt docelowy USB w ramach platformy.
Jeśli używasz szablonów USB dostarczanych z programem Microsoft Visual Studio Professional 2012, kod szablonu wykonuje te zadania. Kod szablonu uzyskuje dojście do obiektu urządzenia docelowego i przechowuje je w kontekście urządzenia.
Sterownik klienta usługi KMDF musi uzyskać dojście WDFUSBDEVICE przez wywołanie metody WdfUsbTargetDeviceCreateWithParameters. Aby uzyskać więcej informacji, zobacz "Kod źródłowy urządzenia" w Opis struktury kodu sterownika klienta USB (KMDF).
Sterownik klienta musi mieć uchwyt do obiektu potoku docelowego frameworku. Aby uzyskać więcej szczegółów, zobacz Jak wyliczać potoki USB.
Krok 1. Określanie przyczyny warunku błędu
Sterownik klienta inicjuje transfer danych przy użyciu bloku żądań USB (URB). Po zakończeniu żądania stos sterowników USB zwraca kod stanu USBD, który wskazuje, czy transfer zakończył się pomyślnie, czy zakończył się niepowodzeniem. W przypadku błędu kod USBD wskazuje przyczynę błędu.
- Jeśli przesłano URB przez wywołanie metody WdfUsbTargetDeviceSendUrbSynchronously, sprawdź składową Hdr.Status struktury URB po powrocie metody.
- Jeśli URB został przesłany asynchronicznie przez wywołanie metody WdfRequestSend, sprawdź stan URB w EVT_WDF_REQUEST_COMPLETION_ROUTINE. Parametr Params wskazuje strukturę WDF_REQUEST_COMPLETION_PARAMS. Aby sprawdzić kod stanu USBD, sprawdź Usb->UsbdStatus składową. Aby uzyskać informacje o kodzie, zobacz USBD_STATUS.
Błędy transferu mogą wynikać z błędu urządzenia, takiego jak USBD_STATUS_STALL_PID lub USBD_STATUS_BABBLE_DETECTED. Mogą one również wynikać z błędu zgłoszonego przez kontroler hosta, na przykład USBD_STATUS_XACT_ERROR.
Krok 2. Określanie, czy urządzenie jest połączone z portem
Przed wysłaniem żądania zresetowania kanału lub urządzenia upewnij się, że urządzenie jest podłączone. Stan połączenia urządzenia można określić, wywołując metodę WdfUsbTargetDeviceIsConnectedSynchronous.
Krok 3: Anuluj wszystkie oczekujące transfery do potoku
Przed wysłaniem żądań zresetowania potoku lub portu, anuluj wszystkie oczekujące żądania transferu do potoku, które stos sterowników USB jeszcze nie ukończył. Żądania można anulować na jeden z następujących sposobów:
Zatrzymaj obiekt docelowy wejścia/wyjścia, wywołując metodę WdfIoTargetStop.
Aby zatrzymać obiekt docelowy we/wy, najpierw pobierz dojście WDFIOTARGET skojarzone z obiektem potoku struktury, wywołując metodę WdfUsbTargetPipeGetIoTarget. Za pomocą uchwytu wywołaj WdfIoTargetStop. W wywołaniu ustaw akcję na WdfIoTargetCancelSentIo (zobacz WDF_IO_TARGET_SENT_IO_ACTION)**, aby framework anulował wszystkie żądania, których stos sterowników USB nie ukończył. W przypadku żądań, które zostały ukończone, sterownik klienta musi poczekać, aż platforma wywoła odpowiednią funkcję zwrotną.
Wyślij żądanie przerwania potoku. Żądanie można wysłać, wywołując jedną z następujących metod:
Wywołaj metodę WdfUsbTargetPipeAbortSynchronously.
Wywołanie jest synchroniczne i zwracane tylko po anulowaniu wszystkich oczekujących żądań. WdfUsbTargetPipeAbortSynchronously przyjmuje opcjonalny parametr Request. Zalecamy przekazanie dojścia WDFREQUEST do wstępnie przydzielonego obiektu żądania platformy. Parametr umożliwia korzystanie z określonego obiektu żądania zamiast wewnętrznego obiektu żądania, do którego sterownik nie może uzyskać dostępu. Ta wartość parametru zapewnia, że operacja WdfUsbTargetPipeAbortSynchronously nie kończy się niepowodzeniem z uwagi na niewystarczającą pamięć.
Wywołaj metodę WdfUsbTargetPipeFormatRequestForAbort, aby sformatować obiekt żądania dla żądania przerwania potoku, a następnie wysłać żądanie, wywołując metodę WdfRequestSend.
Jeśli sterownik wysyła żądanie asynchronicznie, musi określić wskaźnik do EVT_WDF_REQUEST_COMPLETION_ROUTINE, który sterownik implementuje. Aby określić wskaźnik, wywołaj metodę WdfRequestSetCompletionRoutine.
Sterownik może synchronicznie wysłać żądanie, określając WDF_REQUEST_SEND_OPTION_SYNCHRONOUS jako jedną z opcji żądania w WdfRequestSend. Jeśli wyślesz żądanie synchronicznie, wówczas wywołaj metodę WdfUsbTargetPipeAbortSynchronously.
Krok 4. Resetowanie potoku USB
Uruchom odzyskiwanie błędu, resetując potok. Żądanie "reset-pipe" można wysłać, wywołując jedną z następujących metod:
Wywołaj WdfUsbTargetPipeResetSynchronously, aby synchronicznie wysłać żądanie resetu potoku.
Wywołaj metodę WdfUsbTargetPipeFormatRequestForReset, aby sformatować obiekt żądania zresetowania potoku, a następnie wyślij żądanie, wywołując metodę WdfRequestSend. Te wywołania są podobne do wywołań związanych z żądaniem przerwania potoku, zgodnie z opisem w kroku 3.
Uwaga
Nie wysyłaj żadnych nowych żądań transferu do momentu zakończenia operacji resetowania potoku.
Żądanie resetowania rurociągu usuwa błąd w urządzeniu oraz sprzęcie kontrolera hosta. Aby wyczyścić błąd urządzenia, stos sterowników USB wysyła żądanie sterowania CLEAR_FEATURE do urządzenia przy użyciu selektora funkcji ENDPOINT_HALT. Adresatem żądania jest punkt końcowy skojarzony z potokiem. Jeśli warunek błędu miał miejsce w kanale izochronicznym, stos sterownika nie podejmuje żadnych działań w celu wyczyszczenia urządzenia, ponieważ w przypadku błędów punkty końcowe izochroniczne są czyszczone automatycznie.
Aby wyczyścić błąd kontrolera hosta, stos sterownika czyści stan ZATRZYMANIA potoku i resetuje przełącznik danych potoku do wartości 0.
Krok 5. Resetowanie portu USB
Jeśli operacja resetowania kanału nie wyczyści warunku błędu i transfery danych nadal kończą się niepowodzeniem, wyślij żądanie resetu portu.
Anuluj wszystkie transfery do urządzenia. W tym celu należy wyliczyć wszystkie potoki w bieżącej konfiguracji i anulować oczekujące żądania zaplanowane dla każdego potoku.
Zatrzymaj element docelowy we/wy dla urządzenia.
Wywołaj metodę WdfUsbTargetDeviceGetIoTarget, aby uzyskać dojście WDFIOTARGET skojarzone z obiektem urządzenia docelowego platformy. Następnie wywołaj WdfIoTargetStop i podaj uchwyt WDFIOTARGET. W wywołaniu ustaw akcję na WdfIoTargetCancelSentIo (WDF_IO_TARGET_SENT_IO_ACTION).
Wyślij żądanie resetowania portu, wywołując metodę WdfUsbTargetDeviceResetPortSynchronously.
Operacja reset-port powoduje ponowne wyliczenie urządzenia w magistrali USB. Stos sterowników USB zachowuje konfigurację urządzenia po wyliczeniu. Sterownik kliencki może korzystać z wcześniej uzyskanych uchwytów potoku, ponieważ stos sterowników gwarantuje, że istniejące uchwyty potoku nadal są ważne.
Nie można zresetować pojedynczej funkcji urządzenia złożonego. W przypadku urządzenia złożonego, gdy sterownik klienta określonej funkcji wysyła żądanie zresetowania portu, całe urządzenie jest resetowane. Jeśli urządzenie USB zachowuje stan, to żądanie resetowania portu również może mieć wpływ na sterowniki klienta innych funkcji. Dlatego ważne jest, aby sterownik klienta próbował zresetować rurę przed zresetowaniem portu.
Krok 6. Cykl portu USB
Działanie cyklu portu jest podobne do działania urządzenia, które jest odłączane i ponownie podłączane do portu, z wyjątkiem, że nie jest odłączane elektrycznie. Urządzenie jest odłączone i ponownie połączone w oprogramowaniu. Ta operacja prowadzi do resetowania i wyliczania urządzeń. W związku z tym menedżer PnP ponownie kompiluje węzeł urządzenia.
Jeśli operacja resetowania portu nie spowoduje wyczyszczenia warunku błędu, a transfery danych nadal kończą się niepowodzeniem, wyślij żądanie cyklu portu.
Anuluj wszystkie transfery do urządzenia. Upewnij się, że anulujesz oczekujące żądania zaplanowane dla każdego potoku w bieżącej konfiguracji (zobacz krok 3).
Zatrzymaj cel I/O urządzenia.
Wywołaj metodę WdfUsbTargetDeviceGetIoTarget, aby uzyskać dojście WDFIOTARGET skojarzone z obiektem urządzenia docelowego frameworku. Następnie wywołaj WdfIoTargetStop i określ uchwyt WDFIOTARGET. W wywołaniu ustaw akcję na WdfIoTargetCancelSentIo (WDF_IO_TARGET_SENT_IO_ACTION).
Wyślij żądanie dotyczące portu cyklu, wywołując jedną z następujących metod:
- Wywołaj WdfUsbTargetDeviceCyclePortSynchronously, aby synchronicznie wysłać żądanie portu cyklu.
- Wywołaj metodę WdfUsbTargetDeviceFormatRequestForCyclePort, aby sformatować obiekt żądania dla żądania portu cyklu, a następnie wysłać żądanie, wywołując metodę WdfRequestSend. Te wywołania są podobne do tych dla żądania przerwania potoku, zgodnie z opisem w kroku 3.
Sterownik klienta może wysyłać żądania transferu do urządzenia dopiero po zakończeniu żądania cyklu portu. Dzieje się tak, ponieważ węzeł urządzenia jest usuwany, gdy stos sterowników USB przetwarza żądanie cyklu portu.
Żądanie ponownej enumeracji portu powoduje ponowne wyliczenie urządzenia. Stos sterowników USB informuje Menedżera PnP, że urządzenie zostało odłączone. Menedżer PnP rozmontowuje stos urządzenia związany ze sterownikiem klienta. Sterownik resetuje urządzenie, ponownie enumeruje go na magistrali USB i informuje Menedżera PnP, że urządzenie zostało podłączone. Menedżer pnP następnie ponownie kompiluje stos urządzenia dla urządzenia USB.
W wyniku operacji portu cyklicznego każda aplikacja, która ma otwarte dojście do urządzenia, otrzymuje powiadomienie o usunięciu urządzenia (jeśli aplikacja jest zarejestrowana do otrzymywania takich powiadomień). W odpowiedzi aplikacja może zgłosić użytkownikowi komunikat o rozłączeniu urządzenia. Ponieważ ma to wpływ na doświadczenie użytkownika, sterownik klienta powinien wybrać żądanie cyklu portu tylko wtedy, gdy inne mechanizmy odzyskiwania nie rozwiążą problemu błędu.
Podobnie jak operacja resetowania portu (opisana w kroku 6), dla urządzenia złożonego, operacja przełączania portu ma wpływ na całe urządzenie, a nie poszczególne funkcje urządzenia.
Tematy pokrewne
- Kernel-Mode Platforma Sterowników
- transfery we/wy USB