Condividi tramite


Come connettersi a un dispositivo USB (app UWP)

In Windows puoi scrivere un'app UWP che interagisce con un dispositivo USB.

L'articolo illustra:

  • Come usare l'oggetto DeviceWatcher per rilevare i dispositivi
  • Come aprire il dispositivo per la comunicazione
  • Come chiudere il dispositivo al termine dell'uso

API importanti

Quando scrivi un'app UWP che interagisce con un dispositivo USB, l'app può inviare comandi di controllo, ottenere informazioni sul dispositivo e leggere e scrivere dati in/da endpoint bulk ed interrupt. Prima di poter eseguire tutto ciò, è necessario trovare il dispositivo e stabilire la connessione.

Prima di iniziare

  • Questo è il primo argomento di una serie. Prima di iniziare questa esercitazione, è necessario aver creato un progetto di Visual Studio di base che è possibile estendere in questa esercitazione. Per altre informazioni, vedere Introduzione alle app UWP .
  • Gli esempi di codice sono basati sull'esempio CustomUsbDeviceAccess. È possibile scaricare l'esempio completo da questa tabella della raccolta codici.
  • Il dispositivo USB usato nell'esercitazione è il dispositivo SuperMUTT.
  • Per usare lo spazio dei nomi Windows.Devices.Usb per scrivere un'app di Windows che interagisce con un dispositivo USB, il dispositivo deve avere il driver Winusb.sys caricato come driver di funzione. Winusb.sys viene fornito da Microsoft ed è incluso in Windows nella cartella \Windows\System32\drivers .

Diagramma di flusso: ricerca del dispositivo

Per connettersi a un dispositivo USB, è prima necessario trovare il dispositivo in base a vari modelli di individuazione e quindi connettersi a esso:

  • Connettersi a qualsiasi dispositivo USB con un GUID dell'interfaccia del dispositivo specifico.
  • Connettersi a un dispositivo USB con un ID fornitore e un ID prodotto specifici e con un GUID dell'interfaccia del dispositivo specifico.
  • Connettersi a un dispositivo USB con un ID fornitore e un ID prodotto specifici senza conoscere il GUID dell'interfaccia del dispositivo.
  • Connettersi a un dispositivo USB con classe di dispositivo nota.

individuazione dei dispositivi USB.

Concetti chiave

Che cos'è un GUID dell'interfaccia del dispositivo?

Un driver del modello kernel, durante l'inizializzazione, registra ed espone un GUID denominato GUID dell'interfaccia del dispositivo. In genere, l'app usa il GUID esposto per trovare il driver associato e il relativo dispositivo e quindi aprire un handle per il dispositivo. L'handle recuperato viene usato per le operazioni di lettura e scrittura successive.

Tuttavia, nel caso di Winusb.sys, anziché il driver che espone il GUID dell'interfaccia del dispositivo, può essere fornito in uno dei due modi seguenti:

  • Nei descrittori del sistema operativo MS del dispositivo. Il produttore del dispositivo imposta DeviceInterfaceGUID come proprietà personalizzata nel descrittore delle proprietà estese nel dispositivo. Per altri dettagli, vedere il documento "Descrittori di proprietà estese" nei descrittori del sistema operativo Microsoft.
  • Se è stato installato Winusb.sys manualmente tramite un INF personalizzato, l'INF ha registrato un GUID in INF. Vedere Installazione di WinUSB (Winusb.sys).

Se viene trovato un GUID dell'interfaccia del dispositivo per il dispositivo, l'app UWP può trovare tutti i dispositivi che corrispondono al GUID dell'interfaccia del dispositivo.

Come viene visualizzata l'identificazione del dispositivo USB in Windows?

Ogni dispositivo USB deve avere due informazioni: ID fornitore e ID prodotto.

USB-IF assegna tali identificatori e il produttore del dispositivo deve esporli nel dispositivo. Quindi, come puoi ottenere queste informazioni?

  • Anche quando il dispositivo non ha un driver di dispositivo caricato, ovvero Windows lo rileva come "Dispositivo sconosciuto", puoi comunque visualizzare gli identificatori nel Gestione dispositivi nel valore della proprietà Id hardware. Tale valore è una combinazione di questi due identificatori. Ad esempio, per il dispositivo SuperMUTT, l'ID hardware è "USB\VID_045E&PID_F001"; l'ID fornitore è "0x045E" e l'ID prodotto è "0xF001".

  • Se è presente un INF per il dispositivo, ottenere tale stringa dalla sezione Modelli .

  • È possibile esaminare varie impostazioni del Registro di sistema. Il modo più semplice è vedere il

    <ID hardwareHKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USB\>

    Per altre informazioni, vedere Voci del Registro di sistema dei dispositivi USB.

  • L'ID hardware viene usato dal manifesto dell'app per identificare il dispositivo.

    <ID dispositivo="vidpid:045e f001">

