Função USBD_QueryUsbCapability (usbdlib.h)

A rotina de USBD_QueryUsbCapability é chamada por um driver de cliente WDM para determinar se a pilha de driver USB subjacente e o hardware do controlador de host dão suporte a uma funcionalidade específica. Observação para drivers WDF (Windows Driver Framework): Se o driver cliente for um driver baseado em WDF, você deverá chamar o método WdfUsbTargetDeviceQueryUsbCapability em vez de USBD_QueryUsbCapability.

Sintaxe

NTSTATUS USBD_QueryUsbCapability(
  [in]            USBD_HANDLE USBDHandle,
  [in]            const GUID  *CapabilityType,
  [in]            ULONG       OutputBufferLength,
  [in, out]       PUCHAR      OutputBuffer,
  [out, optional] PULONG      ResultLength
);

Parâmetros

[in] USBDHandle

Identificador USBD recuperado pelo driver cliente em uma chamada anterior para a rotina de USBD_CreateHandle .

[in] CapabilityType

Ponteiro para um GUID que representa a capacidade para a qual o driver cliente deseja recuperar informações. Os possíveis valores PGUID são os seguintes:

  • GUID_USB_CAPABILITY_CHAINED_MDLS
  • GUID_USB_CAPABILITY_STATIC_STREAMS
  • GUID_USB_CAPABILITY_SELECTIVE_SUSPEND
  • GUID_USB_CAPABILITY_FUNCTION_SUSPEND
  • GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE
  • GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE
  • GUID_USB_CAPABILITY_TIME_SYNC

[in] OutputBufferLength

Comprimento, em bytes, do buffer apontado por OutputBuffer.

[in, out] OutputBuffer

Ponteiro para um buffer alocado pelo chamador. Determinadas solicitações de funcionalidade retornam informações adicionais em um buffer de saída. Para essas solicitações, você deve alocar o buffer e fornecer um ponteiro para o buffer no parâmetro OutputBuffer . Atualmente, apenas a solicitação de funcionalidade de fluxos estáticos requer um buffer de saída do tipo USHORT. O buffer é preenchido por USBD_QueryUsbCapability com o número máximo de fluxos com suporte por ponto de extremidade.

Outras solicitações de funcionalidade não exigem um buffer de saída. Para essas solicitações, você deve definir OutputBuffer como NULL e OutputBufferLength como 0.

[out, optional] ResultLength

Ponteiro para uma variável ULONG que recebe o número real de bytes no buffer apontado por OutputBuffer. O chamador pode passar NULL em ResultLength. Se ResultLength não for NULL, o valor recebido será menor ou igual ao valor OutputBufferLength .

Retornar valor

A rotina de USBD_QueryUsbCapability retorna um código de status NT.

Os valores possíveis incluem, mas não se limitam a, os códigos de status listados na tabela a seguir.

Código de retorno Descrição
STATUS_SUCCESS
A solicitação foi bem-sucedida e há suporte para a funcionalidade especificada.
STATUS_INVALID_PARAMETER
O chamador passou um valor de parâmetro inválido.
  • USBDHandle ou CapabilityType é NULL.
  • OutputBuffer é NULL, mas OutputBufferLength indica um valor diferente de zero. Por outro lado, o chamador forneceu um buffer de saída, mas o comprimento do buffer é 0.
STATUS_NOT_IMPLEMENTED
A funcionalidade especificada não é compatível com a pilha de driver USB subjacente.
STATUS_NOT_SUPPORTED
Não há suporte para a funcionalidade especificada pelo hardware do controlador de host ou pela pilha do driver USB.

Comentários

Windows 8 inclui uma nova pilha de driver USB para dar suporte a dispositivos USB 3.0. A nova pilha de driver USB fornece vários novos recursos definidos, como suporte a fluxo e MDLs encadeados que podem ser usados por um driver cliente.

Um driver cliente pode determinar a versão da pilha de driver USB subjacente chamando a rotina IsInterfaceVersionSupported .

O driver cliente só poderá usar os novos recursos se a pilha de driver USB subjacente e o hardware deem suporte a eles. Por exemplo, para enviar solicitações de E/S para um fluxo específico associado a um ponto de extremidade em massa, a pilha de driver USB subjacente, o ponto de extremidade e o hardware do controlador de host devem dar suporte à funcionalidade de fluxos estáticos. O driver do cliente não deve chamar IsInterfaceVersionSupported e assumir os recursos da pilha de driver. Em vez disso, o driver do cliente deve sempre chamar USBD_QueryUsbCapability para determinar se a pilha de driver USB e o hardware dão suporte a uma funcionalidade específica.

