USB 제어 전송을 전송하는 방법

이 항목에서는 제어 전송 구조 및 클라이언트 드라이버가 제어 요청을 장치에 전송하는 방법을 설명합니다.

이 항목의 내용:

기본 끝점 정보

모든 USB 장치는 기본 끝점이라는 끝점을 적어도 하나 이상 지원해야 합니다. 기본 끝점을 대상으로 하는 모든 전송을 제어 전송이라고 하는데, 제어 전송의 목적은 호스트가 장치 정보를 획득하거나, 장치를 구성하거나 장치에 고유한 제어 작업을 수행할 수 있도록 하는 것입니다.

먼저 다음과 같은 기본 끝점의 특성에 대해 알아보겠습니다.

  • 기본 끝점의 주소는 0입니다.
  • 기본 끝점은 양방향입니다. 즉 호스트가 데이터를 끝점에 보내고 한 번의 전송 내에 끝점에서 데이터를 받을 수 있습니다.
  • 기본 끝점은 장치 수준에서 사용할 수 있으며 장치의 인터페이스에 정의되어 있지 않습니다.
  • 기본 끝점은 호스트와 장치 간에 연결이 성립되자마자 활성화됩니다. 구성을 선택하기 전에도 활성화됩니다.
  • 기본 끝점의 최대 패킷 크기는 장치의 버스 속도에 따라 다릅니다. 저속 8바이트, 전속력 및 고속 64바이트, 초고속 512바이트.

제어 전송의 레이아웃

제어 전송은 많이 선호하는 전송이므로 호스트에 의해 버스에서 특정 크기의 대역폭이 예약됩니다. 저속 및 전속력 장치의 경우에는 대역폭의 10%, 고속 및 초고속 전송 장치의 경우에는 20%입니다. 이제 제어 전송의 레이아웃을 살펴보겠습니다.

USB 제어 전송

제어 전송은 설치 트랜잭션, 데이터 트랜잭션상태 트랜잭션, 이렇게 세 가지의 트랜잭션으로 나누어집니다. 각 트랜잭션에는 토큰 패킷, 데이터 패킷핸드셰이크 패킷, 이렇게 세 가지 유형의 패킷이 포함되어 있습니다.

일부 필드들은 모든 패킷에 공통입니다. 이러한 필드는 다음과 같습니다.

  • 패킷의 시작을 가리키는 동영상 필드
  • 패킷의 유형, 트랜잭션의 방향을 가리키는 PID(Packet identifier). 핸드셰이크 패킷의 경우에는 트랜잭션의 성공 또는 실패를 가리킵니다.
  • 패킷의 끝을 가리키는 EOP 필드
다른 필드들은 패킷의 유형에 따라 달라집니다.

  • Token packet

    모든 설치 트랜잭션은 토큰 패킷으로 시작합니다. 패킷의 구조는 다음과 같습니다. 호스트는 항상 토큰 패킷을 전송합니다.

    Ff539261.token(ko-kr,VS.85).png

    PID 값은 토큰 패킷의 유형을 가리킵니다. 가능한 값은 다음과 같습니다.

    • SETUP: 제어 전송에서 설치 트랜잭션의 시작을 가리킵니다.
    • IN: 호스트가 장치에서 데이터를 요청하고 있음을 가리킵니다(읽기 경우).
    • OUT: 호스트가 데이터를 장치에 전송하고 있음을 가리킵니다(쓰기 경우).
    • SOF: 프레임의 시작을 가리킵니다. 이 유형의 토큰 패킷에는 11비트 프레임 숫자가 들어 있습니다. 호스트는 SOF 패킷을 전송합니다. 이 패킷이 전송되는 주파수는 버스 속도에 따라 다릅니다. 전속력의 경우 호스트는 1밀리초마다 패킷을 전송하고, 고속 버스에서는 125마이크로초마다 전송합니다.
  • Data packet

    토큰 패킷의 바로 뒤에는 페이로드가 들어 있는 데이터 패킷이 있습니다. 각 데이터 패킷에 포함할 수 있는 바이트 수는 기본 끝점의 최대 패킷 크기에 따라 다릅니다. 데이터 패킷은 전송 방향에 따라 호스트 또는 장치에 의해 전송될 수 있습니다.

    Ff539261.data(ko-kr,VS.85).png

  • Handshake packet

    데이터 패킷 바로 뒤에는 핸드셰이크 패킷이 있습니다. 이 패킷의 PID는 호스트가 이 패킷을 받았는지 아니면 장치가 받았는지를 가리킵니다. 핸드셰이크 패킷은 전송 방향에 따라 호스트 또는 장치에 의해 전송될 수 있습니다.

    Ff539261.handshake(ko-kr,VS.85).png

