Como selecionar uma configuração alternativa em uma interface USB
Este tópico descreve as etapas para emitir uma solicitação select-interface para ativar uma configuração alternativa em uma interface USB. O driver cliente deve emitir essa solicitação depois de selecionar uma configuração USB. A seleção de uma configuração, por padrão, também ativa a primeira configuração alternativa em cada interface nessa configuração.
Cada configuração USB deve dar suporte a uma ou mais interfaces USB múltiplas. Cada interface expõe um ou mais pontos de extremidade que são usados para transferir dados de e para o dispositivo. As interfaces USB devem ter um índice de interface definido pelo dispositivo que seja usado para identificar a interface. A interface também deve ter uma ou mais configurações alternativas que agrupem os pontos de extremidade da interface. Como parte da configuração do dispositivo, o driver do cliente deve selecionar uma das configurações alternativas na interface. Como os pontos de extremidade podem ser compartilhados entre configurações alternativas, apenas uma configuração pode estar ativa em um determinado momento. Depois que a configuração alternativa estiver ativa, seus pontos de extremidade ficarão disponíveis para transferências de dados.
Para um dispositivo de interface múltipla, duas interfaces podem estar ativas em um determinado momento. O driver cliente deve ativar uma configuração alternativa em cada interface. Os pontos de extremidade não são compartilhados entre interfaces e, portanto, cada transferência de dados simultânea pode ser executada em cada interface.
As configurações alternativas são definidas pelo dispositivo e identificadas com um número chamado índice de configuração. A configuração alternativa no índice 0 é chamada de configuração alternativa padrão neste conjunto de documentação. Uma configuração alternativa é descrita em uma estrutura USB_INTERFACE_DESCRIPTOR . A estrutura contém o índice de interface ao qual a configuração está associada e o número de pontos de extremidade definidos pela configuração. Ele também contém informações sobre a especificação de classe à qual a funcionalidade da interface está em conformidade. A maneira como os pontos de extremidade são agrupados depende da funcionalidade do dispositivo.
Por exemplo, uma interface expõe dois pontos de extremidade isócronos e dois em massa por meio de três configurações alternativas (índice 0, 1, 2). A Configuração Alternativa 0 não define nenhum ponto de extremidade; A Configuração Alternativa 1 define os pontos de extremidade em massa; A Configuração Alternativa 2 define os pontos de extremidade isócronos. Como a Configuração Alternativa 0 não tem nenhum ponto de extremidade, o driver cliente pode selecionar essa configuração para desabilitar a transferência de dados para conservar a largura de banda. Quando qualquer uma das outras configurações estiver ativa, o dispositivo estará pronto para transferências de dados. A Configuração Alternativa 1 pode ser usada para transferir dados em massa. A Configuração Alternativa 2 pode ser selecionada quando o dispositivo está no modo de streaming. Portanto, as configurações alternativas dão ao driver do cliente a flexibilidade de alterar a configuração do dispositivo como e quando necessário. Neste exemplo, o driver do cliente pode alternar a funcionalidade do dispositivo de uma transferência em massa para streaming, apenas selecionando uma configuração alternativa.
Configurações alternativas também podem ser usadas para definir requisitos de largura de banda. Para obter um exemplo, consulte o Layout do dispositivo USB.
O WDF (Windows Driver Foundation) fornece métodos na Estrutura do Driver do Modo Kernel e na Estrutura do Driver de Modo de Usuário que o driver cliente pode chamar para selecionar uma configuração alternativa diferente. O driver de cliente KMDF pode selecionar uma configuração especificando o índice de configuração, o descritor de interface da configuração ou enviando um URB que contém a solicitação. O driver de cliente UMDF só pode selecionar uma configuração alternativa especificando seu índice de configuração.
Depois que uma solicitação select-configuration for concluída com êxito, a configuração alternativa anteriormente ativa será desativada.
O que você precisa saber
Este artigo utiliza as seguintes estruturas:
Antes de começar
Antes que o driver do cliente possa selecionar uma configuração alternativa, verifique se esses requisitos foram atendidos:
O driver cliente deve ter criado o objeto de dispositivo de destino USB da estrutura.
Um driver cliente KMDF deve obter um identificador WDFUSBDEVICE chamando o método WdfUsbTargetDeviceCreateWithParameters . Para obter mais informações, confira "Código-fonte do dispositivo" em Noções básicas sobre a estrutura de código do driver de cliente USB (KMDF).
Um driver cliente UMDF deve obter um ponteiro IWDFUsbTargetDevice consultando o objeto de dispositivo de destino da estrutura. Para obter mais informações, confira "Implementação de IPnpCallbackHardware e tarefas específicas de USB" em Noções básicas sobre a estrutura de código do driver de cliente USB (UMDF)
Se você estiver usando os modelos USB fornecidos com Microsoft Visual Studio Professional 2012, o código do modelo executará essas tarefas. O código de modelo obtém o identificador para o objeto de dispositivo de destino e armazena no contexto do dispositivo.
O dispositivo deve ter uma configuração ativa.
Um driver cliente KMDF deve chamar o método WdfUsbTargetDeviceSelectConfig .
Para um driver de cliente UMDF, a estrutura seleciona a primeira configuração e a configuração alternativa padrão para cada interface nessa configuração.
Se você estiver usando modelos USB, o código selecionará a primeira configuração e a configuração alternativa padrão em cada interface.
Selecionar uma configuração alternativa em um driver de cliente KMDF
Obtenha um identificador WDFUSBINTERFACE para a interface que tem a configuração alternativa.
Para obter o identificador, primeiro obtenha o número das interfaces da configuração selecionada chamando WdfUsbTargetDeviceGetNumInterfaces e enumerar interfaces em um loop. Em cada iteração, chame o método WdfUsbTargetDeviceGetInterface e incremente o índice (começando em zero).
Nota Durante a enumeração do dispositivo, a pilha de driver USB atribui números às configurações alternativas. Os números de interface são baseados em zero e sequenciais. Esses números podem ser diferentes do índice de configuração definido pelo dispositivo. Para obter o índice de configuração definido pelo dispositivo, chame o método WdfUsbInterfaceGetInterfaceNumber .
Inicie uma solicitação select-interface chamando o método WdfUsbInterfaceSelectSetting . No parâmetro Params da chamada, escolha uma destas opções:
Especifique o número de configuração alternativo atribuído pela pilha de driver USB. Normalmente, você passa o mesmo índice usado na etapa 1 para enumerar as configurações.
Especifique um ponteiro para o descritor de interface que descreve a configuração alternativa. O driver pode obter descritores de interface ao enumerar configurações alternativas na interface chamando o método WdfUsbInterfaceGetDescriptor . Após a conclusão da enumeração, o driver obtém informações sobre todas as configurações alternativas enumeradas na estrutura USB_INTERFACE_DESCRIPTOR .
Especifique um ponteiro para um URB que contenha todas as informações necessárias para a solicitação select-interface.
- Alocar uma matriz de estruturas USBD_INTERFACE_LIST_ENTRY . O número de elementos nessa matriz depende do número de interfaces na configuração selecionada. Para obter informações sobre como inicializar essa matriz, consulte Como selecionar uma configuração para um dispositivo USB.
- Aloque um URB para a solicitação de interface de seleção chamando a rotina de USBD_SelectInterfaceUrbAllocateAndBuild . Nessa chamada, especifique a matriz de lista de interfaces e o identificador de configuração obtido após a seleção de uma configuração. Você pode obter esse identificador chamando o método WdfUsbTargetDeviceWdmGetConfigurationHandle .
- Chame WdfUsbInterfaceSelectSetting e especifique o URB.
**Drivers WDM:**Para enviar o URB, associe o URB a um IRP e envie o IRP para a pilha de driver USB. Para obter mais informações, consulte Como enviar um URB.
As opções na lista fornecem ao driver do cliente a flexibilidade para especificar os critérios de seleção. Se você já estiver ciente dos recursos de ponto de extremidade da configuração alternativa, escolha a primeira opção (com o número de configuração alternativo) na lista. Caso contrário, escolha a segunda opção que especifica o descritor de interface. Inspecione USB_INTERFACE_DESCRIPTOR estruturas para todas as configurações alternativas. Para cada configuração, enumere seus pontos de extremidade e suas características, como, o tipo de ponto de extremidade, o tamanho máximo do pacote e assim por diante. Quando você encontrar o conjunto de pontos de extremidade necessários para transferências de dados, chame WdfUsbInterfaceSelectSetting especificando um ponteiro para esse descritor de interface. Normalmente, você não precisará da terceira opção, a menos que seja um driver cliente baseado em WDM que só possa enviar solicitações para a pilha de driver USB enviando URBs.
Com base nas informações fornecidas pelo driver cliente, a pilha de driver USB cria uma solicitação de controle padrão (SET INTERFACE) e a envia para o dispositivo. Se a solicitação for concluída com êxito, a pilha de driver USB obterá identificadores de pipes para os pontos de extremidade da configuração alternativa.
Depois de selecionar uma configuração alternativa, o driver do cliente sempre deve obter as alças de pipe para pontos de extremidade na nova configuração. Não fazer isso pode fazer com que o driver envie solicitações de transferência de dados usando identificadores de pipe obsoletos. Para obter informações sobre como recuperar identificadores de pipe, consulte Como enumerar pipes 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;
}
Selecionar uma configuração alternativa em um driver de cliente UMDF
Obtenha o número de interfaces USB compatíveis com a configuração ativa chamando o método IWDFUsbTargetDevice::GetNumInterfaces .
Obtenha um ponteiro IWDFUsbInterface para cada interface na configuração.
Enumere todas as interfaces chamando o método IWDFUsbTargetDevice::RetrieveUsbInterface em um loop até que a função retorne NULL. A cada iteração, incremente o índice de membro (baseado em zero). O loop recupera ponteiros IWDFUsbInterface para todas as interfaces enumeradas.
Para cada interface, obtenha o identificador do WinUSB chamando IWDFUsbInterface::GetWinUsbHandle. Esse identificador é exigido pela próxima etapa.
Chame WinUsb_GetAssociatedInterface para obter um identificador para a interface . No parâmetro AssociatedInterfaceIndex , especifique o índice na etapa 2.
Determine o número de configurações alternativas na interface.
Chame a função WinUsb_QueryInterfaceSettings em um loop e incremente o índice (baseado em zero) em cada iteração. Quando todas as configurações são enumeradas, a função retorna ERROR_NO_MORE_ITEMS. A função também retorna descritores de interface para cada configuração.
Usando o valor recebido no membro bNumEndpoints de cada descritor de interface e enumerar seus pontos de extremidade. Inspecione os descritores de ponto de extremidade e determine qual configuração atende às suas necessidades.
Inicie uma solicitação select-interface chamando a função WinUsb_SetCurrentAlternateSetting . Na chamada, especifique o número de configuração alternativo associado ao índice na etapa 4.
Solte o identificador de interface obtido na etapa 4 chamando a função WinUsb_Free .
Libere o identificador do WinUSB obtido na etapa 3 chamando a função WinUsb_Free .
Se você tiver terminado de usar métodos IWDFUsbInterface , libere todos os ponteiros de interface recuperados na etapa 2.
Comentários
Para um driver cliente KMDF, em sua chamada WdfUsbInterfaceSelectSetting , o driver pode fornecer um ponteiro para um contexto de pipe definido pelo driver. O driver do cliente pode armazenar informações sobre pipes no contexto de pipe. Para obter mais informações sobre informações de pipe, consulte Como enumerar pipes USB.