Sdílet prostřednictvím


Jak odeslat USB kontrolní přenos

Tento článek vysvětluje strukturu přenosu řízení a jak by měl klientský ovladač odesílat kontrolní požadavek do zařízení.

Informace o výchozím koncovém bodu

Všechna zařízení USB musí podporovat alespoň jeden koncový bod označovaný jako výchozí koncový bod. Jakýkoli přenos, který cílí na výchozí koncový bod, se nazývá přenos řízení. Účelem přenosu ovládacích prvků je umožnit hostiteli získat informace o zařízení, nakonfigurovat zařízení nebo provádět řídicí operace, které jsou pro zařízení jedinečné.

Začněme zkoumáním těchto charakteristik výchozího koncového bodu.

  • Adresa výchozího koncového bodu je 0.
  • Výchozí koncový bod je obousměrný, to znamená, že hostitel může odesílat data do koncového bodu a přijímat z něj data v rámci jednoho přenosu.
  • Výchozí koncový bod je k dispozici na úrovni zařízení a není definován v žádném rozhraní zařízení.
  • Výchozí koncový bod je aktivní hned po navázání připojení mezi hostitelem a zařízením. Je aktivní ještě předtím, než je vybrána konfigurace.
  • Maximální velikost paketu výchozího koncového bodu závisí na rychlosti sběrnice zařízení. Nízká rychlost, 8 bajtů; plná a vysoká rychlost, 64 bajtů; SuperSpeed, 512 bajtů.

Rozložení přenosu ovládacího prvku

Vzhledem k tomu, že přenosy řízení mají vysokou prioritu, vyhrazuje host určitou kapacitu na sběrnici. Pro zařízení s nízkou a plnou rychlostí 10% šířky pásma; 20% pro zařízení s přenosy vysoké a SuperSpeed rychlosti. Teď se podíváme na rozložení přenosu ovládacích prvků.

Diagram přenosu ovládacího prvku USB

Přenos ovládacích prvků je rozdělen na tři transakce: nastavení transakce, transakce dat a stav transakce. Každá transakce obsahuje tři typy paketů: paket tokenu, datový paket a paket handshake.

Určitá pole jsou společná pro všechny pakety. Tato pole jsou:

  • Synchronizační pole označující začátek paketu.
  • Identifikátor paketu (PID), který označuje typ paketu, směr transakce a v případě paketu handshake označuje úspěch nebo selhání transakce.
  • Pole EOP označuje konec paketu.

Další pole závisí na typu paketu.

Tokenový paket

Každá transakce nastavení začíná paketem tokenu. Tady je struktura paketu. Hostitel vždy odešle paket tokenu.

Diagram rozložení paketů tokenu

Hodnota PID označuje typ paketu tokenu. Tady jsou možné hodnoty:

  • NASTAVENÍ: Označuje začátek instalační transakce v ovládacím přenosu.
  • IN: Označuje, že hostitel požaduje data ze zařízení (případ čtení).
  • OUT: Označuje, že hostitel odesílá data do zařízení (případ zápisu).
  • SOF: Označuje začátek rámce. Tento typ paketu tokenu obsahuje 11bitové číslo rámce. Hostitel odešle paket SOF. Frekvence odesílání tohoto paketu závisí na rychlosti sběrnice. Pro plnou rychlost hostitel odešle paket každých 1 milisekund; každých 125 mikrosekund na vysokorychlostní sběrnici.

Datový paket

Ihned za tokenovým paketem je datový paket, který obsahuje užitečná data. Počet bajtů, které může každý datový paket obsahovat, závisí na maximální velikosti paketů výchozího koncového bodu. Datový paket může posílat hostitel nebo zařízení v závislosti na směru přenosu.

Diagram rozložení datového paketu

Balíček handshake

Ihned za datovým paketem následuje paket handshake. KÓD PID paketu označuje, zda byl paket přijat hostitelem nebo zařízením. Paket handshake může poslat hostitel nebo zařízení v závislosti na směru přenosu.

Diagram rozložení handshake paketu.

Strukturu transakcí a paketů můžete zobrazit pomocí libovolného analyzátoru USB, jako jsou Beagle, Ellisys, Analyzátory protokolu LeCroy USB. Analyzátor zařízení ukazuje, jak se data odesílají nebo přijímají ze zařízení USB přes drát. V tomto příkladu prozkoumáme některé stopy zachycené analyzátorem LeCroy USB. Tento příklad je určen pouze pro informace. Microsoft toto doporučení nepodporuje.

Nastavení transakce

Hostitel vždy zahájí přenos ovládání. Provede to tím, že odešle transakci nastavení. Tato transakce obsahuje paket tokenu označovaný jako token nastavení následovaný 8 bajtovým datovým paketem. Tento snímek obrazovky ukazuje příklad transakce instalace.

Snímek obrazovky s trasou transakce nastavení.

V předchozím trasování hostitel iniciuje (označeno ) přenos ovládacího prvku odesláním paketu tokenu nastavení č. 434. Všimněte si, že PID specifikuje SETUP, což znamená setup token. ZA PID následuje adresa zařízení a adresa koncového bodu. Pro přenosy ovládacích prvků je tato adresa koncového bodu vždy 0.

Dále hostitel odešle datový paket č. 435. PID je DATA0 a tato hodnota se používá pro sekvencování paketů (prodiskutováno). Po PID následuje 8 bajtů, které obsahují hlavní informace o této žádosti. Tyto 8 bajtů označují typ požadavku a velikost vyrovnávací paměti, do které zařízení zapíše svou odpověď.

Všechny bajty se přijímají v obráceném pořadí. Jak je popsáno v části 9.3, vidíme tato pole a hodnoty:

