Como enviar uma transferência de controle USB (aplicativo UWP)

Este artigo demonstra:

  • Como formatar um pacote de configuração USB
  • Como iniciar uma transferência de controle USB do seu aplicativo

APIs importantes

Um aplicativo que se comunica com um dispositivo USB geralmente envia várias solicitações de transferências de controle. Essas solicitações obtêm informações sobre o dispositivo e enviam comandos de controle definidos pelo fornecedor de hardware. Neste tópico, você aprenderá sobre transferências de controle e como formatá-las e enviá-las em seu aplicativo UWP.

Uma transferência de controle pode ler ou gravar informações de configuração ou executar funções específicas do dispositivo definidas pelo fornecedor de hardware. Se a transferência executar uma operação de gravação, será uma transferência OUT; uma operação de leitura, é uma transferência IN. Independentemente da direção, um software, como seu aplicativo UWP, no sistema host sempre cria e inicia uma solicitação para uma transferência de controle. Às vezes, seu aplicativo pode iniciar transferências de controle que lê ou grava dados. Nesse caso, talvez seja necessário enviar um buffer adicional.

Para acomodar todos os tipos de transferências de controle, Windows.Devices.Usb fornece estes métodos:

transferência de controle usb para apis do windows runtime para usb.

As transferências de controle USB também são usadas para obter dados do descritor ou enviar comandos padrão. No entanto, recomendamos que você envie esses tipos de solicitações chamando métodos específicos fornecidos por Windows.Devices.Usb em vez de criar uma transferência de controle manualmente. Por exemplo, para selecionar uma configuração alternativa, chame SelectSettingAsync em vez de chamar SendControlOutTransferAsync (UsbSetupPacket).

Não há suporte para transferências de controle para determinados tipos de solicitações padrão. No entanto, se o dispositivo pertencer a uma classe de dispositivo compatível com Windows.Devices.Usb, você poderá enviar algumas solicitações conforme definido pela especificação da classe de dispositivo.

Antes de começar

  • Você deve abrir o dispositivo e obter o objeto UsbDevice . Leia Como se conectar a um dispositivo USB (aplicativo UWP).
  • Obtenha informações sobre comandos de controle definidos pelo fornecedor. Esses comandos normalmente são definidos na especificação de hardware.
  • Você pode ver o código completo mostrado neste tópico no exemplo CustomUsbDeviceAccess, Scenario2_ControlTransfer.cpp e Scenario2_ControlTransfer.h.

Etapa 1: Preencher o pacote de instalação

Neste tópico, enviaremos uma transferência de controle para um dispositivo que pisca luzes em vários padrões. Para preencher o pacote de instalação, você deve saber que os comandos de controle são definidos pelo fornecedor de hardware:

  • bmRequestType (D7): OUT
  • bmRequestType (D4): Dispositivo
  • bmRequestType (D6... D5): Fornecedor
  • bRequest: 0x03
  • wValue: 0-7 (qualquer número nesse intervalo, inclusive)
  • wIndex: 0
  • wLength: 0

Para a transferência de controle, você deve preencher um pacote de instalação que contenha todas as informações sobre a transferência; se a solicitação lê ou grava dados, o tipo de solicitação e assim por diante. O formato do pacote de instalação é definido na especificação usb oficial. Os valores dos campos de pacote de instalação são fornecidos pela especificação de hardware do dispositivo.

  1. Crie um objeto UsbSetupPacket .

  2. Preencha o objeto UsbSetupPacket definindo várias propriedades. Esta tabela mostra os campos de pacote de instalação definidos por USB e as propriedades que correspondem a esses campos:

    Campos na Seção 9.3 Propriedade Descrição
    bmRequestType (D7) UsbControlRequestType.Direction Direção da solicitação. Se a solicitação é do host para o dispositivo (transferências de saída) ou do dispositivo para o host (Em transferências)
    bmRequestType (D4) UsbControlRequestType.Recipient Destinatário da solicitação. Todas as transferências de controle têm como destino o ponto de extremidade padrão. No entanto, o destinatário pode ser dispositivo, interface, ponto de extremidade ou outro. Para obter mais informações sobre dispositivo USB, interface, hierarquia de ponto de extremidade, consulte Layout do dispositivo.
    bmRequestType (D6... D5) UsbControlRequestType.ControlTransferType Categoria de solicitação. Padrão, classe ou fornecedor.
    bRequest UsbSetupPacket.Request Tipo de solicitação. Se a solicitação for uma solicitação padrão, como uma solicitação GET_DESCRIPTOR, essa solicitação será definida pela especificação USB. Caso contrário, ele pode ser definido pelo fornecedor.
    wValue UsbSetupPacket.Value Depende do tipo de solicitação.
    Windex UsbSetupPacket.Index Depende do tipo de solicitação.
    wLength UsbSetupPacket.Length Comprimento do pacote de dados enviado ou recebido nesta solicitação.