L'app UWP può trovare tutti i dispositivi che corrispondono a uno specifico fornitore e ID prodotto. È possibile restringere i risultati della ricerca specificando il GUID dell'interfaccia del dispositivo.

Che cosa sono le classi di dispositivi USB?

La maggior parte dei dispositivi USB è conforme alle specifiche della classe di dispositivo approvate da USB-IF. Usando queste specifiche, i dispositivi di natura simile possono presentare le loro funzionalità in modo standard. Il vantaggio principale di questo approccio è che il dispositivo può usare un driver di classe in-box fornito da Microsoft o il driver di Winusb.sys generico.

Alcuni dispositivi potrebbero non seguire una specifica USB-IF. Espongono invece funzionalità definite dal fornitore . Per tali dispositivi, il fornitore deve fornire il driver di dispositivo o Winusb.sys può essere usato.

Se un dispositivo è definito dal fornitore o è conforme a una classe di dispositivo, deve descrivere queste informazioni correlate alla classe di dispositivo:

  • Codice classe: indica la classe del dispositivo a cui appartiene il dispositivo.
  • Codice sottoclasse: all'interno della classe device, indica la sottoclasse del dispositivo.
  • Codice protocollo: protocollo usato dal dispositivo.

Ad esempio, il dispositivo SuperMUTT è un dispositivo definito dal fornitore e che le informazioni sono indicate dal codice di classe sono FF. Se il dispositivo mostra il codice della classe come FEh, il codice della sottoclasse come 02h e il codice del protocollo 00h, è possibile concludere che il dispositivo è un dispositivo bridge IrDA conforme alla classe. L'app UWP può comunicare con i dispositivi che appartengono a queste classi di dispositivi:

  • ActiveSync
  • CdcControl
  • DeviceFirmwareUpdate
  • Irda
  • Misura
  • PalmSync
  • PersonalHealthcare
  • Fisico
  • VendorSpecific

L'app UWP può trovare tutti i dispositivi che corrispondono a un set specifico di codici di classe, sottoclasse e protocollo.

Ottenere la stringa Sintassi query avanzata (AQS) per il dispositivo

Generare una stringa di query avanzata (AQS) che contiene informazioni di identificazione sul dispositivo che si vuole rilevare. È possibile generare la stringa specificando gli ID fornitore/prodotto, il GUID dell'interfaccia del dispositivo o la classe del dispositivo.

  • Per specificare l'ID fornitore/ID prodotto o il GUID dell'interfaccia del dispositivo, chiamare qualsiasi overload di GetDeviceSelector.

    Nell'esempio del dispositivo SuperMUTT , GetDeviceSelector recupera una stringa AQS simile a questa stringa:

    "System.Devices.InterfaceClassGuid:="{DEE824EF-729B-4A0E-9C14-B7117D33A817}" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True AND System.DeviceInterface.WinUsb.UsbVendorId:=1118 AND System.DeviceInterface.WinUsb.UsbProductId:=61441"

    Nota Si noti che il GUID dell'interfaccia del dispositivo visualizzato nella stringa non è quello specificato. Tale GUID è il GUID effettivo dell'interfaccia del dispositivo registrato da Winusb.sys per le app UWP.

  • Se si conosce la classe di dispositivo del dispositivo o della relativa classe, sottoclasse e codici di protocollo, chiamare GetDeviceClassSelector per generare la stringa AQS.

    Creare un oggetto UsbDeviceClass specificando i valori della proprietà ClassCode, SubclassCode e ProtocolCode . In alternativa, se si conosce la classe di dispositivo del dispositivo, è possibile chiamare il costruttore specificando una particolare proprietà UsbDeviceClasses .

Ricerca del dispositivo: il modo di base

