2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
USB 2.0:ssa ja aiemmissa laitteissa joukkopäätepiste voi lähettää tai vastaanottaa yksittäisen datavirran päätepisteen kautta. USB 3.0 -laitteissa joukkopäätepiste pystyy lähettämään ja vastaanottamaan useita tietovirtoja päätepisteen kautta.
Microsoftin Windowsissa toimittama USB-ohjainpino tukee useita suoratoistoja. Tämän ansiosta asiakasohjaimet voivat lähettää itsenäisiä I/O-pyyntöjä jokaiseen USB 3.0 -laitteen joukkopäätepisteeseen liittyvään virtaan ilman, että pyyntöjä sarjoitetaan eri tietovirroihin.
Asiakasohjaimelle tietovirta edustaa useita loogisia päätepisteitä, joilla on samat ominaisuudet. Pyynnön lähettämiseksi tiettyyn tietovirtaan asiakasohjain tarvitsee kahvan kyseiselle virralle (samanlainen kuin päätepisteen putken kahva). I/O-pyyntöjen suoratoiston URB on samanlainen kuin joukkopäätepisteiden I/O-pyyntöjen URB. Ainoa ero on putken kahva. Lähettääkseen I/O-pyynnön streamiin ajuri määrittää putkikahvan virrassa.
Laitteen määrityksen aikana asiakasohjain lähettää valintamäärityspyynnön ja valinnaisesti valintaliittymäpyynnön. Nämä pyynnöt hakevat joukon putkikahvoja käyttöliittymän toiminta-asetuksissa määritetyille päätepisteille. Virtatietoisissa päätepisteissä päätepisteputken kahvaa voidaan käyttää I/O-pyyntöjen lähettämiseen oletusvirtaan (ensimmäiseen tietovirtaan), kunnes ohjain avaa virran.
Jos asiakasohjain haluaa lähettää pyyntöjä muille kuin oletusvirralle, ohjaimen on avattava ja hankittava kahvat kaikille virroille. Tätä varten asiakasohjain lähettää avoimen streamin pyynnön määrittämällä avattavien tietovirtojen määrän. Kun asiakasohjain on lopettanut streamien käytön, ohjain voi päättää sulkea ne lähettämällä streamin sulkemispyynnön.
Kernel Mode Driver Framework (KMDF) ei tue natiivisti staattisia virtoja. Asiakasohjaimien on käytettävä Windows-ohjainmallia (WDM) streamien avaamiseen ja sulkemiseen. User-mode Driver Framework (UMDF) -asiakasohjaimet eivät voi käyttää staattista suoratoistoominaisuutta.
Seuraavassa saattaa olla joitain kommentteja, jotka on merkitty WDM-ohjaimet. Nämä ohjeet kuvaavat rutiineja WDM-pohjaiselle USB-asiakasohjaimelle, joka haluaa lähettää suoratoistopyyntöjä.
Ennen kuin asiakasohjain voi avata tai sulkea streamin, ohjaimella on oltava:
1. Kutsu WdfUsbTargetDeviceCreateWithParameters-metodi. Menetelmä vaatii USBD_CLIENT_CONTRACT_VERSION_602 asiakasprotokollan version. Määrittämällä tämän version asiakasohjaimen on noudatettava tiettyjä sääntöjä.
Soita hakeaksesi kehyksen USB-kohdelaiteobjektin WDFUSBDEVICE-kahvan. Kahva tarvitaan myöhempiä kutsuja avoimeen streamiin. Tyypillisesti asiakasohjain rekisteröi itsensä ohjaimen EVT_WDF_DEVICE_PREPARE_HARDWARE-tapahtuman takaisinkutsurutiiniin.
WDM-ohjain: Kutsu USBD_CreateHandle-rutiini ja hanki ohjaimen USB-ohjainpinoon rekisteröimä USBD-kahva.
2. Määritti laitteen ja hanki WDFUSBPIPE-putkikahvan massapäätepisteeseen, joka tukee suoratoistoa. Saadaksesi putken kahvan, kutsu WdfUsbInterfaceGetConfiguredPipe-menetelmä valitun kokoonpanon liitännän nykyisissä vaihtoehtoisissa asetuksissa.
WDM-ohjain: Hakee USBD-putken kahvan lähettämällä valintakonfiguraatio- tai valintaliittymäpyynnön.
1. Selvitä, tukevatko taustalla oleva USB-ohjainpino ja isäntäohjain staattista suoratoistoominaisuutta kutsumalla WdfUsbTargetDeviceQueryUsbCapability-menetelmää. Tyypillisesti asiakasohjaimet kutsuvat rutiineja ohjaimen EVT_WDF_DEVICE_PREPARE_HARDWARE-tapahtuman takaisinkutsurutiinissa.
WDM-ohjain: Kutsuu USBD_QueryUsbCapability-rutiinia. Tyypillisesti ohjain kysyy toiminnon, jota käytetään ohjaimen käynnistyslaiterutiinissa (IRP_MN_START_DEVICE).
Anna seuraavat tiedot:
WDM-ajuri: Siirrä edellisessä kutsussa haettu USBD-kahva USBD_CreateHandlelle.
Jos asiakasohjain haluaa käyttää tiettyä ominaisuutta, ohjaimen on ensin tehtävä kysely taustalla olevasta USB-ohjainpinosta selvittääkseen, tukevatko ohjainpino ja isäntäohjain ominaisuutta. Jos ominaisuus on tuettu, vain silloin kuljettajan tulee lähettää pyyntö käyttää ominaisuutta. Tietyt pyynnöt edellyttävät URB:itä, kuten vaiheessa 5 käsitelty suoratoistotoiminto. Varmista näissä pyynnöissä, että käytät samaa kahvaa funktion kyselyyn ja URB:n varaamiseen. Tämä johtuu siitä, että ohjainpino käyttää kahvoja pitääkseen kirjaa tuetuista ominaisuuksista, joita ohjain voi käyttää.
Jos esimerkiksi USBD_HANDLE saatiin kutsumalla USBD_CreateHandle, ohjainpinoa kysytään kutsumalla USBD_QueryUsbCapability ja URB varataan kutsumalla USBD_UrbAllocate. Ohita sama USBD_HANDLE molemmissa puheluissa.
Jos kutsut KMDF-menetelmiä, WdfUsbTargetDeviceQueryUsbCapability- ja WdfUsbTargetDeviceCreateUrb, määritä sama WDFUSBDEVICE-kahva kehyksen kohdeobjektille näissä menetelmäkutsuissa.
2. Arvioi palautettu NTSTATUS-arvo. Jos rutiini valmistuu onnistuneesti, palautetaan STATUS_SUCCESS ja staattista suoratoistotoimintoa tuetaan. Muussa tapauksessa menetelmä palauttaa oikean virhekoodin.
3. Määritä avattavien streamien määrä. Avattavien streamien enimmäismäärää rajoittaa:
Voit määrittää virtojen enimmäismäärän valitsemalla pienempi kahdesta isäntäohjaimen ja päätepisteen tukemasta arvosta.
4. Varaa joukko n-elementtejä USBD_STREAM_INFORMATION-rakenteita, missä n on avattavien tietovirtojen määrä. Asiakasohjain on vastuussa tämän taulukon vapauttamisesta sen jälkeen, kun ohjain on käyttänyt streamia.
5. Varaa avoimen virran pyynnölle URB kutsumalla WdfUsbTargetDeviceCreateUrb-menetelmää. Jos puhelu päättyy onnistuneesti, menetelmä hakee WDF-muistiobjektin ja USB-ohjainpinon allokoiman URB-rakenteen osoitteen.
WDM-ohjain: Kutsuu USBD_UrbAllocate-rutiinia.
6. Aseta avoimen streamin pyynnön URB-muoto. URB käyttää _URB_OPEN_STATIC_STREAMS-rakennetta pyyntöjen määrittämiseen. URB:n muotoilemiseen tarvitset:
Muotoile URB soittamalla UsbBuildOpenStaticStreamsRequest ja välitä vaaditut tiedot parametriarvoina. Varmista, että UsbBuildOpenStaticStreamsRequestille määritetty streamien määrä ei ylitä tuettujen suoratoistojen enimmäismäärää.
7. Lähetä URB WDF-pyyntöobjektina kutsumalla WdfRequestSend-menetelmää. Jos haluat lähettää pyynnön synkronisesti, kutsu sen sijaan menetelmää WdfUsbTargetDeviceSendUrbSynchronously.
WDM-ohjain: yhdistää URB:n IRP:hen ja lähettää IRP:n USB-ohjainpinoon.
8. Kun pyyntö on valmis, tarkista pyynnön tila.Jos USB-ohjaimen pinopyyntö epäonnistuu, URB-tila sisältää asiaankuuluvan virhekoodin.
Jos pyynnön tila (IRP- tai WDF-pyyntöobjekti) osoittaa USBD_STATUS_SUCCESS, pyyntö on suoritettu onnistuneesti. Joukko USBD_STREAM_INFORMATION-rakenteita vastaanotettu, kun tarkistus on valmis. Taulukko on täytetty pyydetyn streamin tiedoilla. USB-ohjainpino täyttää jokaisen taulukon rakenteen tietovirtatiedoilla, kuten USBD_PIPE_HANDLE vastaanotetun kahvan, virran tunnisteen ja numeerisen enimmäissiirtokoon. Stream voi nyt siirtää tietoja.
Avoimen streamin pyyntöjä varten on allokoitava URB:t ja taulukot. Kun avoimen virran pyyntö on suoritettu, asiakasohjaimen on vapautettava URB kutsumalla WdfObjectDelete-menetelmä kyseisessä WDF-muistiobjektissa. Jos ajuri lähettää pyynnön synkronisesti kutsumalla WdfUsbTargetDeviceSendUrbSynchronously, WDF-muistiobjekti on vapautettava menetelmän palattua. Jos asiakasohjain lähettää pyynnön asynkronisesti kutsumalla WdfRequestSendiä, ohjaimen on vapautettava WDF-muistiobjekti pyyntöön liittyvässä ohjaimen toteuttamassa viimeistelyrutiinissa.
Tietovirtataulukko voidaan vapauttaa sen jälkeen, kun asiakasohjain on lopettanut virran käytön, tai se voidaan tallentaa I/O-pyyntöjä varten. Alla olevassa koodiesimerkissä ohjain tallentaa virtataulukon laitekontekstiin. Ajuri vapauttaa laitekontekstin ennen laiteobjektin vapauttamista.
Kuinka siirtää tietoja tiettyyn streamiin
Tiedonsiirtopyynnön lähettämiseksi tiettyyn tietovirtaan tarvitaan WDF-pyyntöobjekti. Tyypillisesti asiakasohjaimien ei tarvitse varata WDF-pyyntöobjekteja. Kun I/O-manageri vastaanottaa pyynnön sovelluksesta, I/O-manageri luo pyynnölle IRP:n. Puitteet sieppasivat IRP:n. Tämän jälkeen kehys varaa WDF-pyyntöobjektin edustamaan IRP:tä. Tämän jälkeen kehys välittää WDF-pyyntöobjektin asiakasohjaimelle. Asiakasohjain voi sitten liittää pyyntöobjektin tiedonsiirto-URB:hen ja lähettää sen USB-ohjainpinoon.
Jos asiakasohjain ei vastaanota WDF-pyyntöobjektia viitekehyksestä ja haluaa lähettää pyynnön asynkronisesti, ohjaimen on varattava WDF-pyyntöobjekti kutsumalla WdfRequestCreate-menetelmää. Muotoile uusi objekti kutsumalla WdfUsbTargetPipeFormatRequestForUrb ja lähetä pyyntö kutsumalla WdfRequestSend.
Synkronisessa tapauksessa WDF-pyyntöobjektin välittäminen on valinnaista.
Tietojen siirtämiseksi streamiin on käytettävä URB:tä. URB on alustettava kutsumalla WdfUsbTargetPipeFormatRequestForUrb.
Streamit eivät tue seuraavia WDF-menetelmiä:
Seuraava menettely olettaa, että asiakasohjain vastaanottaa pyyntöobjektin viitekehyksestä.
WDM-ohjain: Varaa URB:n kutsumalla USBD_UrbAllocate ja alustaa sen joukkosiirtoa varten (katso _URB_BULK_OR_INTERRUPT_TRANSFER). Voit muotoilla URB:n kutsumalla UsbBuildInterruptOrBulkTransferRequest tai muotoilemalla URB-rakenteen manuaalisesti. Määritä virran kahva URB:n UrbBulkOrInterruptTransfer.PipeHandle-jäsenessä.
Asiakasohjain voi sulkea streamin, kun ohjain on lopettanut sen käytön. Suoratoistopyynnön sulkeminen on kuitenkin valinnaista. USB-ohjainpino sulkee kaikki streamit, kun streamiin liittyvää päätepistettä ei ole määritetty. Päätepisteitä ei määritetä, kun valitaan vaihtoehtoinen kokoonpano tai käyttöliittymä, poistetaan laitetta jne. Jos asiakasohjain haluaa avata eri määrän streameja, sen on suljettava streamit. Lähetä streamin sulkemispyyntö:
1. Varaa URB-rakenne kutsumalla WdfUsbTargetDeviceCreateUrb.
2. Aseta URB-muoto suoratoistopyynnön sulkemista varten. URB-rakenteen UrbPipeRequest-jäsen on _URB_PIPE_REQUEST-rakenne. Täytä sen jäsenet seuraavasti:
3. Lähetä URB WDF-pyynnönä soittamalla WdfUsbTargetDeviceSendUrbSynchronously.
Sulje kahva pyytää sulkemaan kaikki asiakasohjaimen aiemmin avaamat virrat. Asiakasohjain ei voi käyttää pyyntöjä tietyn virran sulkemiseen päätepisteessä.
USB-ohjainpino tarkistaa vastaanotetun URB:n. Vahvistusvirheiden välttämiseksi toimi seuraavasti:
Joskus siirrot päätepisteeseen tai päätepisteestä voivat epäonnistua. Tällaiset virheet voivat johtua päätepisteen tai isäntäohjaimen virheolosuhteista, kuten pysäytys- tai pysäytystila. Virhetilan poistamiseksi asiakasohjain ensin peruuttaa odottavan siirron ja nollaa sitten päätepisteeseen liittyvän putken. Odottavan siirron peruuttamiseksi asiakasohjain voi lähettää keskeytysputken pyynnön. Putken nollaamiseksi asiakasohjaimen on lähetettävä putken nollauspyyntö.
Suoratoiston keskeyttämis- ja reset-pipe-pyyntöjä ei tueta joukkopäätepisteeseen liittyville yksittäisille virroille. Jos siirto tietyssä stream-putkessa epäonnistuu, isäntäohjain lopettaa kaikkien muiden putkien siirrot Virhetilanteen korjaamiseksi, asiakasohjaimen on peruutettava siirto jokaiseen tietovirtaan putken kahva, joka lähettää nollauspyynnön joukkopäätepisteeseen. Tätä pyyntöä varten asiakasohjaimen on määritettävä päätepisteen putken kahva rakenteessa _URB_PIPE_REQUEST ja asetettava URB-funktioksi (Hdr.Function) URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL.
Seuraava koodiesimerkki havainnollistaa streamin avaamisen.
- NTSTATUS
- OpenStreams (
- _In_ WDFDEVICE Device,
- _In_ WDFUSBPIPE Pipe)
- {
- NTSTATUS status;
- PDEVICE_CONTEXT deviceContext;
- PPIPE_CONTEXT pipeContext;
- USHORT cStreams = 0;
- USBD_PIPE_HANDLE usbdPipeHandle;
- WDFMEMORY urbMemory = NULL;
- PURB urb = NULL;
-
- PAGED_CODE();
-
- deviceContext =GetDeviceContext(Device);
- pipeContext = GetPipeContext (Pipe);
-
- if (deviceContext->MaxStreamsController == 0)
- {
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
- "%!FUNC! Static streams are not supported.");
-
- status = STATUS_NOT_SUPPORTED;
- goto Exit;
- }
-
- // If static streams are not supported, number of streams supported is zero.
-
- if (pipeContext->MaxStreamsSupported == 0)
- {
- status = STATUS_DEVICE_CONFIGURATION_ERROR;
-
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
- "%!FUNC! Static streams are not supported by the endpoint.");
-
- goto Exit;
- }
-
- // Determine the number of streams to open.
- // Compare the number of streams supported by the endpoint with the
- // number of streams supported by the host controller, and choose the
- // lesser of the two values. The deviceContext->MaxStreams value was
- // obtained in a previous call to WdfUsbTargetDeviceQueryUsbCapability
- // that determined whether or not static streams is supported and
- // retrieved the maximum number of streams supported by the
- // host controller. The device context stores the values for IN and OUT
- // endpoints.
-
- // Allocate an array of USBD_STREAM_INFORMATION structures to store handles to streams.
- // The number of elements in the array is the number of streams to open.
- // The code snippet stores the array in its device context.
-
- cStreams = min(deviceContext->MaxStreamsController, pipeContext->MaxStreamsSupported);
-
- // Allocate an array of streams associated with the IN bulk endpoint
- // This array is released in CloseStreams.
-
- pipeContext->StreamInfo = (PUSBD_STREAM_INFORMATION) ExAllocatePoolWithTag (
- NonPagedPool,
- sizeof (USBD_STREAM_INFORMATION) * cStreams,
- USBCLIENT_TAG);
-
- if (pipeContext->StreamInfo == NULL)
- {
- status = STATUS_INSUFFICIENT_RESOURCES;
-
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
- "%!FUNC! Could not allocate stream information array.");
-
- goto Exit;
- }
-
- RtlZeroMemory (pipeContext->StreamInfo,
- sizeof (USBD_STREAM_INFORMATION) * cStreams);
-
- // Get USBD pipe handle from the WDF target pipe object. The client driver received the
- // endpoint pipe handles during device configuration.
-
- usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle (Pipe);
-
- // Allocate an URB for the open streams request.
- // WdfUsbTargetDeviceCreateUrb returns the address of the
- // newly allocated URB and the WDFMemory object that
- // contains the URB.
-
- status = WdfUsbTargetDeviceCreateUrb (
- deviceContext->UsbDevice,
- NULL,
- &urbMemory,
- &urb);
-
- if (status != STATUS_SUCCESS)
- {
- TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE,
- "%!FUNC! Could not allocate URB for an open-streams request.");
-
- goto Exit;
- }
-
- // Format the URB for the open-streams request.
- // The UsbBuildOpenStaticStreamsRequest inline function formats the URB by specifying the
- // pipe handle to the entire bulk endpoint, number of streams to open, and the array of stream structures.
-
- UsbBuildOpenStaticStreamsRequest (
- urb,
- usbdPipeHandle,
- (USHORT)cStreams,
- pipeContext->StreamInfo);
-
- // Send the request synchronously.
- // Upon completion, the USB driver stack populates the array of with handles to streams.
-
- status = WdfUsbTargetPipeSendUrbSynchronously (
- Pipe,
- NULL,
- NULL,
- urb);
-
- if (status != STATUS_SUCCESS)
- {
- goto Exit;
- }
-
- Exit:
- if (urbMemory)
- {
- WdfObjectDelete (urbMemory);
- }
-
- return status;
- }