! [OBSERVAÇÃO] Para determinadas transferências de controle, talvez seja necessário fornecer bmRequestType como um byte bruto. Nesse caso, você pode definir o byte na propriedade UsbControlRequestType.AsByte .

Etapa 2: Iniciar uma operação assíncrona para enviar a transferência de controle

Para enviar transferências de controle, você deve ter um objeto UsbDevice . Sua transferência de controle pode ou não exigir pacotes de dados que seguem o pacote de instalação.

Para iniciar uma transferência de controle, chame a substituição de SendControlInTransferAsync ou SendControlOutTransferAsync. Se a transferência usar pacotes de dados, chame SendControlOutTransferAsync (UsbSetupPacket, IBuffer),SendControlInTransferAsync (UsbSetupPacket, IBuffer). Esses métodos assumem um parâmetro adicional que contém os dados para gravar ou receber dados do dispositivo. Use o fluxograma para determinar qual substituição chamar.

A chamada inicia e a operação assíncrona. Quando a operação for concluída, a chamada retornará o objeto IAsyncOperation que contém os resultados da operação. Para uma transferência OUT, o objeto retorna o número de bytes enviados em uma transferência. Para uma transferência IN, o objeto contém o buffer que contém dados que foram lidos do dispositivo.

Exemplo de código de transferência de controle USB

Este código de exemplo mostra como enviar uma transferência de controle que altera o padrão piscando no dispositivo SuperMUTT. O pacote de instalação para a transferência contém um comando definido pelo fornecedor. O exemplo está em Scenario2_ControlTransfer.cpp.

async Task SetSuperMuttLedBlinkPatternAsync(Byte pattern)
        {
            UsbSetupPacket initSetupPacket = new UsbSetupPacket
            {
                RequestType = new UsbControlRequestType
                {
                    Direction = UsbTransferDirection.Out,
                    Recipient = UsbControlRecipient.Device,
                    ControlTransferType = UsbControlTransferType.Vendor
                },
                Request = SuperMutt.VendorCommand.SetLedBlinkPattern,
                Value = pattern,
                Length = 0
            };

            UInt32 bytesTransferred = await EventHandlerForDevice.Current.Device.SendControlOutTransferAsync(initSetupPacket);

            MainPage.Current.NotifyUser("The Led blink pattern is set to " + pattern.ToString(), NotifyType.StatusMessage);
        }

Este código de exemplo mostra como enviar uma transferência de controle que altera o padrão piscando no dispositivo SuperMUTT. O pacote de instalação para a transferência contém um comando definido pelo fornecedor. O exemplo está em Scenario2_ControlTransfer.cpp.

async Task<IBuffer> SendVendorControlTransferInToDeviceRecipientAsync(Byte vendorCommand, UInt32 dataPacketLength)
 {
    // Data will be written to this buffer when we receive it
    var buffer = new Windows.Storage.Streams.Buffer(dataPacketLength);

    UsbSetupPacket initSetupPacket = new UsbSetupPacket
    {
        RequestType = new UsbControlRequestType
        {
            Direction = UsbTransferDirection.In,
            Recipient = UsbControlRecipient.Device,
            ControlTransferType = UsbControlTransferType.Vendor,
        },
        Request = vendorCommand,
        Length = dataPacketLength
    };

    return await EventHandlerForDevice.Current.Device.SendControlInTransferAsync(initSetupPacket, buffer);
}