A tabela a seguir descreve os recursos específicos de USB que um driver cliente pode consultar por meio de uma chamada USBD_QueryUsbCapability .

GUID de funcionalidade Descrição
GUID_USB_CAPABILITY_CHAINED_MDLS Se a pilha de driver USB der suporte a MDLs encadeados, o driver do cliente poderá fornecer os dados de transferência como uma cadeia de MDLs que fazem referência a buffers segmentados na memória física. Para obter mais informações, consulte MDL. Os MDLs encadeados impedem a necessidade de alocar e copiar memória para criar buffers virtualmente contíguos e, portanto, tornar as transferências de E/S mais eficientes. Para obter mais informações, consulte Como enviar MDLs encadeados.
GUID_USB_CAPABILITY_STATIC_STREAMS Se houver suporte, o driver cliente poderá enviar solicitações de E/S para fluxos em um ponto de extremidade em massa.

Para a solicitação de consulta de fluxos estáticos, o driver do cliente é necessário para fornecer um USHORT (buffer de saída). Após a conclusão da chamada e se a funcionalidade de fluxos estáticos tiver suporte, o buffer de saída receberá o número máximo de fluxos com suporte pelo controlador de host.

O valor do buffer de saída não indica o número máximo de fluxos com suporte pelo ponto de extremidade em massa no dispositivo. Para determinar esse número, o driver do cliente deve inspecionar o descritor complementar do ponto de extremidade.

A pilha de driver USB em Windows 8 dá suporte a até 255 fluxos.

Se houver suporte para fluxos estáticos, o driver do cliente poderá enviar solicitações de E/S para o primeiro fluxo (também chamado de fluxo padrão) usando o identificador de pipe obtido por meio de uma solicitação de configuração de seleção. Para outros fluxos no ponto de extremidade, o driver cliente deve abrir esses fluxos e obter identificadores de pipe para eles para enviar solicitações de E/S. Para obter mais informações sobre como abrir fluxos, consulte Como abrir e fechar fluxos estáticos em um ponto de extremidade em massa USB.

GUID_USB_CAPABILITY_FUNCTION_SUSPEND Essa funcionalidade determina se a pilha de driver USB subjacente dá suporte a recursos de suspensão de função USB e Wake-Up remoto. Se houver suporte, a pilha de driver poderá processar um sinal de retomada (para ativação remota) de uma função individual em um dispositivo composto USB 3.0. Com base nesse sinal, um driver de função individual pode sair do estado de baixa potência de sua função.

A funcionalidade destina-se a ser usada por um driver composto: o driver que é carregado como o FDO (objeto do dispositivo de função) na pilha do dispositivo para o dispositivo composto. Por padrão, o Driver Pai Genérico USB fornecido pela Microsoft (Usbccgp.sys) é carregado como o FDO.

Se o driver substituir Usbccgp.sys, o driver deverá ser capaz de solicitar a ativação remota e propagar o sinal de retomada da pilha do driver USB. Antes de implementar essa lógica, o driver deve determinar o suporte da pilha de driver USB para a funcionalidade de suspensão de função chamando USBD_QueryUsbCapability. Usbccgp.sys em Windows 8 implementa a suspensão da função.

Para obter um exemplo de código e mais informações sobre a suspensão da função, consulte Como implementar a suspensão de função em um driver composto.

GUID_USB_CAPABILITY_SELECTIVE_SUSPEND Determina se a pilha de driver USB subjacente dá suporte à suspensão seletiva.

Para obter informações sobre a suspensão seletiva, consulte Suspensão seletiva usb.

GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE Determina se o ônibus está operando em alta velocidade ou superior.
GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE Determina se o ônibus está operando em SuperSpeed ou superior.
GUID_USB_CAPABILITY_TIME_SYNC Determina se o número do quadro e o recurso de associação QPC têm suporte no controlador. 
 

Exemplos

O snippet de código mostra como chamar USBD_QueryUsbCapability para determinar os recursos da pilha de driver USB subjacente.


/*++

Routine Description:
This helper routine queries the underlying USB driver stack
for specific capabilities. This code snippet assumes that 
USBD handle was retrieved by the client driver in a 
previous call to the USBD_CreateHandle routine.

Parameters:

fdo: Pointer to the device object that is the current top
of the stack as reported by IoAttachDeviceToDeviceStack.

Return Value: VOID
--*/