Beagle, Ellisys, LeCroy USB 프로토콜 분석기와 같은 USB 분석기를 사용하여 트랜잭션 및 패킷의 구조를 볼 수 있습니다. 분석기 장치는 네트워크를 통해 USB 장치로 데이터를 보내거나 받는 방식을 보여 줍니다. 이 예제에서는 LeCroy USB 분석기에서 캡처한 몇 가지 추적을 살펴보겠습니다. 이 예제는 정보 제공용으로만 사용되며, Microsoft의 인증을 받지 않았습니다.

  • Setup transaction

    호스트는 항상 제어 전송을 시작하며, 이러한 시작은 설치 트랜잭션을 전송함으로써 수행됩니다. 이 트랜잭션에는 뒤에 8바이트 데이터 패킷이 있는 설치 토큰이라는 토큰 패킷이 들어 있습니다. 이 스크린샷은 설치 트랜잭션의 예를 보여 줍니다.

    설치 트랜잭션의 자취

    앞의 자취에서는, 호스트가 설치 토큰 패킷 #434를 전송하여 제어 전송을 시작합니다( H↓로 표시). PID는 설치 토큰을 가리키는 SETUP을 지정합니다. PID는 장치 주소와 끝점 주소의 앞에 있습니다. 제어 전송의 경우, 해당 끝점 주소는 항상 0입니다.

    다음으로, 호스트는 데이터 패킷 #435를 전송합니다. PID는 DATA0이고 이 값은 패킷 시퀀싱에 사용됩니다(논의 예정). PID는 이 요청에 대한 기본 정보가 들어 있는 8바이트 앞에 있습니다. 8바이트는 요청의 유형과 장치가 응답을 쓰게 될 버퍼의 크기를 가리킵니다.

    모든 바이트는 역순으로 수신됩니다. 섹션 9.3에서 설명한 필드와 값을 확인할 수 있습니다.

    필드크기설명
    bmRequestType (9.3.1 bmRequestType 참조)1 0x80

    데이터 전송 방향은 장치에서 호스트입니다(D7은 1).

    요청은 표준 요청입니다(D6…D5는 0).

    요청 수신자는 DEVICE입니다(D4가 0).

    bRequest (섹션 9.3.2 및 표 9-4 참조) 1 0x06요청 유형이 GET_DESCRIPTOR입니다.
    wValue (표 9-5 참조) 20x0100요청 값은 설명자 유형이 DEVICE임을 가리킵니다.
    wIndex (섹션 9.3.4 참조) 2 0x0000

    방향은 호스트에서 장치입니다(D7은 1).

    끝점 번호는 0입니다.

    wLength (섹션 9.3.5 참조)20x0012요청은 18바이트를 검색하는 것입니다.

     

    이렇게 해서, 이 제어(읽기) 전송에서 호스트는 요청을 전송하여 장치 설명자를 검색하고, 이 설명자를 보관하기 위한 전송 길이로서 18바이트를 지정한다고 결론을 내릴 수 있습니다. 장치가 이 18바이트를 전송하는 방식은 기본 끝점이 하나의 트랜잭션에서 전송할 수 있는 데이터의 양에 따라 달라집니다. 이러한 정보는 데이터 트랜잭션에서 장치에 의해 반환된 장치 설명자에 포함됩니다.

    장치는 이에 응하여 핸드셰이크 패킷을 전송합니다(D↓으로 표시된 #436). PID 값이 ACK(ACK 패킷)라는 것에 주목하세요. 이것은 장치가 트랜잭션을 승인했음을 가리킵니다.

  • Data transaction

    이제, 장치가 요청에 대한 응답으로 무엇을 반환하는지를 살펴보겠습니다. 실제 데이터는 데이터 트랜잭션에서 전송됩니다.

    다음은 데이터 트랜잭션의 자취입니다.

    예제 데이터 트랜잭션의 자취

    호스트는 ACK 패킷을 받으면 데이터 트랜잭션을 시작합니다. 트랜잭션을 시작하기 위해 호스트는 방향이 IN인 토큰 패킷(#450)(IN 토큰이라고 함)을 전송합니다.

    장치는 이에 응답하여 IN 토큰이 앞에 있는 데이터 패킷(#451)을 전송합니다. 이 데이터 패킷에는 실제 장치 설명자가 들어 있습니다. 첫 번째 바이트는 장치 설명자의 길이인 18바이트(0x12)를 가리킵니다. 이 데이터 패킷의 마지막 바이트는 기본 끝점이 지원하는 최대 패킷 크기입니다. 이 경우, 장치는 기본 끝점을 통해 한 번에 8바이트를 전송할 수 있다는 것을 알 수 있습니다.

    참고  기본 끝점의 최대 패킷 크기는 장치의 속도에 따라 다릅니다. 고속 장치의 기본 끝점은 64바이트이고, 저속 장치는 8바이트입니다.
    호스트는 장치에 ACK 패킷(#452)을 전송하여 데이터 트랜잭션을 승인합니다.

    반환된 데이터의 양을 계산해 보겠습니다. 호스트는 설치 트랜잭션에 있는 데이터 패킷(#435)의 wLength 필드에서 18바이트를 요청했습니다. 데이터 트랜잭션에서는 장치 설명자의 처음 8바이트만 장치에서 받았다는 것을 알 수 있습니다. 그러면, 호스트는 어떻게 나머지 10바이트에 저장된 정보를 수신할까요? 장치는 8바이트 다음 2바이트, 이렇게 두 개의 트랜잭션으로 이 작업을 수행합니다.

    이제 호스트는 기본 끝점의 최대 패킷 크기를 알았으므로, 새 데이터 트랜잭션을 시작하고, 패킷 크기를 기반으로 다음 부분을 요청합니다.

    그다음 데이터 트랜잭션은 아래와 같습니다.

    예제 데이터 트랜잭션의 자취

    호스트는 IN 토큰(#463)을 전송하고 장치에서 그다음 8바이트를 요청하여 앞의 데이터 트랜잭션을 시작합니다. 장치는 장치 설명자의 그다음 8바이트가 들어 있는 데이터 패킷(#464)으로 응답합니다.

    8바이트 수신 시 호스트는 장치에 ACK 패킷(#465)을 전송합니다.

    다음으로, 호스트는 다음과 같이 다른 데이터 트랜잭션에 있는 마지막 2바이트를 요청합니다.

    Ff539261.datra_trans3(ko-kr,VS.85).png

    그러므로, 호스트는 장치에서 호스트로 18바이트를 전송하기 위해 전송되는 바이트 수를 추적하고 세 개의 데이터 트랜잭션(8+8+2)을 시작했음을 알 수 있습니다.

    참고   데이터 트랜잭션 19, 23, 26에 있는 데이터 패킷의 PID에 주목해 주세요. PID는 DATA0과 DATA1 사이를 계속 전환합니다. 이 시퀀스를 데이터 토글이라고 합니다. 여러 데이터 트랜잭션이 있는 경우 데이터 토글은 패킷 시퀀스를 확인하는 데 사용됩니다. 이 메서드에서는 데이터 패킷이 중복되지 않도록 또는 유실되지 않도록 합니다.
    통합된 데이터 패킷을 장치 설명자 구조에 매핑(표 9-8 참조)하면, 이 필드와 값을 볼 수 있습니다.
    필드크기설명
    bLength10x12장치 설명자의 길이로서, 18바이트입니다.
    bDescriptorType10x01설명자 유형은 장치입니다.
    bcdUSB20x0100사양 버전 번호는 1.00입니다.
    bDeviceClass10x00장치 클래스는 0입니다. 구성의 각 인터페이스에는 클래스 정보가 있습니다.
    bDeviceSubClass10x00장치 클래스가 0이므로 하위 클래스는 0입니다.
    bProtocol10x00프로토콜은 0입니다. 이 장치는 클래스별 프로토콜을 사용하지 않습니다.
    bMaxPacketSize010x08끝점의 최대 패킷 크기는 8바이트입니다.
    idVendor20x0562Telex Communications
    idProduct20x0002USB 마이크
    bcdDevice20x0100장치 릴리스 번호를 가리킵니다.
    iManufacturer10x01제조업체의 문자열
    iProduct10x02제품 이름의 문자열
    iSerialNumber10x03일련 번호
    bNumConfigurations10x01구성 개수

     

    이 값을 검사하여 장치에 대한 예비 정보를 얻습니다. 이 장치는 저속 USB 마이크입니다. 기본 끝점의 최대 패킷 크기는 8바이트입니다. 이 장치는 하나의 구성을 지원합니다.
  • Status transaction

    마지막으로, 호스트는 마지막 트랜잭션인 상태 트랜잭션을 시작하여 제어 전송을 완료합니다.

    Ff539261.status_trans(ko-kr,VS.85).png

    호스트는 OUT 토큰 패킷(#481)으로 트랜잭션을 시작합니다. 이 패킷의 목적은 장치가 요청받은 모든 데이터를 전송했는지 확인하는 것입니다. 이 상태 트랜잭션에서 전송된 데이터 패킷은 없습니다. 장치는 ACK 패킷으로 응답합니다. 오류가 발생했다면 PID가 NAK 또는 STALL일 수 있습니다.

지원되는 드라이버 모델

관련 기술

필수 구성 요소

클라이언트 드라이버가 파이프를 열거할 수 있으려면, 먼저 이 요구 사항이 충족되는지 확인하세요.

  • 클라이언트 드라이버가 프레임워크 USB 대상 장치 개체를 만들었어야 합니다.

    Microsoft Visual Studio Professional 2012에 함께 제공된 USB 템플릿을 사용하는 경우 템플릿 코드가 이러한 작업을 수행합니다. 템플릿 코드는 대상 장치 개체에 대한 핸들을 가져와서 디바이스 컨텍스트에 저장합니다.

    KMDF 클라이언트 드라이버:  

    KMDF 클라이언트 드라이버는 WdfUsbTargetDeviceCreateWithParameters 메서드를 호출하여 WDFUSBDEVICE 핸들을 획득해야 합니다. 자세한 내용은 USB 클라이언트 드라이버 코드 구조(KMDF) 이해의 "장치 소스 코드"를 참조하세요.

    UMDF 클라이언트 드라이버:  

    UMDF 클라이언트 드라이버는 프레임워크 대상 장치 개체를 쿼리하여 IWDFUsbTargetDevice 포인터를 획득해야 합니다. 자세한 내용은 USB 클라이언트 드라이버 코드 구조(UMDF) 이해의 "IPnpCallbackHardware 구현 및 USB 특정 작업"을 참조하세요.

  • 제어 전송에 대한 가장 중요한 측면은 설치 토큰의 형식을 적절히 지정하는 것입니다. 요청을 전송하기 전에 이 정보를 수집하세요.

    • 요청의 방향: 호스트에서 장치로 또는 장치에서 호스트로
    • 요청의 수신자: 장치, 인터페이스, 끝점 또는 기타
    • 요청의 범주: 표준, 클래스 또는 공급업체
    • GET_DESCRIPTPOR 요청과 같은 요청의 유형 자세한 내용은 USB 사양의 섹션 9.5를 참조하세요.
    • wValuewIndex 값. 이 값은 요청의 유형에 따라 달라집니다.
    공식 USB 사양에서 이 모든 정보를 얻을 수 있습니다.
  • UMDF 드라이버를 작성하고 있는 경우 헤더 파일 Usb_hw.h를 OSR USB Fx2 학습 키트에 대한 UMDF 샘플 드라이버에서 얻으세요. 이 헤더 파일에는 제어 전송을 위한 설치 패킷의 형식을 지정하기 위한 유용한 매크로 및 구조가 들어 있습니다.

    모든 UMDF 드라이버는 장치에서 데이터를 주고받기 위해 커널 모드 드라이버와 통신해야 합니다. USB UMDF 드라이버의 경우 커널 모드 드라이버는 항상 Microsoft가 제공한 드라이버 WinUSB(Winusb.sys)입니다.

    UMDF 드라이버가 USB 드라이버 스택에 대해 요청할 때마다 Windows I/O 관리자는 WinUSB에 요청을 전송합니다. 요청을 받은 후, WinUSB는 요청을 처리하거나 요청을 USB 드라이버 스택에 전달합니다.

제어 전송 요청을 전송하기 위한 Microsoft 정의 메서드

호스트 상의 USB 클라이언트 드라이버는 대부분의 제어 요청을 시작하여 장치에 대한 정보를 얻거나, 장치를 구성하거나 공급업체 제어 명령을 전송합니다. 이 모든 요청은 다음과 같이 분류할 수 있습니다.

  • 표준 요청—표준 요청은 USB 사양에서 정의됩니다. 이 요청을 전송하는 목적은 장치, 그 구성, 인터페이스 및 끝점에 대한 정보를 얻는 것입니다. 각 요청의 수신자는 요청의 유형에 따라 달라집니다. 수신자는 장치, 인터페이스, 끝점일 수 있습니다.

    참고  모든 제어 전송의 대상은 항상 기본 끝점입니다. 수신자는 호스트가 관심을 가지는 정보(설명자, 상태 등)의 장치 엔터티입니다.

    이 요청은 다음과 같이 더 세부적으로 분류할 수 있습니다.

    • 구성 요청은 호스트가 GET_DESCRIPTOR 요청과 같이 구성할 수 있도록 장치에서 정보를 얻기 위해 전송됩니다. 이 요청은 장치에서 특별한 구성이나 대체 설정을 설정하기 위해 호스트에 의해 전송되는 쓰기 요청일 수도 있습니다.
    • 기능 요청은 장치, 인터페이스 또는 끝점에서 지원하는 특정 부울 장치 설정을 활성화 또는 비활성화하기 위해 클라이언트 드라이버가 전송합니다.
    • USB 장치는 상태 요청을 지원하여 호스트가 장치, 끝점 또는 인터페이스의 USB 정의 상태 비트를 가져오거나 설정할 수 있도록 합니다.
    자세한 내용은, USB 사양 버전 2.0의 섹션 9.4를 참조하세요. 표준 요청 유형은 헤더 파일 Usbspec.h에서 정의됩니다.
  • 클래스 요청—특정 장치 클래스 사양에 의해 정의됩니다.
  • 공급업체 요청—공급업체에 의해 제공되며 장치가 지원하는 요청에 따라 달라집니다.

Microsoft가 제공한 USB 스택은 앞의 자취에서 보듯이 장치와의 모든 프로토콜 통신을 처리합니다. 드라이버는 클라이언트 드라이버가 많은 방법으로 제어 전송을 보낼 수 있도록 해주는 DDI(장치 드라이버 인터페이스)를 노출합니다. 클라이언트 드라이버가 WDF(Windows 드라이버 파운데이션) 드라이버인 경우 직접 루틴을 호출하여 일반적인 유형의 제어 요청을 전송할 수 있습니다. WDF에서는 본질적으로 KMDF와 UMDF 모두에 대한 제어 전송을 지원합니다.

특정 유형의 제어 요청은 WDF를 통해 노출되지 않습니다. 이러한 요청의 경우 클라이언트 드라이버는 WDF-하이브리드 모델을 사용할 수 있습니다. 클라이언트 드라이버는 이 모델을 사용하여 WDM URB 스타일 요청을 빌드하고 그 형식을 지정한 다음 WDF 프레임워크 개체를 사용하여 이 요청을 전송할 수 있습니다. 하이브리드 모델은 커널 모드 드라이버에만 적용됩니다.

UMDF 드라이버의 경우:  

usb_hw.h에 정의된 도우미 매크로 및 구조를 사용하세요. 이 헤더는 OSR USB Fx2 학습 키트용 UMDF 샘플 드라이버와 함께 포함되어 있습니다.

이 표를 사용하여 제어 요청을 USB 드라이버 스택에 전송하는 가장 좋은 방법을 결정하세요. 이 표가 표시되지 않으면 이 항목의 표를 참조하세요.

제어 요청을 받을 대상이 다음과 같을 경우KMDF 드라이버의 경우 KMDF DDI를 사용하여 다음을 수행하세요. UMDF 드라이버의 경우 UMDF 메서드를 사용하여 다음을 수행하세요.WDM 드라이버의 경우, URB 구조(도우미 루틴)를 빌드하세요.
CLEAR_FEATURE: 장치의 특정 기능 설정, 그 구성, 인터페이스 및 끝점을 비활성화하세요. USB 사양의 섹션 9.4.1을 참조하세요.
  1. 설치 패킷을 선언합니다. WDF_USB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. WDF_USB_CONTROL_SETUP_PACKET_INIT_FEATURE를 호출하여 설치 패킷을 초기화합니다.
  3. WDF_USB_BMREQUEST_RECIPIENT에 정의된 수신자 값을 지정합니다.
  4. 기능 선택자(wValue)를 지정합니다. Usbspec.h의 USB_FEATURE_XXX 상수를 참조하세요. USB 사양의 표 9-6도 참조하세요.
  5. SetFeatureFALSE로 설정합니다.
  6. WdfUsbTargetDeviceSendControlTransferSynchronously 또는 WdfUsbTargetDeviceFormatRequestForControlTransfer를 호출하여 요청을 전송합니다.
  1. 설치 패킷을 선언합니다. usb_hw.h에서 선언한 WINUSB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. usb_hw.h에 정의된 도우미 매크로 WINUSB_CONTROL_SETUP_PACKET_INIT_FEATURE를 호출하여 설치 패킷을 시작합니다.
  3. WINUSB_BMREQUEST_RECIPIENT에 정의된 수신자 값을 지정합니다.
  4. 기능 선택자(wValue)를 지정합니다. Usbspec.h의 USB_FEATURE_XXX 상수를 참조하세요. USB 사양의 표 9-6도 참조하세요.
  5. SetFeatureFALSE로 설정합니다.
  6. IWDFUsbTargetDevice::FormatRequestForControlTransfer 메서드를 호출하여 초기화된 설치 패킷을 프레임워크 요청 개체 및 전송 버퍼와 연결하여 요청을 빌드합니다.
  7. IWDFIoRequest::Send 메서드를 호출하여 요청을 전송합니다.

_URB_CONTROL_FEATURE_REQUEST

(UsbBuildFeatureRequest)

URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE

URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE

URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT

URB_FUNCTION_CLEAR_FEATURE_TO_OTHER

GET_CONFIGURATION: 현재 USB 구성을 가져옵니다. USB 사양의 섹션 9.4.2를 참조하세요.

KMDF는 기본적으로 첫 번째 구성을 선택합니다. 장치가 정의한 구성 번호를 검색하려면,

  1. WDF_USB_CONTROL_SETUP_PACKET의 형식을 지정하고 그 bRequest 멤버를 USB_REQUEST_GET_CONFIGURATION으로 설정합니다.
  2. WdfUsbTargetDeviceSendControlTransferSynchronously 또는 WdfUsbTargetDeviceFormatRequestForControlTransfer를 호출하여 요청을 전송합니다.

UMDF는 기본적으로 첫 번째 구성을 선택합니다. 장치가 정의한 구성 번호를 검색하려면,

  1. 설치 패킷을 선언합니다. usb_hw.h에서 선언한 WINUSB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. usb_hw.h에 정의된 도우미 매크로 WINUSB_CONTROL_SETUP_PACKET_INIT를 호출하여 설치 패킷을 시작합니다.
  3. BmRequestToDevice를 방향으로 지정하고, BmRequestToDevice를 수신자로 지정하고, USB_REQUEST_GET_CONFIGURATION을 요청으로 지정합니다.
  4. IWDFUsbTargetDevice::FormatRequestForControlTransfer 메서드를 호출하여 초기화된 설치 패킷을 프레임워크 요청 개체 및 전송 버퍼와 연결하여 요청을 빌드합니다.
  5. IWDFIoRequest::Send 메서드를 호출하여 요청을 전송합니다.
  6. 전송 버퍼에서 구성 번호를 받습니다. IWDFMemory 메서드를 호출하여 해당 버퍼에 액세스합니다.

_URB_CONTROL_GET_CONFIGURATION_REQUEST

URB_FUNCTION_GET_CONFIGURATION

GET_DESCRIPTOR: 장치, 구성, 인터페이스 및 끝점 설명자를 가져옵니다. USB 사양의 섹션 9.4.3을 참조하세요.

자세한 내용은 USB 설명자를 참조하세요.

다음 메서드를 호출합니다.

다음 메서드를 호출합니다.

_URB_CONTROL_DESCRIPTOR_REQUEST

(UsbBuildGetDescriptorRequest)

URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE

URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT

URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE

GET_INTERFACE: 인터페이스에 대한 현재 대체 설정을 가져옵니다. USB 사양의 섹션 9.4.4를 참조하세요.

  1. WdfUsbTargetDeviceGetInterface 메서드를 호출하여 WDFUSBINTERFACE 핸들을 대상 인터페이스 개체로 가져옵니다.
  2. WdfUsbInterfaceGetConfiguredSettingIndex 메서드를 호출합니다.
  1. IWDFUsbInterface 포인터를 대상 인터페이스 개체로 가져옵니다.
  2. IWDFUsbInterface::GetConfiguredSettingIndex 메서드를 호출합니다.

_URB_CONTROL_GET_INTERFACE_REQUEST

URB_FUNCTION_GET_INTERFACE

GET_STATUS: 장치, 끝점 또는 인터페이스에서 상태 비트를 가져옵니다. USB 사양에서 섹션 9.4.5를 참조하세요.
  1. 설치 패킷을 선언합니다. WDF_USB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. WDF_USB_CONTROL_SETUP_PACKET_INIT_GET_STATUS를 호출하여 설치 패킷을 초기화합니다.
  3. WDF_USB_BMREQUEST_RECIPIENT에 정의된 수신자 값을 지정합니다.
  4. 장치, 인터페이스 또는 끝점(wIndex)을 가져오려는 상태를 지정합니다.
  5. WdfUsbTargetDeviceSendControlTransferSynchronously 또는 WdfUsbTargetDeviceFormatRequestForControlTransfer를 호출하여 요청을 전송합니다.
  1. 설치 패킷을 선언합니다. usb_hw.h에서 선언한 WINUSB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. usb_hw.h에 정의된 도우미 매크로 WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS를 호출하여 설치 패킷을 시작합니다.
  3. WINUSB_BMREQUEST_RECIPIENT에 정의된 수신자 값을 지정합니다.
  4. 장치, 인터페이스 또는 끝점(wIndex)을 가져오려는 상태를 지정합니다.
  5. IWDFUsbTargetDevice::FormatRequestForControlTransfer 메서드를 호출하여 초기화된 설치 패킷을 프레임워크 요청 개체 및 전송 버퍼와 연결하여 요청을 빌드합니다.
  6. IWDFIoRequest::Send 메서드를 호출하여 요청을 전송합니다.
  7. 전송 버퍼에서 상태 값을 받습니다. IWDFMemory 메서드를 호출하여 해당 버퍼에 액세스합니다.
  8. 상태가 전원이 자체 공급되는 원격 절전 모드 해제를 나타내는지 판단하려면 WINUSB_DEVICE_TRAITS 열거형에 정의된 3개의 값을 사용하세요.

_URB_CONTROL_GET_STATUS_REQUEST

(UsbBuildGetStatusRequest)

URB_FUNCTION_GET_STATUS_FROM_DEVICE

URB_FUNCTION_GET_STATUS_FROM_INTERFACE

URB_FUNCTION_GET_STATUS_FROM_ENDPOINT

URB_FUNCTION_GET_STATUS_FROM_OTHER.

SET_ADDRESS: USB 사양의 섹션 9.4.6을 참조하세요.이 요청은 USB 드라이버 스택에 의해 처리되며, 클라이언트 드라이버는 이 작업을 수행할 수 없습니다.이 요청은 USB 드라이버 스택에 의해 처리되며, 클라이언트 드라이버는 이 작업을 수행할 수 없습니다.이 요청은 USB 드라이버 스택에 의해 처리되며, 클라이언트 드라이버는 이 작업을 수행할 수 없습니다.
SET_CONFIGURATION: 구성을 설정합니다. USB 사양의 섹션 9.4.7을 참조하세요.

자세한 내용은 USB 장치의 구성을 선택하는 방법을 참조하세요.

기본적으로 KMDF는 각 인터페이스에서 기본 구성과 첫 번째 대체 설정을 선택합니다. 클라이언트 드라이버는 WdfUsbTargetDeviceSelectConfigType 메서드를 호출하고 WdfUsbTargetDeviceSelectConfigTypeUrb를 요청 옵션으로 지정하여 기본 구성을 변경할 수 있습니다. 그러면 여러분은 이 요청에 대한 URB의 형식을 지정하고 이것을 USB 드라이버 스택에 제출해야 합니다.기본적으로 UMDF는 각 인터페이스에서 기본 구성과 첫 번째 대체 설정을 선택합니다. 클라이언트 드라이버는 구성을 변경할 수 없습니다.

_URB_SELECT_CONFIGURATION

(USBD_SelectConfigUrbAllocateAndBuild)

URB_FUNCTION_SELECT_CONFIGURATION

SET_DESCRIPTOR: 기존 장치, 구성 또는 문자열 설명자를 업데이트합니다. USB 사양의 섹션 9.4.8을 참조하세요.

이 요청은 일반적으로 사용되지 않습니다. USB 드라이버 스택은 클라이언트 드라이버로부터 이와 같은 요청을 수락합니다.

  1. 요청에 대한 URB를 할당 및 빌드합니다.
  2. _URB_CONTROL_DESCRIPTOR_REQUEST 구조에서 전송 정보를 지정합니다.
  3. WdfUsbTargetDeviceFormatRequestForUrb 또는 WdfUsbTargetDeviceSendUrbSynchronously를 호출하여 요청을 전송합니다.
  1. 설치 패킷을 선언합니다. usb_hw.h에서 선언한 WINUSB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. USB 사양에 따라 전송 정보를 지정합니다.
  3. IWDFUsbTargetDevice::FormatRequestForControlTransfer 메서드를 호출하여 초기화된 설치 패킷을 프레임워크 요청 개체 및 전송 버퍼와 연결하여 요청을 빌드합니다.
  4. IWDFIoRequest::Send 메서드를 호출하여 요청을 전송합니다.

_URB_CONTROL_DESCRIPTOR_REQUEST

URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE

URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT

URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE

SET_FEATURE: 장치의 특정 기능 설정, 그 구성, 인터페이스 및 끝점을 활성화하세요. USB 사양의 섹션 9.4.9를 참조하세요.
  1. 설치 패킷을 선언합니다. WDF_USB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. WDF_USB_CONTROL_SETUP_PACKET_INIT_FEATURE를 호출하여 설치 패킷을 초기화합니다.
  3. WDF_USB_BMREQUEST_RECIPIENT에 정의된 수신자 값(장치, 인터페이스, 끝점)을 지정합니다.
  4. 기능 선택자(wValue)를 지정합니다. Usbspec.h의 USB_FEATURE_XXX 상수를 참조하세요. USB 사양의 표 9-6도 참조하세요.
  5. SetFeatureTRUE로 설정합니다.
  6. WdfUsbTargetDeviceSendControlTransferSynchronously 또는 WdfUsbTargetDeviceFormatRequestForControlTransfer를 호출하여 요청을 전송합니다.
  1. 설치 패킷을 선언합니다. usb_hw.h에서 선언한 WINUSB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. usb_hw.h에 정의된 도우미 매크로 WINUSB_CONTROL_SETUP_PACKET_INIT_FEATURE를 호출하여 설치 패킷을 시작합니다.
  3. WINUSB_BMREQUEST_RECIPIENT에 정의된 수신자 값을 지정합니다.
  4. 기능 선택자(wValue)를 지정합니다. Usbspec.h의 USB_FEATURE_XXX 상수를 참조하세요. USB 사양의 표 9-6도 참조하세요.
  5. SetFeatureTRUE로 설정합니다.
  6. IWDFUsbTargetDevice::FormatRequestForControlTransfer 메서드를 호출하여 초기화된 설치 패킷을 프레임워크 요청 개체 및 전송 버퍼와 연결하여 요청을 빌드합니다.
  7. IWDFIoRequest::Send 메서드를 호출하여 요청을 전송합니다.

_URB_CONTROL_FEATURE_REQUEST

(UsbBuildFeatureRequest)

URB_FUNCTION_SET_FEATURE_TO_DEVICE

URB_FUNCTION_SET_FEATURE_TO_INTERFACE

URB_FUNCTION_SET_FEATURE_TO_ENDPOINT

URB_FUNCTION_SET_FEATURE_TO_OTHER

SET_INTERFACE: 인터페이스에서 대체 설정을 변경합니다. USB 사양의 섹션 9.4.9를 참조하세요.

자세한 내용은 USB 인터페이스에서 대체 설정을 선택하는 방법을 참조하세요.

WdfUsbTargetDeviceSelectConfig

  1. WDFUSBINTERFACE 핸들을 대상 인터페이스 개체로 가져옵니다.
  2. WdfUsbInterfaceSelectSetting 메서드를 호출합니다.
  1. IWDFUsbInterface 포인터를 대상 인터페이스 개체로 가져옵니다.
  2. IWDFUsbInterface::SelectSetting 메서드를 호출합니다.

_URB_SELECT_INTERFACE

(USBD_SelectInterfaceUrbAllocateAndBuild)

URB_FUNCTION_SELECT_INTERFACE

SYNC_FRAME: 끝점의 동기화 프레임 번호를 설정 및 가져옵니다. USB 사양의 섹션 9.4.10을 참조하세요.이 요청은 USB 드라이버 스택에 의해 처리되며, 클라이언트 드라이버는 이 작업을 수행할 수 없습니다.이 요청은 USB 드라이버 스택에 의해 처리되며, 클라이언트 드라이버는 이 작업을 수행할 수 없습니다.이 요청은 USB 드라이버 스택에 의해 처리되며, 클라이언트 드라이버는 이 작업을 수행할 수 없습니다.
장치 클래스별 요청 및 공급업체 명령의 경우
  1. 설치 패킷을 선언합니다. WDF_USB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. WDF_USB_CONTROL_SETUP_PACKET_INIT_CLASS별 요청이나 공급업체 명령에 대한 WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR를 호출하여 설치 패킷을 초기화합니다.
  3. WDF_USB_BMREQUEST_RECIPIENT에 정의된 수신자 값(장치, 인터페이스, 끝점)을 지정합니다.
  4. WdfUsbTargetDeviceSendControlTransferSynchronously 또는 WdfUsbTargetDeviceFormatRequestForControlTransfer를 호출하여 요청을 전송합니다.
  1. 설치 패킷을 선언합니다. usb_hw.h에서 선언한 WINUSB_CONTROL_SETUP_PACKET 구조를 참조하세요.
  2. usb_hw.h에 정의된 도우미 매크로 WINUSB_CONTROL_SETUP_PACKET_INIT_CLASS 또는 WINUSB_CONTROL_SETUP_PACKET_INIT_VENDOR를 호출하여 설치 패킷을 시작합니다.
  3. 클래스 또는 하드웨어 사양에 설명된 대로 방향(WINUSB_BMREQUEST_DIRECTION 열거형 참조), 수신자(WINUSB_BMREQUEST_RECIPIENT 열거형 참조) 및 요청을 지정합니다.
  4. IWDFUsbTargetDevice::FormatRequestForControlTransfer 메서드를 호출하여 초기화된 설치 패킷을 프레임워크 요청 개체 및 전송 버퍼와 연결하여 요청을 빌드합니다.
  5. IWDFIoRequest::Send 메서드를 호출하여 요청을 전송합니다.
  6. 전송 버퍼에 있는 장치로부터 정보를 받습니다. 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_FUNCTION_CLASS_ENDPOINT

URB_FUNCTION_CLASS_OTHER

 

공급업체 명령에 대한 제어 전송을 보내는 방법 - KMDF

아래 절차는 클라이언트 드라이버가 제어 전송을 보낼 수 있는 방법을 보여 줍니다. 이 예제에서 클라이언트 드라이버는 장치에서 펌웨어 버전을 검색하는 공급업체 명령을 전송합니다.

  1. 공급업체 명령용 상수를 선언합니다. 하드웨어 사양을 살펴보고 사용할 공급업체 명령을 결정하세요.
  2. WDF_MEMORY_DESCRIPTOR_INIT_BUFFER 매크로를 호출하여 WDF_MEMORY_DESCRIPTOR 구조를 선언하고 초기화합니다. 이 구조는 USB 드라이버가 요청을 완료한 후 장치로부터 응답을 받게 됩니다.
  3. 요청을 동기적으로 전송하는지 비동기적으로 전송하는지에 따라 전송 옵션을 지정합니다.
    • WdfUsbTargetDeviceSendControlTransferSynchronously를 호출하여 요청을 동기적으로 전송하는 경우 시간 제한 값을 지정합니다. 시간 제한이 없으면 스레드를 무한대로 차단할 수 있으므로 이 값은 중요합니다.

      이 경우, WDF_REQUEST_SEND_OPTIONS_INIT 매크로를 호출하여 WDF_REQUEST_SEND_OPTIONS 구조를 선언하고 초기화합니다. 옵션을 WDF_REQUEST_SEND_OPTION_TIMEOUT으로 설정합니다.

      다음으로 WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT 매크로를 호출하여 시간 제한 값을 설정합니다.

    • 요청을 비동기적으로 전송하는 경우 완료 루틴을 구현합니다. 완료 루틴에서 모든 할당된 리소스를 해제합니다.
  4. WDF_USB_CONTROL_SETUP_PACKET 구조를 선언하여 설치 토큰을 포함하고 구조의 형식을 지정합니다. 이렇게 하려면 WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR 매크로를 호출하여 설치 패킷의 형식을 지정합니다. 호출에서 요청 방향, 수신자, 보낸 요청 옵션(3단계에서 초기화됨) 및 공급업체 명령에 대한 상수를 지정합니다.
  5. WdfUsbTargetDeviceSendControlTransferSynchronously 또는 WdfUsbTargetDeviceFormatRequestForControlTransfer를 호출하여 요청을 전송합니다.
  6. 프레임워크에서 반환된 NTSTATUS 값을 확인하고 수신된 값을 검사하세요.

이 코드 예제는 제어 전송 요청을 USB 장치에 전송하여 펌웨어 버전을 검색합니다. 요청은 동기적으로 전송되며 클라이언트 드라이버는 상대적인 시간 제한 값 5초(100나노초 단위)를 지정합니다. 드라이버는 드라이버가 정의한 디바이스 컨텍스트에 수신된 응답을 저장합니다.



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;  
}  


GET_STATUS에 대한 제어 전송을 보내는 방법 - KMDF

이 절차에서는 클라이언트 드라이버가 어떻게 GET_STATUS 명령에 대한 제어 전송을 전송할 수 있는지를 보여 줍니다. 요청 수신자는 장치이며, 요청은 비트 D1-D0에서 정보를 얻습니다. 자세한 내용은 USB 사양의 그림 9-4를 참조하세요.

  1. OSR USB Fx2 학습 키트용 UMDF 샘플 드라이버와 함께 사용할 수 있는 헤더 파일 Usb_hw.h를 포함합니다.
  2. WINUSB_CONTROL_SETUP_PACKET 구조를 선언합니다.
  3. 도우미 매크로 WINUSB_CONTROL_SETUP_PACKET_INIT_GET_STATUS를 호출하여 설치 패킷을 초기화합니다.
  4. BmRequestToDevice를 수신자로 지정합니다.
  5. Index 값에 0을 지정합니다.
  6. 도우미 메서드 SendControlTransferSynchronously를 호출하여 요청을 비동기적으로 전송합니다.

    이 도우미 메서드는 IWDFUsbTargetDevice::FormatRequestForControlTransfer 메서드를 호출하여 초기화된 설치 패킷을 프레임워크 요청 개체와 전송 버퍼에 연결함으로써 요청을 빌드합니다. 그런 다음 도우미 메서드는 IWDFIoRequest::Send 메서드를 호출하여 요청을 전송합니다. 메서드가 반환되면 반환된 값을 검사합니다.

  7. 상태가 전원이 자체 공급되는 원격 절전 모드 해제를 나타내는지 판단하려면 WINUSB_DEVICE_TRAITS 열거형에 정의된 값을 사용하세요.

이 코드 예제는 제어 전송 요청을 전송하여 장치의 상태를 알아냅니다. 이 예제에서는 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;  

 }


다음 코드 예제에서는 SendControlTransferSynchronously라는 도우미 메서드의 구현을 보여 줍니다. 이 메서드는 요청을 동기적으로 전송합니다.



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;  
}  



설명

Winusb.sys를 장치에 대한 기능 드라이버로 사용하는 중인 경우 응용 프로그램에서 제어 전송을 전송할 수 있습니다. WinUSB에서 설치 패킷의 형식을 지정하려면, 이 항목의 표에서 설명한 UMDF 도우미 매크로와 구조를 사용합니다. 요청을 전송하려면, WinUsb_ControlTransfer 함수를 호출합니다.

 

 

표시:
© 2015 Microsoft