USB 인터페이스에서 대체 설정을 선택하는 방법
이 항목에서는 USB 인터페이스에서 대체 설정을 활성화하기 위한 선택 인터페이스 요청을 실행하는 단계를 설명합니다. 클라이언트 드라이버는 USB 구성을 선택한 후 이 요청을 실행해야 합니다. 기본적으로 구성을 선택하면 해당 구성의 각 인터페이스에서 첫 번째 대체 설정도 활성화됩니다.
각 USB 구성은 하나 이상의 여러 USB 인터페이스를 지원해야 합니다. 각 인터페이스는 디바이스와 데이터를 전송하는 데 사용되는 하나 이상의 엔드포인트를 노출합니다. USB 인터페이스에는 인터페이스를 식별하는 데 사용되는 디바이스 정의 인터페이스 인덱 스가 있어야 합니다. 인터페이스에는 인터페이스의 엔드포인트를 그룹화하는 하나 이상의 대체 설정 도 있어야 합니다. 디바이스 구성의 일부로 클라이언트 드라이버는 인터페이스에서 대체 설정 중 하나를 선택해야 합니다. 엔드포인트는 대체 설정 간에 공유할 수 있으므로 지정된 시간에 하나의 설정만 활성화할 수 있습니다. 대체 설정이 활성화되면 해당 엔드포인트를 데이터 전송에 사용할 수 있게 됩니다.
여러 인터페이스 디바이스의 경우 지정된 시간에 두 개의 인터페이스를 활성화할 수 있습니다. 클라이언트 드라이버는 각 인터페이스에서 대체 설정을 활성화해야 합니다. 엔드포인트는 인터페이스 간에 공유되지 않으므로 각 인터페이스에서 각 동시 데이터 전송을 수행할 수 있습니다.
대체 설정은 디바이스 정의이며 설정 인덱스라는 숫자로 식별됩니다. 인덱스 0의 대체 설정을 이 설명서 집합의 기본 대체 설정 이라고 합니다. 대체 설정은 USB_INTERFACE_DESCRIPTOR 구조에 설명되어 있습니다. 구조체에는 설정이 연결된 인터페이스 인덱스와 설정에서 정의한 엔드포인트 수가 포함됩니다. 또한 인터페이스의 기능이 준수하는 클래스 사양에 대한 정보도 포함되어 있습니다. 엔드포인트가 그룹화되는 방식은 디바이스의 기능에 따라 달라집니다.
예를 들어 인터페이스는 세 가지 대체 설정(인덱스 0, 1, 2)을 통해 두 개의 등시 및 두 개의 대량 엔드포인트를 노출합니다. 대체 설정 0은 엔드포인트를 정의하지 않습니다. 대체 설정 1은 대량 엔드포인트를 정의합니다. 대체 설정 2는 등시 엔드포인트를 정의합니다. 대체 설정 0에는 엔드포인트가 없으므로 클라이언트 드라이버는 대역폭을 절약하기 위해 이 설정을 선택하여 데이터 전송을 사용하지 않도록 설정할 수 있습니다. 다른 설정 중 하나가 활성 상태이면 디바이스에서 데이터 전송을 수행할 준비가 된 것입니다. 대체 설정 1은 대량 데이터를 전송하는 데 사용할 수 있습니다. 디바이스가 스트리밍 모드인 경우 대체 설정 2를 선택할 수 있습니다. 따라서 대체 설정을 사용하면 클라이언트 드라이버가 필요에 따라 디바이스 구성을 유연하게 변경할 수 있습니다. 이 예제에서 클라이언트 드라이버는 대체 설정을 선택하여 디바이스 기능을 대량 전송에서 스트리밍으로 전환할 수 있습니다.
대역폭 요구 사항을 설정하는 데 대체 설정을 사용할 수도 있습니다. 예제는 USB 디바이스 레이아웃을 참조하세요.
WDF(Windows Driver Foundation)는 클라이언트 드라이버가 다른 대체 설정을 선택하기 위해 호출할 수 있는 커널 모드 드라이버 프레임워크 및 사용자 모드 드라이버 프레임워크 의 메서드를 제공합니다. KMDF 클라이언트 드라이버는 설정 인덱스, 설정의 인터페이스 설명자를 지정하거나 요청이 포함된 URB를 제출하여 설정을 선택할 수 있습니다. UMDF 클라이언트 드라이버는 설정 인덱스만 지정하여 대체 설정을 선택할 수 있습니다.
select-configuration 요청이 성공적으로 완료되면 이전에 활성 상태였던 대체 설정이 비활성화됩니다.
알아야 하는 작업
이 문서에서는 다음 프레임워크를 활용합니다.
시작하기 전에
클라이언트 드라이버가 대체 설정을 선택하기 전에 다음 요구 사항이 충족되는지 확인합니다.
클라이언트 드라이버가 프레임워크 USB 대상 디바이스 개체를 만들었어야 합니다.
KMDF 클라이언트 드라이버는 WdfUsbTargetDeviceCreateWithParameters 메서드를 호출하여 WDFUSBDEVICE 핸들을 가져와야 합니다. 자세한 내용은 KMDF(USB 클라이언트 드라이버 코드 구조) 이해의 "디바이스 소스 코드"를 참조하세요.
UMDF 클라이언트 드라이버는 프레임워크 대상 디바이스 개체를 쿼리하여 IWDFUsbTargetDevice 포인터를 가져와야 합니다. 자세한 내용은 UMDF(USB 클라이언트 드라이버 코드 구조) 이해에서 "IPnpCallbackHardware 구현 및 USB 관련 작업"을 참조하세요.
Microsoft Visual Studio Professional 2012와 함께 제공되는 USB 템플릿을 사용하는 경우 템플릿 코드는 이러한 작업을 수행합니다. 템플릿 코드는 대상 디바이스 개체에 대한 핸들을 가져오고 디바이스 컨텍스트에 저장합니다.
디바이스에 활성 구성이 있어야 합니다.
KMDF 클라이언트 드라이버는 WdfUsbTargetDeviceSelectConfig 메서드를 호출해야 합니다.
UMDF 클라이언트 드라이버의 경우 프레임워크는 해당 구성의 각 인터페이스에 대한 첫 번째 구성 및 기본 대체 설정을 선택합니다.
USB 템플릿을 사용하는 경우 코드는 각 인터페이스에서 첫 번째 구성 및 기본 대체 설정을 선택합니다.
KMDF 클라이언트 드라이버에서 대체 설정 선택
대체 설정이 있는 인터페이스에 대한 WDFUSBINTERFACE 핸들을 가져옵니다.
핸들을 얻으려면 먼저 WdfUsbTargetDeviceGetNumInterfaces 를 호출하고 루프에서 인터페이스를 열거하여 선택한 구성의 인터페이스 수를 가져옵니다. 각 반복에서 WdfUsbTargetDeviceGetInterface 메서드를 호출하고 인덱스를 0부터 증분합니다.
참고 디바이스 열거 중에 USB 드라이버 스택은 대체 설정에 숫자를 할당합니다. 인터페이스 번호는 0부터 시작하며 순차적입니다. 이러한 숫자는 디바이스 정의 설정 인덱스와 다를 수 있습니다. 디바이스 정의 설정 인덱스를 가져오려면 WdfUsbInterfaceGetInterfaceNumber 메서드를 호출합니다.
WdfUsbInterfaceSelectSetting 메서드를 호출하여 select-interface 요청을 시작합니다. 호출의 Params 매개 변수에서 다음 옵션 중 하나를 선택합니다.
USB 드라이버 스택에서 할당한 대체 설정 번호를 지정합니다. 일반적으로 1단계에서 설정을 열거하는 데 사용한 것과 동일한 인덱스 를 전달합니다.
대체 설정을 설명하는 인터페이스 설명자 포인터를 지정합니다. 그런 다음 드라이버는 WdfUsbInterfaceGetDescriptor 메서드를 호출하여 인터페이스에서 대체 설정을 열거하는 동안 인터페이스 설명자를 가져올 수 있습니다. 열거가 완료되면 드라이버는 USB_INTERFACE_DESCRIPTOR 구조의 열거된 모든 대체 설정에 대한 정보를 가져옵니다.
select-interface 요청에 필요한 모든 정보를 포함하는 URB에 대한 포인터를 지정합니다.
- USBD_INTERFACE_LIST_ENTRY 구조의 배열을 할당합니다. 이 배열의 요소 수는 선택한 구성의 인터페이스 수에 따라 달라집니다. 이 배열을 초기화하는 방법에 대한 자세한 내용은 USB 디바이스에 대한 구성을 선택하는 방법을 참조하세요.
- USBD_SelectInterfaceUrbAllocateAndBuild 루틴을 호출하여 선택 인터페이스 요청에 대한 URB를 할당합니다. 이 호출에서는 구성을 선택한 후 가져온 인터페이스 목록 배열 및 구성 핸들을 지정합니다. WdfUsbTargetDeviceWdmGetConfigurationHandle 메서드를 호출하여 해당 핸들을 가져올 수 있습니다.
- WdfUsbInterfaceSelectSetting을 호출하고 URB를 지정합니다.
**WDM 드라이버:**URB를 제출하려면 URB를 IRP와 연결하고 IRP를 USB 드라이버 스택에 제출합니다. 자세한 내용은 URB를 제출하는 방법을 참조하세요.
목록의 옵션은 클라이언트 드라이버에 선택 조건을 지정할 수 있는 유연성을 제공합니다. 대체 설정의 엔드포인트 기능을 이미 알고 있는 경우 목록에서 첫 번째 옵션(대체 설정 번호 포함)을 선택합니다. 그렇지 않으면 인터페이스 설명자를 지정하는 두 번째 옵션을 선택합니다. 모든 대체 설정에 대한 USB_INTERFACE_DESCRIPTOR 구조를 검사합니다. 각 설정에 대해 엔드포인트 및 해당 특성(예: 엔드포인트 유형, 최대 패킷 크기 등)을 열거합니다. 데이터 전송에 필요한 엔드포인트 집합을 찾으면 해당 인터페이스 설명자에 대한 포인터를 지정 하여 WdfUsbInterfaceSelectSetting 을 호출합니다. 일반적으로 URL을 제출하여 USB 드라이버 스택에 요청을 보낼 수 있는 WDM 기반 클라이언트 드라이버가 아니면 세 번째 옵션이 필요하지 않습니다.
클라이언트 드라이버에서 제공하는 정보에 따라 USB 드라이버 스택은 표준 제어 요청(SET INTERFACE)을 빌드하고 디바이스로 보냅니다. 요청이 성공적으로 완료되면 USB 드라이버 스택은 대체 설정의 엔드포인트에 대한 파이프 핸들을 가져옵니다.
대체 설정을 선택한 후 클라이언트 드라이버는 항상 새 설정에서 엔드포인트에 대한 파이프 핸들을 가져와야 합니다. 이렇게 하지 않으면 드라이버가 부실 파이프 핸들을 사용하여 데이터 전송 요청을 보낼 수 있습니다. 파이프 핸들을 검색하는 방법에 대한 자세한 내용은 USB 파이프를 열거하는 방법을 참조하세요.
NTSTATUS FX3SelectInterfaceSetting(
_In_ WDFDEVICE Device,
_In_ UCHAR SettingIndex)
{
NTSTATUS status;
PDEVICE_CONTEXT pDeviceContext;
WDF_OBJECT_ATTRIBUTES pipeAttributes;
WDF_USB_INTERFACE_SELECT_SETTING_PARAMS settingParams;
PAGED_CODE();
pDeviceContext = GetDeviceContext(Device);
if (pDeviceContext->UsbInterface == NULL)
{
status = USBD_STATUS_BAD_NUMBER_OF_INTERFACES;
goto Exit;
}
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pipeAttributes, PIPE_CONTEXT);
pipeAttributes.EvtCleanupCallback = FX3EvtPipeContextCleanup;
WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING (&settingParams, SettingIndex);
status = WdfUsbInterfaceSelectSetting (
pDeviceContext->UsbInterface,
&pipeAttributes,
&settingParams);
if (status != STATUS_SUCCESS)
{
goto Exit;
}
if (WdfUsbInterfaceGetNumConfiguredPipes (pDeviceContext->UsbInterface) > 0)
{
status = FX3EnumeratePipes (Device);
if (status != STATUS_SUCCESS)
{
goto Exit;
}
}
Exit:
return status;
}
UMDF 클라이언트 드라이버에서 대체 설정 선택
IWDFUsbTargetDevice::GetNumInterfaces 메서드를 호출하여 활성 구성에서 지원하는 USB 인터페이스 수를 가져옵니다.
구성의 각 인터페이스에 대한 IWDFUsbInterface 포인터를 가져옵니다.
함수가 NULL을 반환할 때까지 루프에서 IWDFUsbTargetDevice::RetrieveUsbInterface 메서드를 호출하여 모든 인터페이스를 열거합니다. 반복할 때마다 멤버 인덱스(0부터 시작)를 증분합니다. 루프는 열거된 모든 인터페이스에 대한 IWDFUsbInterface 포인터를 검색합니다.
각 인터페이스에 대해 IWDFUsbInterface::GetWinUsbHandle을 호출하여 WinUSB 핸들을 가져옵니다. 이 핸들은 다음 단계에서 필요합니다.
WinUsb_GetAssociatedInterface 호출하여 인터페이스에 대한 핸들을 가져옵니다. AssociatedInterfaceIndex 매개 변수에서 2단계에서 인덱스를 지정합니다.
인터페이스의 대체 설정 수를 결정합니다.
루프에서 WinUsb_QueryInterfaceSettings 함수를 호출하고 각 반복에서 인덱스(0부터 시작)를 증분합니다. 모든 설정이 열거되면 함수는 ERROR_NO_MORE_ITEMS 반환합니다. 또한 함수는 각 설정에 대한 인터페이스 설명자를 반환합니다.
각 인터페이스 설명자의 bNumEndpoints 멤버에서 받은 값을 사용하여 해당 엔드포인트를 열거합니다. 엔드포인트 설명자를 검사하고 요구 사항을 충족하는 설정을 결정합니다.
WinUsb_SetCurrentAlternateSetting 함수를 호출하여 선택 인터페이스 요청을 시작합니다. 호출에서 4단계에서 인덱스와 연결된 대체 설정 번호를 지정합니다.
WinUsb_Free 함수를 호출하여 4단계에서 얻은 인터페이스 핸들을 해제합니다.
WinUsb_Free 함수를 호출하여 3단계에서 얻은 WinUSB 핸들을 해제합니다.
IWDFUsbInterface 메서드 사용을 완료한 경우 2단계에서 검색된 모든 인터페이스 포인터를 해제합니다.
설명
KMDF 클라이언트 드라이버의 경우 WdfUsbInterfaceSelectSetting 호출에서 드라이버는 드라이버 정의 파이프 컨텍스트에 대한 포인터를 제공할 수 있습니다. 클라이언트 드라이버는 파이프 컨텍스트에서 파이프에 대한 정보를 저장할 수 있습니다. 파이프 정보에 대한 자세한 내용은 USB 파이프를 열거하는 방법을 참조하세요.