(No improvements necessary, the translation is already optimal.) Velikost Hodnota Popis
bmRequestType (Viz 9.3.1 bmRequestType) 1 0x80 Směr přenosu dat je ze zařízení do hostitele (D7 je 1).

Požadavek je standardní požadavek (D6... D5 je 0)

Příjemcem žádosti je ZAŘÍZENÍ (D4 je 0).
bRequest (viz bod 9.3.2 a tabulka 9-4) 1 0x06 Typ požadavku je GET_DESCRIPTOR.
wValue (viz tabulka 9–5) 2 0x0100 Hodnota požadavku označuje, že typ popisovače je DEVICE.
wIndex (viz bod 9.3.4) 2 0x0000 Směr je od hostitele k zařízení (D7 je 1).

Číslo koncového bodu je 0.
wLength (viz bod 9.3.5) 2 0x0012 Požadavek je načíst 18 bajtů.

Můžeme tedy dojít k závěru, že v tomto ovládacím prvku (pro čtení) hostitel odešle požadavek na načtení popisovače zařízení a jako délku přenosu určuje 18 bajtů pro uložení tohoto popisovače. Způsob, jakým zařízení odesílá tyto 18 bajtů, závisí na tom, kolik dat může výchozí koncový bod odeslat v jedné transakci. Informace jsou zahrnuty do popisovače zařízení vráceného zařízením v datové transakci.