Questo è il modo più semplice per trovare un dispositivo USB. Per informazioni dettagliate, vedere Avvio rapido: enumerazione dei dispositivi usati comunemente.

  1. Passare la stringa AQS recuperata a FindAllAsync. La chiamata recupera un oggetto DeviceInformationCollection .
  2. Scorrere l'insieme. Ogni iterazione ottiene un oggetto DeviceInformation .
  3. Ottiene il valore della proprietà DeviceInformation.Id . Il valore stringa è il percorso dell'istanza del dispositivo. Ad esempio, "\\\\?\USB#VID_045E&PID_078F#6&1b8ff026&0&5#{dee824ef-729b-4a0e-9c14-b7117d33a817}".
  4. Chiamare FromIdAsync passando la stringa di istanza del dispositivo e ottenere l'oggetto UsbDevice . È quindi possibile utilizzare l'oggetto UsbDevice per eseguire altre operazioni, ad esempio l'invio di un trasferimento di controllo. Al termine dell'uso dell'app tramite l'oggetto UsbDevice , l'app deve rilasciarla chiamando Close. Nota Quando l'app UWP viene sospesa, il dispositivo viene chiuso automaticamente. Per evitare di usare un handle non aggiornato per le operazioni future, l'app deve rilasciare il riferimento UsbDevice .
    private async void OpenDevice()
    {
        UInt32 vid = 0x045E;
        UInt32 pid = 0x0611;

        string aqs = UsbDevice.GetDeviceSelector(vid, pid);

        var myDevices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(aqs);

        try
        {
            usbDevice = await UsbDevice.FromIdAsync(myDevices[0].Id);
        }
        catch (Exception exception)
        {
            ShowStatus(exception.Message.ToString());
        }
        finally
        {
            ShowStatus("Opened device for communication.");
        }

    }

Trovare il dispositivo usando DeviceWatcher

In alternativa, è possibile enumerare i dispositivi in modo dinamico. L'app può quindi ricevere una notifica se i dispositivi vengono aggiunti o rimossi o se le proprietà del dispositivo cambiano. Per altre informazioni, vedere Come ottenere notifiche se i dispositivi vengono aggiunti, rimossi o modificati.

Un oggetto DeviceWatcher consente a un'app di rilevare dinamicamente i dispositivi man mano che vengono aggiunti e rimossi dal sistema.

  1. Creare un oggetto DeviceWatcher per rilevare quando il dispositivo viene aggiunto o rimosso dal sistema. È necessario creare l'oggetto chiamando CreateWatcher e specificando la stringa AQS.

  2. Implementare e registrare i gestori per gli eventi Added e Removed nell'oggetto DeviceWatcher . Questi gestori eventi vengono richiamati quando i dispositivi (con le stesse informazioni di identificazione) vengono aggiunti o rimossi dal sistema.

  3. Avviare e arrestare l'oggetto DeviceWatcher .

    L'app deve avviare l'oggetto DeviceWatcher chiamando Start in modo che possa avviare il rilevamento dei dispositivi quando vengono aggiunti o rimossi dal sistema. Viceversa, l'app deve arrestare DeviceWatcher chiamando Stop, quando non è più necessario rilevare i dispositivi. L'esempio include due pulsanti che consentono all'utente di avviare e arrestare DeviceWatcher.

Questo esempio di codice illustra come creare e avviare un watcher del dispositivo per cercare le istanze del dispositivo SuperMUTT.

void CreateSuperMuttDeviceWatcher(void)
{
    UInt32 vid = 0x045E;
    UInt32 pid = 0x0611;

    string aqs = UsbDevice.GetDeviceSelector(vid, pid);

    var superMuttWatcher = DeviceInformation.CreateWatcher(aqs);

    superMuttWatcher.Added += new TypedEventHandler<DeviceWatcher, DeviceInformation>
                              (this.OnDeviceAdded);

    superMuttWatcher.Removed += new TypedEventHandler<DeviceWatcher, DeviceInformationUpdate>
                            (this.OnDeviceRemoved);

    superMuttWatcher.Start();
 }

Aprire il dispositivo

Per aprire il dispositivo, l'app deve avviare un'operazione asincrona chiamando il metodo statico FromIdAsync e passando il percorso dell'istanza del dispositivo (ottenuto da DeviceInformation.Id). Tale risultato di tale operazione ottiene è un oggetto UsbDevice , che viene usato per la comunicazione futura con il dispositivo, ad esempio l'esecuzione di trasferimenti di dati.

Al termine dell'utilizzo dell'oggetto UsbDevice , è necessario rilasciarlo. Rilasciando l'oggetto, tutti i trasferimenti di dati in sospeso vengono annullati. Le routine di callback di completamento per tali operazioni vengono comunque richiamate con un errore annullato o l'operazione è stata completata.

Le app C++ devono rilasciare il riferimento usando la parola chiave delete . Le app C#/VB devono chiamare il metodo UsbDevice.Dispose . Le app JavaScript devono chiamare UsbDevice.Close.

FromIdAsync ha esito negativo se il dispositivo è in uso o non è stato trovato.