Come inviare un trasferimento di controllo USB (app UWP)
Questo articolo illustra:
- Come formattare un pacchetto di installazione USB
- Come avviare un trasferimento di controllo USB dall'app
API importanti
Un'app che comunica con un dispositivo USB in genere invia diverse richieste di trasferimento dei controlli. Queste richieste ottengono informazioni sul dispositivo e inviano comandi di controllo definiti dal fornitore dell'hardware. In questo argomento scoprirai come controllare i trasferimenti e come formattarli e inviarli nella tua app UWP.
Un trasferimento di controllo può leggere o scrivere informazioni di configurazione o eseguire funzioni specifiche del dispositivo definite dal fornitore dell'hardware. Se il trasferimento esegue un'operazione di scrittura, si tratta di un trasferimento OUT; un'operazione di lettura, è un trasferimento IN. Indipendentemente dalla direzione, un software, ad esempio l'app UWP, nel sistema host compila sempre e avvia una richiesta di trasferimento del controllo. A volte, l'app può avviare trasferimenti di controllo che leggono o scrivono i dati. In tal caso, potrebbe essere necessario inviare un buffer aggiuntivo.
Per supportare tutti i tipi di trasferimenti di controllo, Windows.Devices.Usb fornisce questi metodi:
- SendControlOutTransferAsync (UsbSetupPacket)
- SendControlInTransferAsync (UsbSetupPacket)
- SendControlOutTransferAsync (UsbSetupPacket, IBuffer)
- SendControlInTransferAsync (UsbSetupPacket, IBuffer)
I trasferimenti di controllo USB vengono usati anche per ottenere i dati del descrittore o inviare comandi standard. È tuttavia consigliabile inviare tali tipi di richieste chiamando metodi specifici forniti da Windows.Devices.Usb anziché creare manualmente un trasferimento di controllo. Ad esempio, per selezionare un'impostazione alternativa, chiamare SelectSettingAsync anziché chiamare SendControlOutTransferAsync (UsbSetupPacket).
I trasferimenti di controllo per determinati tipi di richieste standard non sono supportati. Tuttavia, se il dispositivo appartiene a una classe di dispositivo supportata da Windows.Devices.Usb, è possibile inviare alcune richieste come definito dalla specifica della classe di dispositivo.
Prima di iniziare
- È necessario aprire il dispositivo e ottenere l'oggetto UsbDevice . Leggi Come connettersi a un dispositivo USB (app UWP).
- Ottenere informazioni sui comandi di controllo definiti dal fornitore. Questi comandi vengono in genere definiti nella specifica hardware.
- È possibile visualizzare il codice completo illustrato in questo argomento nell'esempio CustomUsbDeviceAccess, Scenario2_ControlTransfer.cpp e Scenario2_ControlTransfer.h.
Passaggio 1: Popolare il pacchetto di installazione
In questo argomento verrà inviato un trasferimento di controllo a un dispositivo che lampeggia le luci in vari modelli. Per popolare il pacchetto di installazione, è necessario conoscere i comandi di controllo definiti dal fornitore dell'hardware:
- bmRequestType (D7): OUT
- bmRequestType (D4): Dispositivo
- bmRequestType (D6... D5): Fornitore
- bRequest: 0x03
- wValue: 0-7 (qualsiasi numero compreso nell'intervallo incluso)
- wIndex: 0
- wLength: 0
Per il trasferimento del controllo, è necessario popolare un pacchetto di installazione contenente tutte le informazioni sul trasferimento, indipendentemente dal fatto che la richiesta legga o scriva i dati, il tipo di richiesta e così via. Il formato del pacchetto di installazione è definito nella specifica USB ufficiale. I valori dei campi pacchetto di installazione vengono forniti dalla specifica hardware del dispositivo.
Creare un oggetto UsbSetupPacket.
Popolare l'oggetto UsbSetupPacket impostando varie proprietà. Questa tabella mostra i campi del pacchetto di installazione definiti da USB e le proprietà che corrispondono a tali campi:
Campi nella sezione 9.3 Proprietà Descrizione bmRequestType (D7) UsbControlRequestType.Direction Direzione della richiesta. Indica se la richiesta proviene dall'host al dispositivo (trasferimenti in uscita) o dal dispositivo all'host (in trasferimenti) bmRequestType (D4) UsbControlRequestType.Recipient Destinatario della richiesta. Tutti i trasferimenti di controllo hanno come destinazione l'endpoint predefinito. Tuttavia, il destinatario potrebbe essere dispositivo, interfaccia, endpoint o altro. Per altre informazioni su dispositivo USB, interfaccia, gerarchia degli endpoint, vedere Layout del dispositivo. bmRequestType (D6... D5) UsbControlRequestType.ControlTransferType Categoria di richiesta. Standard, classe o fornitore. bRequest UsbSetupPacket.Request Tipo di richiesta. Se la richiesta è una richiesta standard, ad esempio una richiesta di GET_DESCRIPTOR, tale richiesta viene definita dalla specifica USB. In caso contrario, potrebbe essere definito dal fornitore. wValue UsbSetupPacket.Value Dipende dal tipo di richiesta. wIndex UsbSetupPacket.Index Dipende dal tipo di richiesta. wLength UsbSetupPacket.Length Lunghezza del pacchetto di dati inviato o ricevuto in questa richiesta.
! [NOTA] Per determinati trasferimenti di controllo, potrebbe essere necessario fornire bmRequestType come byte non elaborato. In tal caso, è possibile impostare il byte nella proprietà UsbControlRequestType.AsByte.
Passaggio 2: Avviare un'operazione asincrona per inviare il trasferimento del controllo
Per inviare trasferimenti di controllo, è necessario disporre di un oggetto UsbDevice . Il trasferimento del controllo può richiedere o meno pacchetti di dati che seguono il pacchetto di installazione.
Per avviare un trasferimento di controllo, chiamare un override di SendControlInTransferAsync o SendControlOutTransferAsync. Se il trasferimento usa pacchetti di dati, chiama SendControlOutTransferAsync (UsbSetupPacket, IBuffer), SendControlInTransferAsync (UsbSetupPacket, IBuffer). Questi metodi accettano un parametro aggiuntivo che contiene i dati da scrivere o ricevere dati dal dispositivo. Usare il diagramma di flusso per determinare quale override chiamare.
La chiamata avvia e l'operazione asincrona. Al termine dell'operazione, la chiamata restituisce l'oggetto IAsyncOperation che contiene i risultati dell'operazione. Per un trasferimento OUT, l'oggetto restituisce il numero di byte inviati in un trasferimento. Per un trasferimento IN, l'oggetto contiene il buffer che contiene i dati letti dal dispositivo.
Esempio di codice di trasferimento del controllo USB
Questo codice di esempio illustra come inviare un trasferimento di controllo che modifica il modello lampeggiante nel dispositivo SuperMUTT. Il pacchetto di installazione per il trasferimento contiene un comando definito dal fornitore. L'esempio si trova in 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);
}
Questo codice di esempio illustra come inviare un trasferimento di controllo che modifica il modello lampeggiante nel dispositivo SuperMUTT. Il pacchetto di installazione per il trasferimento contiene un comando definito dal fornitore. L'esempio si trova in 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);
}