Comment envoyer un transfert de contrôle USB (application UWP)
Le présent article porte sur les éléments suivants :
- Comment formater un paquet de configuration USB
- Comment initier un transfert de contrôle USB depuis votre application
API importantes
Une application qui communique avec un périphérique USB envoie généralement plusieurs demandes de transfert de contrôle. Ces demandes obtiennent des informations sur le périphérique et envoient des commandes de contrôle définies par le fabricant du matériel. Dans cette rubrique, vous apprendrez ce qu’est un transfert de contrôle et comment les formater et les envoyer dans votre application UWP.
Un transfert de contrôle peut lire ou écrire des informations de configuration ou effectuer des fonctions spécifiques définies par le fabricant du matériel. Si le transfert effectue une opération d’écriture, il s’agit d’un transfert OUT ; une opération de lecture, il s’agit d’un transfert IN. Quel que soit le sens, un logiciel, tel que votre application UWP, sur le système hôte construit et initie toujours une demande de transfert de contrôle. Parfois, votre application peut initier des transferts de contrôle qui lisent ou écrivent des données. Dans ce cas, vous pourriez avoir besoin d’envoyer un tampon supplémentaire.
Pour prendre en charge tous les types de transferts de contrôle, Windows.Devices.Usb fournit ces méthodes :
- SendControlOutTransferAsync (UsbSetupPacket)
- SendControlInTransferAsync (UsbSetupPacket)
- SendControlOutTransferAsync (UsbSetupPacket, IBuffer)
- SendControlInTransferAsync (UsbSetupPacket, IBuffer)
Les transferts de contrôle USB sont également utilisés pour obtenir des données de descripteur ou envoyer des commandes standard. Cependant, nous recommandons d’envoyer ces types de demandes en appelant des méthodes spécifiques fournies par Windows.Devices.Usb plutôt qu’en construisant manuellement un transfert de contrôle. Par exemple, pour sélectionner un paramètre alternatif, appelez SelectSettingAsync au lieu d’appeler SendControlOutTransferAsync (UsbSetupPacket).
Les transferts de contrôle pour certains types de demandes standard ne sont pas pris en charge. Cependant, si votre périphérique appartient à une classe de périphériques prise en charge par Windows.Devices.Usb, vous pouvez envoyer certaines demandes telles que définies par la spécification de la classe de périphériques.
Avant de commencer
- Vous devez avoir ouvert le périphérique et obtenu l’objet UsbDevice. Lisez Comment se connecter à un dispositif USB (application UWP).
- Obtenez des informations sur les commandes de contrôle définies par le fabricant. Ces commandes sont généralement définies dans la spécification matérielle.
- Vous pouvez voir le code complet montré dans cette rubrique dans l’exemple CustomUsbDeviceAccess, Scenario2_ControlTransfer.cpp et Scenario2_ControlTransfer.h.
Étape 1 : Remplir le paquet de configuration
Dans cette rubrique, nous enverrons un transfert de contrôle à un périphérique qui fait clignoter des lumières dans divers motifs. Pour remplir le paquet de configuration, vous devez connaître les commandes de contrôle définies par le fabricant du matériel :
- bmRequestType (D7): OUT
- bmRequestType (D4): Device
- bmRequestType (D6…D5): Vendor
- bRequest: 0x03
- wValue : 0-7 (tout nombre dans cette plage, inclus)
- wIndex: 0
- wLength: 0
Pour le transfert de contrôle, vous devez remplir un paquet de configuration qui contient toutes les informations sur le transfert ; que la demande lise ou écrive des données, le type de demande, etc. Le format du paquet de configuration est défini dans la spécification officielle USB. Les valeurs des champs du paquet de configuration sont fournies par la spécification matérielle du périphérique.
Créez un objet UsbSetupPacket.
Remplissez l’objet UsbSetupPacket en définissant diverses propriétés. Ce tableau montre les champs du paquet de configuration définis par USB et les propriétés qui correspondent à ces champs :
Champs dans la section 9.3 Propriété Description bmRequestType (D7) UsbControlRequestType.Direction Direction de la demande. Que la demande aille de l’hôte au périphérique (transferts OUT) ou du périphérique à l’hôte (transferts IN) bmRequestType (D4) UsbControlRequestType.Recipient Destinataire de la demande. Tous les transferts de contrôle ciblent le point de terminaison par défaut. Cependant, le destinataire peut être un périphérique, une interface, un point de terminaison ou autre. Pour plus d’informations sur la hiérarchie des périphériques, interfaces, points de terminaison USB, consultez Device Layout. bmRequestType (D6…D5) UsbControlRequestType.ControlTransferType Catégorie de la demande. Standard, classe ou fabricant. bRequest UsbSetupPacket.Request Type de la demande. Si la demande est une demande standard, telle qu’une demande GET_DESCRIPTOR, cette demande est définie par la spécification USB. Sinon, elle peut être définie par le fabricant. wValue UsbSetupPacket.Value Dépend du type de demande. wIndex UsbSetupPacket.Index Dépend du type de demande. wLength UsbSetupPacket.Length Longueur du paquet de données envoyé ou reçu dans cette demande.
![NOTE] Pour certains transferts de contrôle, vous pourriez devoir fournir bmRequestType en tant qu’octet brut. Dans ce cas, vous pouvez définir l’octet dans la propriété UsbControlRequestType.AsByte.
Étape 2 : Démarrer une opération asynchrone pour envoyer le transfert de contrôle
Pour envoyer des transferts de contrôle, vous devez avoir un objet UsbDevice. Votre transfert de contrôle peut ou non nécessiter des paquets de données qui suivent le paquet de configuration.
Pour initier un transfert de contrôle, appelez une des surcharges de SendControlInTransferAsync ou SendControlOutTransferAsync. Si le transfert utilise des paquets de données, appelez alors SendControlOutTransferAsync (UsbSetupPacket, IBuffer), SendControlInTransferAsync (UsbSetupPacket, IBuffer). Ces méthodes prennent un paramètre supplémentaire qui contient les données à écrire ou reçoit des données du périphérique. Utilisez l’organigramme pour déterminer quelle surcharge appeler.
L’appel démarre une opération asynchrone. Lorsque l’opération se termine, l’appel renvoie un objet IAsyncOperation qui contient les résultats de l’opération. Pour un transfert OUT, l’objet renvoie le nombre d’octets envoyés dans un transfert. Pour un transfert IN, l’objet contient le tampon qui contient les données lues depuis le périphérique.
Exemple de code de transfert de contrôle USB
Cet exemple de code montre comment envoyer un transfert de contrôle qui modifie le motif de clignotement sur le périphérique SuperMUTT. Le paquet de configuration pour le transfert contient une commande définie par le fabricant. L’exemple se trouve dans 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);
}
Cet exemple de code montre comment envoyer un transfert de contrôle qui modifie le motif de clignotement sur le périphérique SuperMUTT. Le paquet de configuration pour le transfert contient une commande définie par le fabricant. L’exemple se trouve dans 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);
}