V reakci zařízení odešle paket handshake (#436 označený D↓). Všimněte si, že hodnota PID je ACK (paket ACK). To znamená, že zařízení potvrdilo transakci.

Transakce dat

Teď se podíváme, co zařízení vrací v reakci na požadavek. Skutečná data se přenesou v datové transakci.

Tady je trasování datové transakce.

Snímek obrazovky znázorňující trasování ukázkové datové transakce

Po přijetí paketu ACK zahájí hostitel datovou transakci. Chcete-li zahájit transakci, odešle paket tokenu (#450) se směrem IN, který se nazývá IN token.

V reakci zařízení odešle datový paket (#451), který následuje za tokenem IN. Tento datový paket obsahuje skutečný popisovač zařízení. První bajt označuje délku popisovače zařízení, 18 bajtů (0x12). Poslední bajt v tomto datovém paketu označuje maximální velikost paketů podporovanou výchozím koncovým bodem. V tomto případě vidíme, že zařízení může posílat 8 bajtů najednou prostřednictvím svého výchozího koncového bodu.

Poznámka:

Maximální velikost paketu výchozího koncového bodu závisí na rychlosti zařízení. Výchozí koncový bod vysokorychlostního zařízení je 64 bajtů; zařízení s nízkou rychlostí je 8 bajtů.

Hostitel potvrdí datovou transakci odesláním paketu ACK (#452) do zařízení.

Pojďme vypočítat množství vrácených dat. V poli wLength datového paketu (#435) v transakci nastavení hostitel požadoval 18 bajtů. V datové transakci vidíme, že ze zařízení bylo přijato pouze prvních 8 bajtů popisovače zařízení. Jak tedy hostitel přijímá informace uložené ve zbývajících 10 bajtech? Zařízení to provede ve dvou transakcích: 8 bajtů a pak posledních 2 bajty.

Teď, když hostitel zná maximální velikost paketu výchozího koncového bodu, zahájí hostitel novou datovou transakci a vyžádá další část na základě velikosti paketu.

Tady je další datová transakce:

Snímek obrazovky znázorňující trasování nové datové transakce

Hostitel zahájí předchozí datovou transakci odesláním tokenu IN (#463) a vyžádáním dalších 8 bajtů ze zařízení. Zařízení odpoví datovým paketem (#464), který obsahuje dalších 8 bajtů popisovače zařízení.

Po přijetí 8 bajtů hostitel odešle do zařízení paket ACK (#465).

Dále hostitel požaduje poslední 2 bajty v jiné datové transakci následujícím způsobem:

Snímek obrazovky znázorňující trasování nové ukázkové datové transakce, ve které hostitel požaduje posledních 2 bajty

Proto vidíme, že pokud chcete přenést 18 bajtů ze zařízení na hostitele, hostitel sleduje počet bajtů přenesených a inicializoval tři datové transakce (8+8+2).

Poznámka:

Všimněte si PID datových paketů v datových transakcích 19, 23, 26. PID se střídá mezi DAT0 a DATA1. Tato posloupnost se nazývá přepínání dat. V případech, kdy dochází k více datovým transakcím, se k ověření sekvence paketů používá střídání dat. Tato metoda zajišťuje, aby datové pakety nebyly duplikovány nebo ztraceny.

Mapováním konsolidovaných datových paketů na strukturu popisovače zařízení (viz tabulka 9–8) vidíme tato pole a hodnoty:

(No improvements necessary, the translation is already optimal.) Velikost Hodnota Popis
bLength 1 0x12 Délka popisovače zařízení, což je 18 bajtů.
bDescriptorType 1 0x01 Typ popisovače je zařízení.
bcdUSB 2 0x0100 Číslo verze specifikace je 1.00.
bDeviceClass 1 0x00 Třída zařízení je 0. Každé rozhraní v konfiguraci má informace o třídě.
bDeviceSubClass 1 0x00 Podtřída je 0, protože třída zařízení je 0.
bProtocol 1 0x00 Protokol je 0. Toto zařízení nepoužívá žádné protokoly specifické pro třídu.
bMaxPacketSize0 1 0x08 Maximální velikost paketu koncového bodu je 8 bajtů.
idVendor 2 0x0562 Telex Communications.
idProduct 2 0x0002 Usb mikrofon.
bcdDevice 2 0x0100 Označuje číslo verze zařízení.
iManufacturer 1 0x01 Řetězec výrobce.
iProduct 1 0x02 Řetězec produktu.
iSerialNumber 1 0x03 Sériové číslo.
bNumConfigurations 1 0x01 Početkonfiguracích

Prozkoumáním těchto hodnot máme o zařízení nějaké předběžné informace. Zařízení je mikrofon USB s nízkou rychlostí. Maximální velikost paketu výchozího koncového bodu je 8 bajtů. Zařízení podporuje jednu konfiguraci.

Status transakce

Nakonec hostitel dokončí přenos řízení zahájením poslední transakce: stav transakce.

Snímek obrazovky s trasou ukázkové datové transakce

Hostitel spustí transakci paketem tokenu OUT (#481). Účelem tohoto paketu je ověřit, že zařízení odeslalo všechna požadovaná data. V této transakci stavu se neposílají žádné datové pakety. Zařízení reaguje paketem ACK. Pokud došlo k chybě, mohl být KÓD PID buď NAK, nebo STALL.

Modely ovladačů

Požadavky

Než klientský ovladač může vytvořit výčet kanálů, ujistěte se, že jsou splněny tyto požadavky:

  • Klientský ovladač musí vytvořit objekt cílového zařízení USB ve frameworku.

    Pokud používáte šablony USB poskytované v sadě Microsoft Visual Studio Professional 2012, kód šablony tyto úlohy provede. Kód šablony získá popisovač objektu cílového zařízení a uloží ho v kontextu zařízení.

Ovladač klienta KmDF

Klientský ovladač KMDF musí získat popisovač WDFUSBDEVICE voláním metody WdfUsbTargetDeviceCreateWithParameters. Další informace najdete v tématu "Zdrojový kód zařízení" v tématu Principy struktury kódu klientského ovladače USB (KMDF).

Klientský ovladač UMDF

Klientský ovladač UMDF musí získat ukazatel IWDFUsbTargetDevice dotazováním objektu cílového zařízení architektury. Další informace najdete v tématu Implementace IPnpCallbackHardware a úlohy specifické pro USB v tématu Principy struktury kódu ovladače klienta USB (UMDF).

Nejdůležitějším aspektem přenosu ovládacího prvku je správně naformátovat token nastavení. Před odesláním požadavku shromážděte tuto sadu informací:

  • Směr požadavku: od hostitele k zařízení nebo od zařízení k hostiteli.
  • Příjemce požadavku: zařízení, rozhraní, koncový bod nebo jiný.
  • Kategorie požadavku: standard, třída nebo dodavatel.
  • Typ požadavku, například požadavek GET_DESCRIPTPOR. Další informace naleznete v části 9.5 specifikace USB.
  • wValue a wIndex hodnoty. Tyto hodnoty závisí na typu požadavku.

Všechny informace můžete získat z oficiální specifikace USB.

Pokud píšete ovladač UMDF, získejte hlavičkový soubor Usb_hw.h z ukázkového ovladače UMDF pro OSR USB Fx2 Learning Kit. Tento soubor záhlaví obsahuje užitečná makra a strukturu pro formátování instalačního paketu pro přenos ovládacího prvku.

Všechny ovladače UMDF musí komunikovat s ovladačem režimu jádra, aby bylo možné odesílat a přijímat data ze zařízení. Pro ovladač USB UMDF je ovladač v režimu jádra vždy ovladač WinUSB poskytovaný společností Microsoft (Winusb.sys).

Pokaždé, když ovladač UMDF odešle požadavek na zásobník ovladačů USB, správce vstupně-výstupních operací systému Windows odešle požadavek do WinUSB. Po přijetí požadavku WinUSB žádost buď zpracuje, nebo ji předá do zásobníku ovladačů USB.

Metody definované Microsoftem pro odesílání žádostí o přenos řízení

Ovladač klienta USB na hostiteli inicializuje většinu řídicích požadavků na získání informací o zařízení, konfiguraci zařízení nebo odeslání řídicích příkazů dodavatele. Všechny tyto požadavky je možné zařadit do kategorií:

  • Standardní požadavky jsou definovány ve specifikaci USB. Účelem odesílání standardních požadavků je získat informace o zařízení, jeho konfiguracích, rozhraních a koncových bodech. Příjemce každého požadavku závisí na typu žádosti. Příjemcem může být zařízení, rozhraní nebo koncový bod.

    Poznámka:

    Cílem jakéhokoli přenosu ovládacích prvků je vždy výchozí koncový bod. Příjemce je entita zařízení, o jejíž informace (popisovač, stav atd.) má hostitel zájem.

    Požadavky je možné dále klasifikovat: požadavky na konfiguraci, žádosti o funkce a žádosti o stav.

    • Požadavky na konfiguraci se odesílají za účelem získání informací ze zařízení, aby ho hostitel mohl nakonfigurovat, například požadavek GET_DESCRIPTOR. Tyto požadavky mohou být také požadavky na zápis odeslané hostitelem za účelem nastavení konkrétní konfigurace nebo alternativního nastavení v zařízení.
    • Žádosti o funkce odesílá klientský ovladač, aby bylo možné povolit nebo zakázat určitá booleovská nastavení zařízení podporovaná zařízením, rozhraním nebo koncovým bodem.
    • Požadavky na stav umožňují hostiteli získat nebo nastavit bity stavu definované rozhraním USB zařízení, koncového bodu nebo rozhraní.

    Další informace naleznete v části 9.4 specifikace USB verze 2.0. Standardní typy požadavků jsou definovány hlavičkovým souborem Usbspec.h.

  • Požadavky na třídy jsou definovány konkrétní specifikací třídy zařízení.

  • Žádosti o dodavatele poskytuje dodavatel a závisí na požadavcích podporovaných zařízením.

Zásobník USB poskytovaný společností Microsoft zpracovává veškerou komunikaci protokolu se zařízením, jak je uvedeno v předchozích záznamech. Ovladač zveřejňuje rozhraní ovladačů zařízení (DDI), která umožňují klientskému ovladači posílat řídicí přenosy mnoha způsoby. Pokud je vaším klientským ovladačem ovladač Windows Driver Foundation (WDF), může volat rutiny přímo pro odesílání běžných typů žádostí o řízení. WDF podporuje přenosy ovládacích prvků vnitřně pro KMDF i UMDF.

Některé typy žádostí o řízení nejsou prostřednictvím WDF zpřístupněny. Pro tyto požadavky může klientský ovladač použít model WDF-hybrid. Tento model umožňuje klientskému ovladači vytvářet a formátovat požadavky ve stylu WDM URB a pak tyto požadavky odesílat pomocí objektů rozhraní WDF. Hybridní model se vztahuje pouze na ovladače režimu jádra.

Pro ovladače UMDF:

Použijte pomocná makra a strukturu definovanou v usb_hw.h. Tato hlavička je součástí ukázkového ovladače UMDF pro OSR USB Fx2 Learning Kit.

Pomocí této tabulky určíte nejlepší způsob odesílání žádostí o řízení do zásobníku ovladačů USB.

Pokud chcete odeslat žádost o kontrolu... Pro ovladač KMDF... Pro ovladač UMDF... Pro ovladač WDM sestavte strukturu URB (pomocná rutina).
CLEAR_FEATURE: Zakažte určitá nastavení funkcí v zařízení, jeho konfiguracích, rozhraních a koncových bodech. Viz bod 9.4.1 ve specifikaci USB.
  1. Deklarujte instalační paket. Prohlédněte si strukturu WDF_USB_CONTROL_SETUP_PACKET .
  2. Inicializace instalačního paketu voláním WDF_USB_CONTROL_SETUP_PACKET_INIT_FEATURE.
  3. Zadejte hodnotu příjemce definovanou v WDF_USB_BMREQUEST_RECIPIENT.
  4. Zadejte selektor funkcí (wValue). Viz USB_FEATURE_XXX konstanty v usbspec.h. Viz také tabulka 9-6 ve specifikaci USB.
  5. Nastavte SetFeature na FALSE.
  6. Odeslat požadavek voláním WdfUsbTargetDeviceSendControlTransferSynchronously nebo WdfUsbTargetDeviceFormatRequestForControlTransfer.
  1. Deklarujte instalační paket. Viz struktura WINUSB_CONTROL_SETUP_PACKET deklarovaná v usb_hw.h.
  2. Inicializace instalačního paketu voláním pomocného makra WINUSB_CONTROL_SETUP_PACKET_INIT_FEATURE definovaného v usb_hw.h.
  3. Zadejte hodnotu příjemce definovanou v WINUSB_BMREQUEST_RECIPIENT.
  4. Zadejte selektor funkcí (wValue). Viz USB_FEATURE_XXX konstanty v usbspec.h. Viz také tabulka 9-6 ve specifikaci USB.
  5. Nastavte SetFeature na FALSE.
  6. Sestavte požadavek spojením inicializovaného nástavbového paketu s objektem požadavku infrastruktury a přenosové vyrovnávací paměti voláním metody IWDFUsbTargetDevice::FormatRequestForControlTransfer.
  7. Odešlete požadavek voláním metody IWDFIoRequest::Send .
_URB_CONTROL_FEATURE_REQUEST

(UsbBuildFeatureRequest)

URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE

URB_FUNKCE_VYMAZAT_FUNKCI_K_ROZHRANÍ

FUNKCE_CLEAR_FEATURE_DO_KONCOVÉHO_BODU

Funkce URB vymazání vlastnosti k druhé zařízení
GET_CONFIGURATION: Získejte aktuální konfiguraci USB. Podívejte se na bod 9.4.2 ve specifikaci USB. KMDF ve výchozím nastavení vybere první konfiguraci. K načtení čísla konfigurace definovaného zařízením:

  1. Naformátovat WDF_USB_CONTROL_SETUP_PACKET a nastavit jeho člen bRequest na USB_REQUEST_GET_CONFIGURATION.
  2. Odeslat požadavek voláním WdfUsbTargetDeviceSendControlTransferSynchronously nebo WdfUsbTargetDeviceFormatRequestForControlTransfer.
UmDF ve výchozím nastavení vybere první konfiguraci. K načtení čísla konfigurace definovaného zařízením:

  1. Deklarujte instalační paket. Viz struktura WINUSB_CONTROL_SETUP_PACKET deklarovaná v usb_hw.h.
  2. Inicializace instalačního paketu voláním pomocného makra WINUSB_CONTROL_SETUP_PACKET_INIT definovaného v usb_hw.h.
  3. Jako směr zadejte BmRequestToDevice , jako příjemce BmRequestToDevice a jako požadavek USB_REQUEST_GET_CONFIGURATION .
  4. Sestavte požadavek spojením inicializovaného nástavbového paketu s objektem požadavku infrastruktury a přenosové vyrovnávací paměti voláním metody IWDFUsbTargetDevice::FormatRequestForControlTransfer.
  5. Odešlete požadavek voláním metody IWDFIoRequest::Send .
  6. Přijměte číslo konfigurace ve vyrovnávací paměti přenosu. K přístupu k této vyrovnávací paměti použijte volání metod IWDFMemory.
_URB_CONTROL_GET_CONFIGURATION_REQUEST

URB_FUNCTION_GET_CONFIGURATION
GET_DESCRIPTOR: Získání popisovačů zařízení, konfigurace, rozhraní a koncových bodů Viz oddíl 9.4.3 ve specifikaci USB.

Další informace najdete v tématu Popisovače USB.
Volejte tyto metody:

Volejte tyto metody:

_URB_CONTROL_DESCRIPTOR_REQUEST

(UsbBuildGetDescriptorRequest)

URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE

URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT

URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE (funkce získání deskriptoru z rozhraní)
GET_INTERFACE: Získejte aktuální alternativní nastavení pro rozhraní. Vizte část 9.4.4 ve specifikaci USB.

  1. Získejte popisovač WDFUSBINTERFACE pro objekt cílového rozhraní voláním metody WdfUsbTargetDeviceGetInterface.
  2. Zavolejte metodu WdfUsbInterfaceGetConfiguredSettingIndex.
  1. Získejte ukazatel IWDFUsbInterface na objekt cílového rozhraní.
  2. Zavolejte metodu IWDFUsbInterface::GetConfiguredSettingIndex.
_URB_CONTROL_GET_INTERFACE_REQUEST

URB_FUNCTION_GET_INTERFACE
GET_STATUS: Získání bitů stavu ze zařízení, koncového bodu nebo rozhraní Viz oddíl 9.4.5. ve specifikaci USB.
  1. Deklarujte instalační paket. Prohlédněte si strukturu WDF_USB_CONTROL_SETUP_PACKET .
  2. Inicializace instalačního paketu voláním WDF_USB_CONTROL_SETUP_PACKET_INIT_GET_STATUS.
  3. Zadejte hodnotu příjemce definovanou v WDF_USB_BMREQUEST_RECIPIENT.
  4. Zadejte, jaký stav chcete získat: zařízení, rozhraní nebo koncový bod (wIndex).
  5. Odeslat požadavek voláním WdfUsbTargetDeviceSendControlTransferSynchronously nebo WdfUsbTargetDeviceFormatRequestForControlTransfer.
  1. Deklarujte instalační paket. Viz struktura WINUSB_CONTROL_SETUP_PACKET deklarovaná v usb_hw.h.
  2. Inicializace instalačního paketu voláním pomocného makra WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS definovaného v usb_hw.h.
  3. Zadejte hodnotu příjemce definovanou v WINUSB_BMREQUEST_RECIPIENT.
  4. Zadejte, jaký stav chcete získat: zařízení, rozhraní nebo koncový bod (wIndex).
  5. Sestavte požadavek spojením inicializovaného nástavbového paketu s objektem požadavku infrastruktury a přenosové vyrovnávací paměti voláním metody IWDFUsbTargetDevice::FormatRequestForControlTransfer.
  6. Odešlete požadavek voláním metody IWDFIoRequest::Send .
  7. Přijme stavovou hodnotu v vyrovnávací paměti přenosu. K přístupu k této vyrovnávací paměti použijte volání metod IWDFMemory.
  8. Pokud chcete zjistit, jestli stav indikuje samoobslužné vzdálené probuzení, použijte hodnoty definované v WINUSB_DEVICE_TRAITS výčtu:
_URB_CONTROL_GET_STATUS_REQUEST

(UsbBuildGetStatusRequest)

URB_FUNCTION_GET_STATUS_FROM_DEVICE

URB_FUNCTION_ZÍSKAT_STATUS_Z_ROZHRANÍ

URB_FUNCTION_GET_STATUS_FROM_ENDPOINT

Funkce URB vrátí stav z jiného.
SET_ADDRESS: Viz bod 9.4.6 ve specifikaci USB. Tento požadavek zpracovává zásobník ovladačů USB; ovladač klienta nemůže tuto operaci provést. Tento požadavek zpracovává zásobník ovladačů USB; ovladač klienta nemůže tuto operaci provést. Tento požadavek zpracovává zásobník ovladačů USB; ovladač klienta nemůže tuto operaci provést.
SET_CONFIGURATION: Nastavte konfiguraci. Viz odstavec 9.4.7 ve specifikaci USB.

Další informace naleznete v tématu Jak vybrat konfiguraci pro zařízení USB.
Ve výchozím nastavení služba KMDF vybere výchozí konfiguraci a první alternativní nastavení v každém rozhraní. Klientský ovladač může změnit výchozí konfiguraci voláním metody WdfUsbTargetDeviceSelectConfigType a zadáním WdfUsbTargetDeviceSelectConfigTypeUrb jako možnosti požadavku. Pak musíte pro tento požadavek vytvořit URB zprávu a odeslat ji do USB ovladačového zásobníku. Ve výchozím nastavení UMDF vybere výchozí konfiguraci a první alternativní nastavení v každém rozhraní. Klientský ovladač nemůže změnit konfiguraci. _URB_SELECT_CONFIGURATION

(USBD_SelectConfigUrbAllocateAndBuild)

Funkce URB_SELECT_CONFIGURATION
SET_DESCRIPTOR: Aktualizujte existující zařízení, konfiguraci nebo popisovač řetězců. Viz část 9.4.8 ve specifikaci USB.

Tento požadavek se běžně nepoužívá. Zásobník ovladačů USB však přijímá takový požadavek od klientského ovladače.
  1. Přidělte a vytvořte URB pro žádost.
  2. Zadejte informace o přenosu ve struktuře _URB_CONTROL_DESCRIPTOR_REQUEST .
  3. Odešlete požadavek voláním WdfUsbTargetDeviceFormatRequestForUrb nebo WdfUsbTargetDeviceSendUrbSynchronously .
  1. Deklarujte instalační paket. Viz struktura WINUSB_CONTROL_SETUP_PACKET deklarovaná v usb_hw.h.
  2. Zadejte informace o přenosu podle specifikace USB.
  3. Sestavte požadavek spojením inicializovaného nástavbového paketu s objektem požadavku infrastruktury a přenosové vyrovnávací paměti voláním metody IWDFUsbTargetDevice::FormatRequestForControlTransfer.
  4. Odešlete požadavek voláním metody IWDFIoRequest::Send .
_URB_CONTROL_DESCRIPTOR_REQUEST

FUNKCE_URB_NASTAVIT_DESKRIPTOR_DO_ZAŘÍZENÍ

URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT

URB_FUNCTION_SET_DESCRIPTOR_DO_ROZHRANÍ
SET_FEATURE: Povolte určitá nastavení funkcí v zařízení, jeho konfigurace, rozhraní a koncové body. Viz bod 9.4.9 ve specifikaci USB.
  1. Deklarujte instalační paket. Prohlédněte si strukturu WDF_USB_CONTROL_SETUP_PACKET .
  2. Inicializace instalačního paketu voláním WDF_USB_CONTROL_SETUP_PACKET_INIT_FEATURE.
  3. Zadejte hodnotu příjemce (zařízení, rozhraní, koncový bod) definovanou v WDF_USB_BMREQUEST_RECIPIENT.
  4. Zadejte selektor funkcí (wValue). Viz USB_FEATURE_XXX konstanty v usbspec.h. Viz také tabulka 9-6 ve specifikaci USB.
  5. Nastavte SetFeature na TRUE
  6. Odeslat požadavek voláním WdfUsbTargetDeviceSendControlTransferSynchronously nebo WdfUsbTargetDeviceFormatRequestForControlTransfer.
  1. Deklarujte instalační paket. Viz struktura WINUSB_CONTROL_SETUP_PACKET deklarovaná v usb_hw.h.
  2. Inicializace instalačního paketu voláním pomocného makra WINUSB_CONTROL_SETUP_PACKET_INIT_FEATURE definovaného v usb_hw.h.
  3. Zadejte hodnotu příjemce definovanou v WINUSB_BMREQUEST_RECIPIENT.
  4. Zadejte selektor funkcí (wValue). Viz USB_FEATURE_XXX konstanty v usbspec.h. Viz také tabulka 9-6 ve specifikaci USB.
  5. Nastavte SetFeature na TRUE.
  6. Sestavte požadavek spojením inicializovaného nástavbového paketu s objektem požadavku infrastruktury a přenosové vyrovnávací paměti voláním metody IWDFUsbTargetDevice::FormatRequestForControlTransfer.
  7. Odešlete požadavek voláním metody IWDFIoRequest::Send .
_URB_CONTROL_FEATURE_REQUEST

(UsbBuildFeatureRequest)

Funkce URB nastavit vlastnost zařízení

URB_FUNCTION_SET_FEATURE_TO_INTERFACE (Nastavit funkci na rozhraní)

Funkce URB NASTAVIT FUNKCI NA KONECPOINT

URB_FUNCTION_SET_FEATURE_TO_OTHER
SET_INTERFACE: Změní alternativní nastavení v rozhraní. Viz oddíl 9.4.9 ve specifikaci USB.

Další informace naleznete v tématu Jak vybrat alternativní nastavení v rozhraní USB.
WdfUsbTargetDeviceSelectConfig
  1. Získejte popisovač WDFUSBINTERFACE k objektu cílového rozhraní.
  2. Volejte metodu WdfUsbInterfaceSelectSetting .
  1. Získejte ukazatel IWDFUsbInterface na objekt cílového rozhraní.
  2. Volejte metodu IWDFUsbInterface::SelectSetting .
_URB_SELECT_INTERFACE

(USBD_SelectInterfaceUrbAllocateAndBuild)

URB_FUNCTION_SELECT_INTERFACE
SYNC_FRAME: Nastavte a získejte číslo synchronizačního rámce koncového bodu. Viz bod 9.4.10 ve specifikaci USB. Tento požadavek zpracovává zásobník ovladačů USB; ovladač klienta nemůže tuto operaci provést. Tento požadavek zpracovává zásobník ovladačů USB; ovladač klienta nemůže tuto operaci provést. Tento požadavek zpracovává zásobník ovladačů USB; ovladač klienta nemůže tuto operaci provést.
Pro požadavky specifické pro třídu zařízení a příkazy dodavatele.
  1. Deklarujte instalační paket. Prohlédněte si strukturu WDF_USB_CONTROL_SETUP_PACKET .
  2. Inicializujte nastavovací paket voláním specifických požadavků na WDF_USB_CONTROL_SETUP_PACKET_INIT_CLASS nebo WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR pro požadavky dodavatele.
  3. Zadejte hodnotu příjemce (zařízení, rozhraní, koncový bod) definovanou v WDF_USB_BMREQUEST_RECIPIENT.
  4. Odeslat požadavek voláním WdfUsbTargetDeviceSendControlTransferSynchronously nebo WdfUsbTargetDeviceFormatRequestForControlTransfer.
  1. Deklarujte instalační paket. Viz struktura WINUSB_CONTROL_SETUP_PACKET deklarovaná v usb_hw.h.
  2. Inicializace instalačního paketu voláním pomocného makra , WINUSB_CONTROL_SETUP_PACKET_INIT_CLASS nebo WINUSB_CONTROL_SETUP_PACKET_INIT_VENDOR definovaného v usb_hw.h.
  3. Zadejte směr (viz výčet WINUSB_BMREQUEST_DIRECTION ), příjemce (viz výčet WINUSB_BMREQUEST_RECIPIENT ) a požadavek, jak je popsáno ve třídě nebo specifikaci hardwaru.
  4. Sestavte požadavek spojením inicializovaného nástavbového paketu s objektem požadavku infrastruktury a přenosové vyrovnávací paměti voláním metody IWDFUsbTargetDevice::FormatRequestForControlTransfer.
  5. Odešlete požadavek voláním metody IWDFIoRequest::Send .
  6. Přijímá informace ze zařízení v přenosové vyrovnávací paměti. K přístupu k této vyrovnávací paměti použijte volání metod IWDFMemory.
_URB_CONTROL_VENDOR_OR_CLASS_REQUEST

(UsbBuildVendorRequest)

URB_FUNCTION_VENDOR_DEVICE

URB_FUNCTION_VENDOR_INTERFACE

URB_FUNCTION_VENDOR_ENDPOINT

URB_FUNCTION_VENDOR_OTHER

URB_FUNCTION_CLASS_DEVICE

URB_FUNCTION_CLASS_INTERFACE

URB_Funkce_klasifikace_koncového_bodu

JINÁ FUNKCE TŘÍDY URB

Jak řídit přenos příkazů výrobce - KMDF

Tento postup ukazuje, jak může klientský ovladač odeslat přenos řízení. V tomto příkladu klientský ovladač odešle příkaz dodavatele, který načte verzi firmwaru ze zařízení.

  1. Deklarujte konstantu pro příkaz dodavatele. Prostudujte si specifikaci hardwaru a určete příkaz dodavatele, který chcete použít.

  2. Deklarujte WDF_MEMORY_DESCRIPTOR strukturu a inicializujete ji voláním makra WDF_MEMORY_DESCRIPTOR_INIT_BUFFER . Tato struktura obdrží odpověď ze zařízení poté, co ovladač USB dokončí požadavek.

  3. V závislosti na tom, jestli požadavek odesíláte synchronně nebo asynchronně, zadejte možnosti odeslání:

  4. Deklarujte strukturu WDF_USB_CONTROL_SETUP_PACKET , která bude obsahovat token nastavení a naformátovat strukturu. Uděláte to tak, že zavoláte makro WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR pro naformátování nastavovacího paketu. Ve volání zadejte směr požadavku, příjemce, možnosti odeslané žádosti (inicializované v kroku3) a konstantu pro příkaz dodavatele.

  5. Odešle požadavek voláním WdfUsbTargetDeviceSendControlTransferSynchronously nebo WdfUsbTargetDeviceFormatRequestForControlTransfer.

  6. Zkontrolujte hodnotu NTSTATUS vrácenou rámcem a prozkoumejte přijatou hodnotu.

Tento příklad kódu odešle žádost o přenos ovládacího prvku na zařízení USB za účelem načtení jeho verze firmwaru. Požadavek se odešle synchronně a klientský ovladač určuje relativní hodnotu časového limitu 5 sekund (v jednotkách 100 nanosekund). Ovladač uloží přijatou odpověď do kontextu zařízení definovaného ovladačem.

enum {
    USBFX2_GET_FIRMWARE_VERSION = 0x1,
....

} USBFX2_VENDOR_COMMANDS; 

#define WDF_TIMEOUT_TO_SEC              ((LONGLONG) 1 * 10 * 1000 * 1000)  // defined in wdfcore.h

const __declspec(selectany) LONGLONG
            DEFAULT_CONTROL_TRANSFER_TIMEOUT = 5 * -1 * WDF_TIMEOUT_TO_SEC; 


typedef struct _DEVICE_CONTEXT
{

    ...
       union {
        USHORT      VersionAsUshort;
        struct {
            BYTE Minor;
            BYTE Major;
        } Version;
    } Firmware; // Firmware version.

} DEVICE_CONTEXT, *PDEVICE_CONTEXT;


__drv_requiresIRQL(PASSIVE_LEVEL)
VOID  GetFirmwareVersion(
    __in PDEVICE_CONTEXT DeviceContext
)
{
    NTSTATUS                        status;
    WDF_USB_CONTROL_SETUP_PACKET    controlSetupPacket;
    WDF_REQUEST_SEND_OPTIONS        sendOptions;
    USHORT                          firmwareVersion;
    WDF_MEMORY_DESCRIPTOR           memoryDescriptor;

    PAGED_CODE();

    firmwareVersion = 0;

    WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor, (PVOID) &firmwareVersion, sizeof(firmwareVersion));

    WDF_REQUEST_SEND_OPTIONS_INIT(
                                  &sendOptions,
                                  WDF_REQUEST_SEND_OPTION_TIMEOUT
                                  );

    WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(
                                         &sendOptions,
                                         DEFAULT_CONTROL_TRANSFER_TIMEOUT
                                         );

    WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket,
                                        BmRequestDeviceToHost,       // Direction of the request
                                        BmRequestToDevice,           // Recipient
                                        USBFX2_GET_FIRMWARE_VERSION, // Vendor command
                                        0,                           // Value
                                        0);                          // Index 

    status = WdfUsbTargetDeviceSendControlTransferSynchronously(
                                        DeviceContext->UsbDevice,
                                        WDF_NO_HANDLE,               // Optional WDFREQUEST
                                        &sendOptions,
                                        &controlSetupPacket,
                                        &memoryDescriptor,           // MemoryDescriptor
                                        NULL);                       // BytesTransferred 

    if (!NT_SUCCESS(status)) 
    {
        KdPrint(("Device %d: Failed to get device firmware version 0x%x\n", DeviceContext->DeviceNumber, status));
        TraceEvents(DeviceContext->DebugLog,
                    TRACE_LEVEL_ERROR,
                    DBG_RUN,
                    "Device %d: Failed to get device firmware version 0x%x\n",
                    DeviceContext->DeviceNumber,
                    status);
    }
    else 
    {
        DeviceContext->Firmware.VersionAsUshort = firmwareVersion;
        TraceEvents(DeviceContext->DebugLog,
                    TRACE_LEVEL_INFORMATION,
                    DBG_RUN,
                    "Device %d: Get device firmware version : 0x%x\n",
                    DeviceContext->DeviceNumber,
                    firmwareVersion);
    }

    return;
}

Jak odeslat řídicí přenos pro GET_STATUS - UMDF

Tento postup ukazuje, jak může ovladač klienta odeslat přenos ovládacího prvku pro příkaz GET_STATUS. Příjemcem žádosti je zařízení a žádost získá informace v bitech D1-D0. Další informace naleznete na obrázku 9-4 ve specifikaci USB.

  1. Zahrňte hlavičkový soubor Usb_hw.h dostupný s ukázkovým ovladačem UMDF pro OSR USB Fx2 Learning Kit.

  2. Deklarujte strukturu WINUSB_CONTROL_SETUP_PACKET .

  3. Inicializace instalačního paketu voláním pomocného makra WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS.

  4. Jako příjemce zadejte BmRequestToDevice .

  5. Zadejte hodnotu 0 v hodnotě indexu .

  6. Zavolejte pomocnou metodu SendControlTransferSynchronously k synchronnímu odeslání požadavku.

    Pomocná metoda sestaví požadavek tím, že přidruží inicializovaný konfigurační paket k objektu požadavku rozhraní a vyrovnávací paměť přenosu voláním metody IWDFUsbTargetDevice::FormatRequestForControlTransfer. Pomocná metoda pak odešle požadavek voláním IWDFIoRequest::Send metoda. Po vrácení metody zkontrolujte vrácenou hodnotu.

  7. Pokud chcete zjistit, jestli stav indikuje samoobslužné vzdálené probuzení, použijte tyto hodnoty definované v WINUSB_DEVICE_TRAITS výčtu:

Tento příklad kódu odešle žádost o kontrolní přenos, aby získal stav zařízení. Příklad odešle požadavek synchronně voláním pomocné metody s názvem SendControlTransferSynchronously.

HRESULT
CDevice::GetDeviceStatus ()
{

    HRESULT hr = S_OK;

    USHORT deviceStatus;
    ULONG bytesTransferred;

    TraceEvents(TRACE_LEVEL_INFORMATION,
                DRIVER_ALL_INFO,
                "%!FUNC!: entry");

    // Setup the control packet.

    WINUSB_CONTROL_SETUP_PACKET setupPacket;

    WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS(
                                      &setupPacket,
                                      BmRequestToDevice,
                                      0);

    hr = SendControlTransferSynchronously(
                 &(setupPacket.WinUsb),
                 & deviceStatus,
                 sizeof(USHORT),
                 &bytesReturned
                );

     if (SUCCEEDED(hr))
    {
        if (deviceStatus & USB_GETSTATUS_SELF_POWERED)
        {
             m_Self_Powered = true;
        } 
        if (deviceStatus & USB_GETSTATUS_REMOTE_WAKEUP_ENABLED)
        {
             m_remote_wake-enabled = true;
        }
    }

    return hr;
 }

Následující příklad kódu ukazuje implementaci pomocné metody s názvem SendControlTransferSynchronously. Tato metoda odešle požadavek synchronně.

HRESULT
CDevice::SendControlTransferSynchronously(
    _In_ PWINUSB_SETUP_PACKET SetupPacket,
    _Inout_ PBYTE Buffer,
    _In_ ULONG BufferLength,
    _Out_ PULONG LengthTransferred
    )
{
    HRESULT hr = S_OK;
    IWDFIoRequest *pWdfRequest = NULL;
    IWDFDriver * FxDriver = NULL;
    IWDFMemory * FxMemory = NULL;
    IWDFRequestCompletionParams * FxComplParams = NULL;
    IWDFUsbRequestCompletionParams * FxUsbComplParams = NULL;

    *LengthTransferred = 0;

    hr = m_FxDevice->CreateRequest( NULL, //pCallbackInterface
                                    NULL, //pParentObject
                                    &pWdfRequest);

    if (SUCCEEDED(hr))
    {
        m_FxDevice->GetDriver(&FxDriver);

        hr = FxDriver->CreatePreallocatedWdfMemory( Buffer,
                                                    BufferLength,
                                                    NULL,        //pCallbackInterface
                                                    pWdfRequest, //pParetObject
                                                    &FxMemory );
    }

    if (SUCCEEDED(hr))
    {
        hr = m_pIUsbTargetDevice->FormatRequestForControlTransfer( pWdfRequest,
                                                                   SetupPacket,
                                                                   FxMemory,
                                                                   NULL); //TransferOffset
    }

    if (SUCCEEDED(hr))
    {
        hr = pWdfRequest->Send( m_pIUsbTargetDevice,
                                WDF_REQUEST_SEND_OPTION_SYNCHRONOUS,
                                0); //Timeout
    }

    if (SUCCEEDED(hr))
    {
        pWdfRequest->GetCompletionParams(&FxComplParams);

        hr = FxComplParams->GetCompletionStatus();
    }

    if (SUCCEEDED(hr))
    {
        HRESULT hrQI = FxComplParams->QueryInterface(IID_PPV_ARGS(&FxUsbComplParams));
        WUDF_TEST_DRIVER_ASSERT(SUCCEEDED(hrQI));

        WUDF_TEST_DRIVER_ASSERT( WdfUsbRequestTypeDeviceControlTransfer ==
                            FxUsbComplParams->GetCompletedUsbRequestType() );

        FxUsbComplParams->GetDeviceControlTransferParameters( NULL,
                                                             LengthTransferred,
                                                             NULL,
                                                             NULL );
    }

    SAFE_RELEASE(FxUsbComplParams);
    SAFE_RELEASE(FxComplParams);
    SAFE_RELEASE(FxMemory);

    pWdfRequest->DeleteWdfObject(); 
    SAFE_RELEASE(pWdfRequest);

    SAFE_RELEASE(FxDriver);

    return hr;
}

Pokud používáte Winusb.sys jako ovladač funkce pro vaše zařízení, můžete odesílat řídicí přenosy z aplikace. Chcete-li formátovat instalační paket ve WinUSB, použijte pomocná makra a struktury UMDF popsané v tabulce v tomto článku. Pokud chcete požadavek odeslat, zavolejte funkci WinUsb_ControlTransfer .