VOID QueryUsbDriverStackCaps (PDEVICE_OBJECT fdo)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;   
    PDEVICE_EXTENSION deviceExtension;

    deviceExtension = (PDEVICE_EXTENSION)fdo->DeviceExtension;

    if (!deviceExtension->UsbdHandle)
    {
        return;
    }

    // Check if the underlying USB driver stack
    // supports USB 3.0 devices.

    if (!USBD_IsInterfaceVersionSupported(
        deviceExtension->UsbdHandle,                                       
        USBD_INTERFACE_VERSION_602))
    {
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Old USB stack loaded.\n" ));
    }
    else
    {
        // Call USBD_QueryUsbCapability to determine 
        // function suspend support.     
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "New USB stack loaded.\n" ));
        ntStatus = USBD_QueryUsbCapability ( deviceExtension->UsbdHandle,  
            (GUID*)&GUID_USB_CAPABILITY_FUNCTION_SUSPEND,  
            0,  
            NULL,
            NULL);

        if (NT_SUCCESS(ntStatus)) 
        {
            deviceExtension->FunctionSuspendSupported = TRUE;
            KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Function suspend supported.\n" ));
        } 
        else 
        {
            deviceExtension->FunctionSuspendSupported  = FALSE;
            ntStatus = STATUS_SUCCESS;
            KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Function suspend not supported.\n" ));
        }
    }

    // Call USBD_QueryUsbCapability to determine 
    // chained MDL support. 

    ntStatus = USBD_QueryUsbCapability(
        deviceExtension->UsbdHandle,
        (GUID*)&GUID_USB_CAPABILITY_CHAINED_MDLS,
        0,
        NULL,
        NULL);

    if (NT_SUCCESS(ntStatus)) 
    {
        deviceExtension->ChainedMDLSupport = TRUE;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Chained MDLs supported.\n" ));
    } 
    else 
    {
        deviceExtension->ChainedMDLSupport = FALSE;
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Chained MDLs not supported.\n" ));
    }

    // Call USBD_QueryUsbCapability to determine 
    // stream support. 

    ntStatus = USBD_QueryUsbCapability (deviceExtension->UsbdHandle, 
        (GUID*)&GUID_USB_CAPABILITY_STATIC_STREAMS, 
        sizeof(ULONG), 
        (PUCHAR) &deviceExtension->MaxSupportedStreams, 
        NULL);  


    if (!NT_SUCCESS(ntStatus)) 
    {
        deviceExtension->MaxSupportedStreams = 0;
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Static streams not supported.\n" ));
    }

    // Call USBD_QueryUsbCapability to determine 
    // selective suspend support. 

    ntStatus = USBD_QueryUsbCapability (deviceExtension->UsbdHandle, 
        (GUID*)&GUID_USB_CAPABILITY_SELECTIVE_SUSPEND, 
        0, 
        NULL, 
        NULL);

    if (!NT_SUCCESS(ntStatus)) 
    {
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Selective suspend not supported.\n" ));
    }
    else
    {
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Selective suspend supported.\n" ));
    }

    // Call USBD_QueryUsbCapability to determine 
    // device speed. 
    ntStatus = USBD_QueryUsbCapability (deviceExtension->UsbdHandle, 
        (GUID*)&GUID_USB_CAPABILITY_DEVICE_CONNECTION_HIGH_SPEED_COMPATIBLE, 
        0, 
        NULL, 
        NULL);

    if (!NT_SUCCESS(ntStatus)) 
    {
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "The device is operating at full speed or lower.\n The device can operate at high speed or higher." ));
    }
    else
    {
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "The device is operating at high speed or higher.\n" ));
    }

    // Call USBD_QueryUsbCapability to determine 
    // device speed. 
    ntStatus = USBD_QueryUsbCapability (deviceExtension->UsbdHandle, 
        (GUID*)&GUID_USB_CAPABILITY_DEVICE_CONNECTION_SUPER_SPEED_COMPATIBLE, 
        0, 
        NULL, 
        NULL);

    if (!NT_SUCCESS(ntStatus)) 
    {
        ntStatus = STATUS_SUCCESS;
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "The device is operating at high speed or lower.\n The device can operate at Superspeed or higher." ));
    }
    else
    {
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "The device is operating at SuperSpeed or higher.\n" ));
    }

    return;

}

Requisitos

Requisito Valor
Cliente mínimo com suporte Requer WDK para Windows 8. Tem como destino o Windows Vista e versões posteriores do sistema operacional Windows.
Plataforma de Destino Área de Trabalho
Cabeçalho usbdlib.h (inclua Usbdlib.h)
Biblioteca Usbdex.lib
IRQL PASSIVE_LEVEL

Confira também

Referência de programação do driver de dispositivo USB