Cómo enviar una transferencia de control USB (aplicación UWP)
En este artículo se muestra lo siguiente:
- Cómo formatear un paquete de configuración USB
- Cómo iniciar una transferencia de control USB desde la aplicación
API importantes
Una aplicación que se comunica con un dispositivo USB normalmente envía varias solicitudes de transferencia de control. Esas solicitudes obtienen información sobre el dispositivo y envían comandos de control definidos por el proveedor de hardware. En este artículo, obtendrá información sobre las transferencias de control y cómo formatearlas y enviarlas en la aplicación para UWP.
Una transferencia de control puede leer o escribir información de configuración o realizar funciones específicas del dispositivo definidas por el proveedor de hardware. Si la transferencia realiza una operación de escritura, es una transferencia OUT; una operación de lectura, es una transferencia IN. Independientemente de la dirección, un software, como la aplicación para UWP, en el sistema host siempre se crea e inicia una solicitud de transferencia de control. En ocasiones, la aplicación puede iniciar transferencias de control que leen o escriben datos. En ese caso, es posible que tenga que enviar un búfer adicional.
Para dar cabida a todos los tipos de transferencias de control, Windows.Devices.Usb proporciona estos métodos:
- SendControlOutTransferAsync (UsbSetupPacket)
- SendControlInTransferAsync (UsbSetupPacket)
- SendControlOutTransferAsync (UsbSetupPacket, IBuffer)
- SendControlInTransferAsync (UsbSetupPacket, IBuffer)
Las transferencias de control USB también se usan para obtener datos de descriptor o enviar comandos estándar. Sin embargo, se recomienda enviar esos tipos de solicitudes mediante una llamada a métodos específicos proporcionados por Windows.Devices.Usb en lugar de crear una transferencia de control manualmente. Por ejemplo, para seleccionar una configuración alternativa, llame a SelectSettingAsync en lugar de llamar a SendControlOutTransferAsync (UsbSetupPacket).
No se admiten transferencias de control para determinados tipos de solicitudes estándar. Sin embargo, si el dispositivo pertenece a una clase de dispositivo compatible con Windows.Devices.Usb, puede enviar algunas solicitudes definidas por la especificación de la clase de dispositivo.
Antes de comenzar
- Debe haber abierto el dispositivo y obtenido el objeto UsbDevice. Consulte Cómo conectarse a un dispositivo USB (aplicación para UWP).
- Debe haber obtenido información sobre los comandos de control definidos por el proveedor. Estos comandos se definen normalmente en la especificación de hardware.
- Puede ver el código completo que se muestra en este tema en el ejemplo CustomUsbDeviceAccess, Scenario2_ControlTransfer.cpp y Scenario2_ControlTransfer.h.
Paso 1: Rellenar el paquete de instalación
En este tema, enviaremos una transferencia de control a un dispositivo que hace parpadear luces en varios patrones. Para rellenar el paquete de instalación, debe saber que el proveedor de hardware define los comandos de control:
- bmRequestType (D7): OUT
- bmRequestType (D4): Dispositivo
- bmRequestType (D6…D5): Proveedor
- bRequest: 0x03
- wValue: 0-7 (cualquier número dentro de ese intervalo, inclusive)
- wIndex: 0
- wLength: 0
Para la transferencia de control, debe rellenar un paquete de instalación que contenga toda la información sobre la transferencia; si la solicitud lee o escribe datos, el tipo de solicitud, etc. El formato del paquete de instalación se define en la especificación USB oficial. Los valores de los campos de paquete de instalación los proporciona la especificación de hardware del dispositivo.
Cree un objeto UsbSetupPacket.
Rellene el objeto UsbSetupPacket configurando varias propiedades. En esta tabla se muestran los campos de paquete de instalación definidos por USB y las propiedades que corresponden a esos campos:
Campos de la sección 9.3 Propiedad Descripción bmRequestType (D7) UsbControlRequestType.Direction Dirección de la solicitud. Si la solicitud es de host a dispositivo (transferencias OUT) o dispositivo al host (transferencias IN) bmRequestType (D4) UsbControlRequestType.Recipient Destinatario de la solicitud. odas las transferencias de control tienen como destino el punto de conexión predeterminado. Sin embargo, el destinatario puede ser un dispositivo, una interfaz, un punto de conexión u otro. Para obtener más información sobre el dispositivo USB, la interfaz, la jerarquía de puntos de conexión, consulte Diseño de dispositivo. bmRequestType (D6…D5) UsbControlRequestType.ControlTransferType Categoría de solicitud. Estándar, clase o proveedor. bRequest UsbSetupPacket.Request Tipo de solicitud. Si la solicitud es una solicitud estándar, como una solicitud GET_DESCRIPTOR, esa solicitud se define mediante la especificación USB. De lo contrario, podría definirse por el proveedor. wValue UsbSetupPacket.Value Depende del tipo de solicitud. wIndex UsbSetupPacket.Index Depende del tipo de solicitud. wLength UsbSetupPacket.Length Longitud del paquete de datos enviado o recibido en esta solicitud.
![NOTA] Para determinadas transferencias de control, es posible que tenga que proporcionar bmRequestType como un byte sin formato. En ese caso, puede establecer el byte en la propiedad UsbControlRequestType.AsByte.
Paso 2: Iniciar una operación asincrónica para enviar la transferencia de control
Para enviar transferencias de control, debe tener un objeto UsbDevice. La transferencia de control puede requerir o no paquetes de datos que sigan al paquete de instalación.
Para iniciar una transferencia de control, llame a la invalidación de SendControlInTransferAsync o SendControlOutTransferAsync. Si la transferencia usa paquetes de datos, llame a SendControlOutTransferAsync (UsbSetupPacket, IBuffer), SendControlInTransferAsync (UsbSetupPacket, IBuffer). Esos métodos toman un parámetro adicional que contiene los datos que se van a escribir o para recibir datos del dispositivo. Use el diagrama de flujo para determinar a qué invalidación llamar.
La llamada inicia una operación asincrónica. Cuando se completa la operación, la llamada devuelve el objeto IAsyncOperation que contiene los resultados de la operación. Para una transferencia OUT, el objeto devuelve el número de bytes enviados en una transferencia. Para una transferencia IN, el objeto contiene el búfer que contiene datos leídos desde el dispositivo.
Ejemplo de código de transferencia de control USB
En este código de ejemplo se muestra cómo enviar una transferencia de control que cambia el patrón de parpadeo en el dispositivo SuperMUTT. El paquete de instalación de la transferencia contiene un comando definido por el proveedor. El ejemplo está en 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);
}
En este código de ejemplo se muestra cómo enviar una transferencia de control que cambia el patrón de parpadeo en el dispositivo SuperMUTT. El paquete de instalación de la transferencia contiene un comando definido por el proveedor. El ejemplo está en 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);
}